initial commit, day 10
This commit is contained in:
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
*.txt
|
||||
24
01a.py
Executable file
24
01a.py
Executable file
@@ -0,0 +1,24 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
with open('01a.txt') as f:
|
||||
text = f.read().strip()
|
||||
|
||||
lines = text.split('\n')
|
||||
|
||||
a = [0] * len(lines)
|
||||
b = a[:]
|
||||
|
||||
for i in range(len(lines)):
|
||||
spl = lines[i].split(' ', maxsplit=1)
|
||||
a[i] = int(spl[0].strip())
|
||||
b[i] = int(spl[1].strip())
|
||||
|
||||
a.sort()
|
||||
b.sort()
|
||||
|
||||
total = 0
|
||||
|
||||
for x, y in zip(a, b):
|
||||
total += abs(x - y)
|
||||
|
||||
print(total)
|
||||
40
01b.py
Executable file
40
01b.py
Executable file
@@ -0,0 +1,40 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
with open('01a.txt') as f:
|
||||
text = f.read().strip()
|
||||
|
||||
lines = text.split('\n')
|
||||
|
||||
a = [None] * len(lines)
|
||||
b = [None] * len(lines)
|
||||
|
||||
for i in range(len(lines)):
|
||||
spl = lines[i].split(' ', maxsplit=1)
|
||||
a[i] = int(spl[0].strip())
|
||||
b[i] = int(spl[1].strip())
|
||||
|
||||
a.sort()
|
||||
b.sort()
|
||||
|
||||
total = 0
|
||||
|
||||
# for x, y in zip(a, b):
|
||||
# total += abs(x - y)
|
||||
|
||||
# print(total)
|
||||
|
||||
i_a = 0
|
||||
i_b = 0
|
||||
|
||||
while i_a < len(lines) and i_b < len(lines):
|
||||
x_a = a[i_a]
|
||||
x_b = b[i_b]
|
||||
if x_a == x_b:
|
||||
total += x_b
|
||||
i_b += 1
|
||||
elif x_a < x_b:
|
||||
i_a += 1
|
||||
else:
|
||||
i_b += 1
|
||||
|
||||
print(total)
|
||||
19
02a.py
Executable file
19
02a.py
Executable file
@@ -0,0 +1,19 @@
|
||||
with open('02a.txt') as f:
|
||||
text = f.read().strip()
|
||||
|
||||
def make_report(line):
|
||||
return [int(x.strip()) for x in line.split()]
|
||||
|
||||
reports = [make_report(x) for x in text.split('\n')]
|
||||
|
||||
def test_report(report):
|
||||
if len(report) == 1:
|
||||
return True
|
||||
dir = 1 if report[1] - report[0] > 0 else -1
|
||||
for i in range(len(report)-1):
|
||||
diff = (report[i+1] - report[i]) * dir
|
||||
if diff < 1 or diff > 3:
|
||||
return False
|
||||
return True
|
||||
|
||||
print(sum(test_report(x) for x in reports))
|
||||
25
02b.py
Executable file
25
02b.py
Executable file
@@ -0,0 +1,25 @@
|
||||
with open('02a.txt') as f:
|
||||
text = f.read().strip()
|
||||
|
||||
def make_report(line):
|
||||
return [int(x.strip()) for x in line.split()]
|
||||
|
||||
reports = [make_report(x) for x in text.split('\n')]
|
||||
|
||||
def test_report(report):
|
||||
if len(report) == 1:
|
||||
return True
|
||||
dir = 1 if report[1] - report[0] > 0 else -1
|
||||
for i in range(len(report)-1):
|
||||
diff = (report[i+1] - report[i]) * dir
|
||||
if diff < 1 or diff > 3:
|
||||
return False
|
||||
return True
|
||||
|
||||
def test_sub_reports(report):
|
||||
for i in range(len(report)):
|
||||
if test_report(report[:i] + report[i+1:]):
|
||||
return True
|
||||
return False
|
||||
|
||||
print(sum(test_sub_reports(x) for x in reports))
|
||||
15
03a.py
Executable file
15
03a.py
Executable file
@@ -0,0 +1,15 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
import re
|
||||
|
||||
with open('03a.txt') as f:
|
||||
text = f.read()
|
||||
|
||||
reg = re.compile(r'mul\((?P<num1>[0-9]+),(?P<num2>[0-9]+)\)')
|
||||
|
||||
total = 0
|
||||
|
||||
for match in reg.finditer(text):
|
||||
total += int(match.group('num1')) * int(match.group('num2'))
|
||||
|
||||
print(total)
|
||||
24
03b.py
Executable file
24
03b.py
Executable file
@@ -0,0 +1,24 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
import re
|
||||
|
||||
with open('03a.txt') as f:
|
||||
text = f.read()
|
||||
|
||||
reg = re.compile(r'(?P<mul>mul\((?P<num1>[0-9]+),(?P<num2>[0-9]+)\))|(?P<do>do\(\))|(?P<dont>don\'t\(\))')
|
||||
|
||||
total = 0
|
||||
enabled = True
|
||||
|
||||
for match in reg.finditer(text):
|
||||
if match.group('do'):
|
||||
enabled = True
|
||||
elif match.group('dont'):
|
||||
enabled = False
|
||||
elif match.group('mul'):
|
||||
if enabled:
|
||||
total += int(match.group('num1')) * int(match.group('num2'))
|
||||
else:
|
||||
raise RuntimeError()
|
||||
|
||||
print(total)
|
||||
42
04a.py
Executable file
42
04a.py
Executable file
@@ -0,0 +1,42 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
with open('04a.txt') as f:
|
||||
lines = f.readlines()
|
||||
lines = [x.strip() for x in lines if x.strip()]
|
||||
count = 0
|
||||
|
||||
i_len = len(lines)
|
||||
j_len = len(lines[0])
|
||||
for i in range(i_len):
|
||||
for j in range(j_len):
|
||||
if lines[i][j] == 'X':
|
||||
UP = i >= 3
|
||||
DOWN = (i_len - i) >= 4
|
||||
LEFT = j >= 3
|
||||
RIGHT = (j_len - j) >= 4
|
||||
if UP:
|
||||
if lines[i-1][j] == 'M' and lines[i-2][j] == 'A' and lines[i-3][j] == 'S':
|
||||
count += 1
|
||||
if DOWN:
|
||||
if lines[i+1][j] == 'M' and lines[i+2][j] == 'A' and lines[i+3][j] == 'S':
|
||||
count += 1
|
||||
if LEFT:
|
||||
if lines[i][j-1] == 'M' and lines[i][j-2] == 'A' and lines[i][j-3] == 'S':
|
||||
count += 1
|
||||
if RIGHT:
|
||||
if lines[i][j+1] == 'M' and lines[i][j+2] == 'A' and lines[i][j+3] == 'S':
|
||||
count += 1
|
||||
if UP and LEFT:
|
||||
if lines[i-1][j-1] == 'M' and lines[i-2][j-2] == 'A' and lines[i-3][j-3] == 'S':
|
||||
count += 1
|
||||
if UP and RIGHT:
|
||||
if lines[i-1][j+1] == 'M' and lines[i-2][j+2] == 'A' and lines[i-3][j+3] == 'S':
|
||||
count += 1
|
||||
if DOWN and LEFT:
|
||||
if lines[i+1][j-1] == 'M' and lines[i+2][j-2] == 'A' and lines[i+3][j-3] == 'S':
|
||||
count += 1
|
||||
if DOWN and RIGHT:
|
||||
if lines[i+1][j+1] == 'M' and lines[i+2][j+2] == 'A' and lines[i+3][j+3] == 'S':
|
||||
count += 1
|
||||
|
||||
print(count)
|
||||
45
04a_alt.py
Executable file
45
04a_alt.py
Executable file
@@ -0,0 +1,45 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
import re
|
||||
|
||||
with open('04a.txt') as f:
|
||||
chars = ''.join(c for c in f.read() if c in ['X', 'M', 'A', 'S'])
|
||||
|
||||
UP = r'S.{139}A.{139}M.{139}X'
|
||||
DOWN = r'X.{139}M.{139}A.{139}S'
|
||||
LEFT = r'SAMX'
|
||||
RIGHT = r'XMAS'
|
||||
UPLEFT = r'S.{140}A.{140}M.{140}X'
|
||||
UPRIGHT = r'S.{138}A.{138}M.{138}X'
|
||||
DOWNLEFT = r'X.{138}M.{138}A.{138}S'
|
||||
DOWNRIGHT = r'X.{140}M.{140}A.{140}S'
|
||||
|
||||
ORED = '|'.join((UP, DOWN, LEFT, RIGHT, UPLEFT, UPRIGHT, DOWNLEFT, DOWNRIGHT))
|
||||
REG = re.compile(f'(?={ORED})')
|
||||
|
||||
def lookahead(s):
|
||||
return f'(?={s})'
|
||||
|
||||
up = next(re.finditer(UP, chars))
|
||||
print(up.pos)
|
||||
|
||||
_UP = len(re.findall(UP, chars))
|
||||
_DOWN = len(re.findall(DOWN, chars))
|
||||
_LEFT = len(re.findall(LEFT, chars))
|
||||
_RIGHT = len(re.findall(RIGHT, chars))
|
||||
_UPLEFT = len(re.findall(UPLEFT, chars))
|
||||
_UPRIGHT = len(re.findall(UPRIGHT, chars))
|
||||
_DOWNLEFT = len(re.findall(DOWNLEFT, chars))
|
||||
_DOWNRIGHT = len(re.findall(DOWNRIGHT, chars))
|
||||
|
||||
print(f'UP {_UP}')
|
||||
print(f'DOWN {_DOWN}')
|
||||
print(f'LEFT {_LEFT}')
|
||||
print(f'RIGHT {_RIGHT}')
|
||||
print(f'UPLEFT {_UPLEFT}')
|
||||
print(f'UPRIGHT {_UPRIGHT}')
|
||||
print(f'DOWNLEFT {_DOWNLEFT}')
|
||||
print(f'DOWNRIGHT {_DOWNRIGHT}')
|
||||
print(f'TOTAL {_UP + _DOWN + _LEFT + _RIGHT + _UPLEFT + _UPRIGHT + _DOWNLEFT + _DOWNRIGHT}')
|
||||
|
||||
print(len(REG.findall(chars)))
|
||||
42
04b.py
Executable file
42
04b.py
Executable file
@@ -0,0 +1,42 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
with open('04a.txt') as f:
|
||||
lines = f.readlines()
|
||||
lines = [x.strip() for x in lines if x.strip()]
|
||||
count = 0
|
||||
|
||||
i_len = len(lines)
|
||||
j_len = len(lines[0])
|
||||
for i in range(i_len):
|
||||
for j in range(j_len):
|
||||
if lines[i][j] == 'X':
|
||||
UP = i >= 3
|
||||
DOWN = (i_len - i) >= 4
|
||||
LEFT = j >= 3
|
||||
RIGHT = (j_len - j) >= 4
|
||||
if UP:
|
||||
if lines[i-1][j] == 'M' and lines[i-2][j] == 'A' and lines[i-3][j] == 'S':
|
||||
count += 1
|
||||
if DOWN:
|
||||
if lines[i+1][j] == 'M' and lines[i+2][j] == 'A' and lines[i+3][j] == 'S':
|
||||
count += 1
|
||||
if LEFT:
|
||||
if lines[i][j-1] == 'M' and lines[i][j-2] == 'A' and lines[i][j-3] == 'S':
|
||||
count += 1
|
||||
if RIGHT:
|
||||
if lines[i][j+1] == 'M' and lines[i][j+2] == 'A' and lines[i][j+3] == 'S':
|
||||
count += 1
|
||||
if UP and LEFT:
|
||||
if lines[i-1][j-1] == 'M' and lines[i-2][j-2] == 'A' and lines[i-3][j-3] == 'S':
|
||||
count += 1
|
||||
if UP and RIGHT:
|
||||
if lines[i-1][j+1] == 'M' and lines[i-2][j+2] == 'A' and lines[i-3][j+3] == 'S':
|
||||
count += 1
|
||||
if DOWN and LEFT:
|
||||
if lines[i+1][j-1] == 'M' and lines[i+2][j-2] == 'A' and lines[i+3][j-3] == 'S':
|
||||
count += 1
|
||||
if DOWN and RIGHT:
|
||||
if lines[i+1][j+1] == 'M' and lines[i+2][j+2] == 'A' and lines[i+3][j+3] == 'S':
|
||||
count += 1
|
||||
|
||||
print(count)
|
||||
27
04b_alt.py
Executable file
27
04b_alt.py
Executable file
@@ -0,0 +1,27 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
import re
|
||||
|
||||
with open('04a.txt') as f:
|
||||
text = f.read().strip().replace('\n', 'Z')
|
||||
|
||||
TOP = r'M[^Z]M.{139}A.{139}S[^Z]S'
|
||||
LEFT = r'M[^Z]S.{139}A.{139}M[^Z]S'
|
||||
BOTTOM = r'S[^Z]S.{139}A.{139}M[^Z]M'
|
||||
RIGHT = r'S[^Z]M.{139}A.{139}S[^Z]M'
|
||||
|
||||
T = re.compile(f'(?={TOP})')
|
||||
L = re.compile(f'(?={LEFT})')
|
||||
B = re.compile(f'(?={BOTTOM})')
|
||||
R = re.compile(f'(?={RIGHT})')
|
||||
|
||||
T_ = len(T.findall(text))
|
||||
L_ = len(L.findall(text))
|
||||
B_ = len(B.findall(text))
|
||||
R_ = len(R.findall(text))
|
||||
|
||||
print(f'TOP {T_}')
|
||||
print(f'LEFT {L_}')
|
||||
print(f'BOTTOM {B_}')
|
||||
print(f'RIGHT {R_}')
|
||||
print(f'TOTAL {T_ + L_ + B_ + R_}')
|
||||
129
10.cpp
Normal file
129
10.cpp
Normal file
@@ -0,0 +1,129 @@
|
||||
#include <iostream>
|
||||
#include <array>
|
||||
#include <cstdint>
|
||||
#include <fstream>
|
||||
#include <iterator>
|
||||
#include <unordered_set>
|
||||
|
||||
using map_t = std::array<std::array<uint8_t, 55>, 54>;
|
||||
|
||||
struct Point
|
||||
{
|
||||
int16_t Row;
|
||||
int16_t Col;
|
||||
};
|
||||
|
||||
using sols_t = std::unordered_set<uint32_t>;
|
||||
|
||||
void load_map(map_t& map, const char* filepath)
|
||||
{
|
||||
std::fstream in(filepath);
|
||||
std::istreambuf_iterator<char> iter(in);
|
||||
// std::istream_iterator<char> end;
|
||||
for (auto& row : map)
|
||||
{
|
||||
for (auto& cell : row)
|
||||
{
|
||||
cell = *(iter++);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void branch(const map_t& map, sols_t& terminals, char height, Point pos)
|
||||
{
|
||||
if (height == '9')
|
||||
terminals.emplace((pos.Row << 16) + pos.Col);
|
||||
else
|
||||
{
|
||||
if (pos.Row > 0 && map[pos.Row-1][pos.Col] == height+1)
|
||||
{
|
||||
branch(map, terminals, height+1, {pos.Row-1, pos.Col});
|
||||
}
|
||||
if (pos.Row < map.size()-1 && map[pos.Row+1][pos.Col] == height+1)
|
||||
{
|
||||
branch(map, terminals, height+1, {pos.Row+1, pos.Col});
|
||||
}
|
||||
if (pos.Col > 0 && map[pos.Row][pos.Col-1] == height+1)
|
||||
{
|
||||
branch(map, terminals, height+1, {pos.Row, pos.Col-1});
|
||||
}
|
||||
if (pos.Col < map[0].size()-2 && map[pos.Row][pos.Col+1] == height+1)
|
||||
{
|
||||
branch(map, terminals, height+1, {pos.Row, pos.Col+1});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int64_t branch2(const map_t& map, char height, Point pos)
|
||||
{
|
||||
if (height == '9')
|
||||
return 1;
|
||||
else
|
||||
{
|
||||
int64_t total = 0;
|
||||
if (pos.Row > 0 && map[pos.Row-1][pos.Col] == height+1)
|
||||
{
|
||||
total += branch2(map, height+1, {pos.Row-1, pos.Col});
|
||||
}
|
||||
if (pos.Row < map.size()-1 && map[pos.Row+1][pos.Col] == height+1)
|
||||
{
|
||||
total += branch2(map, height+1, {pos.Row+1, pos.Col});
|
||||
}
|
||||
if (pos.Col > 0 && map[pos.Row][pos.Col-1] == height+1)
|
||||
{
|
||||
total += branch2(map, height+1, {pos.Row, pos.Col-1});
|
||||
}
|
||||
if (pos.Col < map[0].size()-2 && map[pos.Row][pos.Col+1] == height+1)
|
||||
{
|
||||
total += branch2(map, height+1, {pos.Row, pos.Col+1});
|
||||
}
|
||||
return total;
|
||||
}
|
||||
}
|
||||
|
||||
void main1(const map_t& map)
|
||||
{
|
||||
int total = 0;
|
||||
// for (const auto& row : map)
|
||||
// for (const auto& cell : row)
|
||||
// std::cout << cell;
|
||||
// std::cout << std::endl;
|
||||
for (int16_t r = 0; r < map.size(); r++)
|
||||
{
|
||||
for (int16_t c = 0; c < map[r].size()-1; c++)
|
||||
{
|
||||
if (map[r][c] == '0')
|
||||
{
|
||||
sols_t terminals;
|
||||
branch(map, terminals, '0', {r, c});
|
||||
total += terminals.size();
|
||||
}
|
||||
}
|
||||
}
|
||||
std::cout << "Part1 " << total << std::endl;
|
||||
}
|
||||
|
||||
void main2(const map_t& map)
|
||||
{
|
||||
int64_t total = 0;
|
||||
for (int16_t r = 0; r < map.size(); r++)
|
||||
{
|
||||
for (int16_t c = 0; c < map[r].size()-1; c++)
|
||||
{
|
||||
if (map[r][c] == '0')
|
||||
{
|
||||
total += branch2(map, '0', {r, c});
|
||||
}
|
||||
}
|
||||
}
|
||||
std::cout << "Part2 " << total << std::endl;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
map_t map;
|
||||
load_map(map, "10.txt");
|
||||
main1(map);
|
||||
main2(map);
|
||||
return 0;
|
||||
}
|
||||
260
10_extraquick.cpp
Normal file
260
10_extraquick.cpp
Normal file
@@ -0,0 +1,260 @@
|
||||
#include <iostream>
|
||||
#include <array>
|
||||
#include <cstdint>
|
||||
#include <fstream>
|
||||
#include <iterator>
|
||||
#include <bitset>
|
||||
|
||||
#define WIDTH 54
|
||||
#define HEIGHT 54
|
||||
|
||||
using map_t = std::array<std::array<uint8_t, WIDTH>, HEIGHT>;
|
||||
|
||||
struct Point
|
||||
{
|
||||
int_fast8_t Row;
|
||||
int_fast8_t Col;
|
||||
};
|
||||
|
||||
struct sols_t
|
||||
{
|
||||
std::bitset<WIDTH*HEIGHT> bits;
|
||||
void emplace(Point point)
|
||||
{
|
||||
bits.set(point.Row * WIDTH + point.Col);
|
||||
}
|
||||
int size() const
|
||||
{
|
||||
return bits.count();
|
||||
}
|
||||
void clear()
|
||||
{
|
||||
bits.reset();
|
||||
}
|
||||
};
|
||||
|
||||
void load_map(map_t& map, const char* filepath)
|
||||
{
|
||||
std::fstream in(filepath);
|
||||
std::istreambuf_iterator iter(in);
|
||||
for (auto& row : map)
|
||||
{
|
||||
for (auto& cell : row)
|
||||
{
|
||||
cell = *(iter++) - '0';
|
||||
}
|
||||
iter++;
|
||||
}
|
||||
}
|
||||
|
||||
void quick_branch(const map_t& map, sols_t& terminals, Point init)
|
||||
{
|
||||
std::array<int_fast8_t, 9> path;
|
||||
int_fast8_t height = 0;
|
||||
path[0] = 0;
|
||||
Point pos = init;
|
||||
while (height >= 0)
|
||||
{
|
||||
// const auto& pos = path[height].pos;
|
||||
switch (path[height]++)
|
||||
{
|
||||
case 0:
|
||||
if (pos.Row > 0 && map[pos.Row-1][pos.Col] == height+1)
|
||||
{
|
||||
if (height == 8)
|
||||
terminals.emplace({static_cast<int_fast8_t>(pos.Row-1), pos.Col});
|
||||
else
|
||||
{
|
||||
path[++height] = 0;
|
||||
pos.Row--;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
if (pos.Col < WIDTH-1 && map[pos.Row][pos.Col+1] == height+1)
|
||||
{
|
||||
if (height == 8)
|
||||
terminals.emplace({pos.Row, static_cast<int_fast8_t>(pos.Col+1)});
|
||||
else
|
||||
{
|
||||
path[++height] = 0;
|
||||
pos.Col++;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
if (pos.Row < HEIGHT-1 && map[pos.Row+1][pos.Col] == height+1)
|
||||
{
|
||||
if (height == 8)
|
||||
terminals.emplace({static_cast<int_fast8_t>(pos.Row+1), pos.Col});
|
||||
else
|
||||
{
|
||||
path[++height] = 0;
|
||||
pos.Row++;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
if (pos.Col > 0 && map[pos.Row][pos.Col-1] == height+1)
|
||||
{
|
||||
if (height == 8)
|
||||
terminals.emplace({pos.Row, static_cast<int_fast8_t>(pos.Col-1)});
|
||||
else
|
||||
{
|
||||
path[++height] = 0;
|
||||
pos.Col--;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (height > 0)
|
||||
//remember that the previous path was already incremented
|
||||
switch (path[height-1])
|
||||
{
|
||||
case 1:
|
||||
pos.Row++;
|
||||
break;
|
||||
case 2:
|
||||
pos.Col--;
|
||||
break;
|
||||
case 3:
|
||||
pos.Row--;
|
||||
break;
|
||||
case 4:
|
||||
pos.Col++;
|
||||
break;
|
||||
}
|
||||
height--;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int quick_branch2(const map_t& map, Point init)
|
||||
{
|
||||
std::array<int_fast8_t, 9> path;
|
||||
int_fast8_t height = 0;
|
||||
path[0] = 0;
|
||||
int total = 0;
|
||||
Point pos = init;
|
||||
while (height >= 0)
|
||||
{
|
||||
switch (path[height]++)
|
||||
{
|
||||
case 0:
|
||||
if (pos.Row > 0 && map[pos.Row-1][pos.Col] == height+1)
|
||||
{
|
||||
if (height == 8)
|
||||
total++;
|
||||
else
|
||||
{
|
||||
path[++height] = 0;
|
||||
pos.Row--;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
if (pos.Col < WIDTH-1 && map[pos.Row][pos.Col+1] == height+1)
|
||||
{
|
||||
if (height == 8)
|
||||
total++;
|
||||
else
|
||||
{
|
||||
path[++height] = 0;
|
||||
pos.Col++;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
if (pos.Row < HEIGHT-1 && map[pos.Row+1][pos.Col] == height+1)
|
||||
{
|
||||
if (height == 8)
|
||||
total++;
|
||||
else
|
||||
{
|
||||
path[++height] = 0;
|
||||
pos.Row++;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
if (pos.Col > 0 && map[pos.Row][pos.Col-1] == height+1)
|
||||
{
|
||||
if (height == 8)
|
||||
total++;
|
||||
else
|
||||
{
|
||||
path[++height] = 0;
|
||||
pos.Col--;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (height > 0)
|
||||
//remember that the previous path was already incremented
|
||||
switch (path[height-1])
|
||||
{
|
||||
case 1:
|
||||
pos.Row++;
|
||||
break;
|
||||
case 2:
|
||||
pos.Col--;
|
||||
break;
|
||||
case 3:
|
||||
pos.Row--;
|
||||
break;
|
||||
case 4:
|
||||
pos.Col++;
|
||||
break;
|
||||
}
|
||||
height--;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return total;
|
||||
}
|
||||
|
||||
void main1(const map_t& map)
|
||||
{
|
||||
int total = 0;
|
||||
sols_t terminals;
|
||||
terminals.clear();
|
||||
for (int8_t r = 0; r < map.size(); r++)
|
||||
{
|
||||
for (int8_t c = 0; c < map[r].size(); c++)
|
||||
{
|
||||
if (map[r][c] == 0)
|
||||
{
|
||||
quick_branch(map, terminals, {r, c});
|
||||
total += terminals.size();
|
||||
terminals.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
std::cout << "Part1 " << total << std::endl;
|
||||
}
|
||||
|
||||
void main2(const map_t& map)
|
||||
{
|
||||
int32_t total = 0;
|
||||
for (int8_t r = 0; r < map.size(); r++)
|
||||
{
|
||||
for (int8_t c = 0; c < map[r].size(); c++)
|
||||
{
|
||||
if (map[r][c] == 0)
|
||||
{
|
||||
total += quick_branch2(map, {r, c});
|
||||
}
|
||||
}
|
||||
}
|
||||
std::cout << "Part2 " << total << std::endl;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
map_t map;
|
||||
load_map(map, "10.txt");
|
||||
main1(map);
|
||||
main2(map);
|
||||
return 0;
|
||||
}
|
||||
484
dotnet/.gitignore
vendored
Normal file
484
dotnet/.gitignore
vendored
Normal file
@@ -0,0 +1,484 @@
|
||||
## Ignore Visual Studio temporary files, build results, and
|
||||
## files generated by popular Visual Studio add-ons.
|
||||
##
|
||||
## Get latest from `dotnet new gitignore`
|
||||
|
||||
# dotenv files
|
||||
.env
|
||||
|
||||
# User-specific files
|
||||
*.rsuser
|
||||
*.suo
|
||||
*.user
|
||||
*.userosscache
|
||||
*.sln.docstates
|
||||
|
||||
# User-specific files (MonoDevelop/Xamarin Studio)
|
||||
*.userprefs
|
||||
|
||||
# Mono auto generated files
|
||||
mono_crash.*
|
||||
|
||||
# Build results
|
||||
[Dd]ebug/
|
||||
[Dd]ebugPublic/
|
||||
[Rr]elease/
|
||||
[Rr]eleases/
|
||||
x64/
|
||||
x86/
|
||||
[Ww][Ii][Nn]32/
|
||||
[Aa][Rr][Mm]/
|
||||
[Aa][Rr][Mm]64/
|
||||
bld/
|
||||
[Bb]in/
|
||||
[Oo]bj/
|
||||
[Ll]og/
|
||||
[Ll]ogs/
|
||||
|
||||
# Visual Studio 2015/2017 cache/options directory
|
||||
.vs/
|
||||
# Uncomment if you have tasks that create the project's static files in wwwroot
|
||||
#wwwroot/
|
||||
|
||||
# Visual Studio 2017 auto generated files
|
||||
Generated\ Files/
|
||||
|
||||
# MSTest test Results
|
||||
[Tt]est[Rr]esult*/
|
||||
[Bb]uild[Ll]og.*
|
||||
|
||||
# NUnit
|
||||
*.VisualState.xml
|
||||
TestResult.xml
|
||||
nunit-*.xml
|
||||
|
||||
# Build Results of an ATL Project
|
||||
[Dd]ebugPS/
|
||||
[Rr]eleasePS/
|
||||
dlldata.c
|
||||
|
||||
# Benchmark Results
|
||||
BenchmarkDotNet.Artifacts/
|
||||
|
||||
# .NET
|
||||
project.lock.json
|
||||
project.fragment.lock.json
|
||||
artifacts/
|
||||
|
||||
# Tye
|
||||
.tye/
|
||||
|
||||
# ASP.NET Scaffolding
|
||||
ScaffoldingReadMe.txt
|
||||
|
||||
# StyleCop
|
||||
StyleCopReport.xml
|
||||
|
||||
# Files built by Visual Studio
|
||||
*_i.c
|
||||
*_p.c
|
||||
*_h.h
|
||||
*.ilk
|
||||
*.meta
|
||||
*.obj
|
||||
*.iobj
|
||||
*.pch
|
||||
*.pdb
|
||||
*.ipdb
|
||||
*.pgc
|
||||
*.pgd
|
||||
*.rsp
|
||||
*.sbr
|
||||
*.tlb
|
||||
*.tli
|
||||
*.tlh
|
||||
*.tmp
|
||||
*.tmp_proj
|
||||
*_wpftmp.csproj
|
||||
*.log
|
||||
*.tlog
|
||||
*.vspscc
|
||||
*.vssscc
|
||||
.builds
|
||||
*.pidb
|
||||
*.svclog
|
||||
*.scc
|
||||
|
||||
# Chutzpah Test files
|
||||
_Chutzpah*
|
||||
|
||||
# Visual C++ cache files
|
||||
ipch/
|
||||
*.aps
|
||||
*.ncb
|
||||
*.opendb
|
||||
*.opensdf
|
||||
*.sdf
|
||||
*.cachefile
|
||||
*.VC.db
|
||||
*.VC.VC.opendb
|
||||
|
||||
# Visual Studio profiler
|
||||
*.psess
|
||||
*.vsp
|
||||
*.vspx
|
||||
*.sap
|
||||
|
||||
# Visual Studio Trace Files
|
||||
*.e2e
|
||||
|
||||
# TFS 2012 Local Workspace
|
||||
$tf/
|
||||
|
||||
# Guidance Automation Toolkit
|
||||
*.gpState
|
||||
|
||||
# ReSharper is a .NET coding add-in
|
||||
_ReSharper*/
|
||||
*.[Rr]e[Ss]harper
|
||||
*.DotSettings.user
|
||||
|
||||
# TeamCity is a build add-in
|
||||
_TeamCity*
|
||||
|
||||
# DotCover is a Code Coverage Tool
|
||||
*.dotCover
|
||||
|
||||
# AxoCover is a Code Coverage Tool
|
||||
.axoCover/*
|
||||
!.axoCover/settings.json
|
||||
|
||||
# Coverlet is a free, cross platform Code Coverage Tool
|
||||
coverage*.json
|
||||
coverage*.xml
|
||||
coverage*.info
|
||||
|
||||
# Visual Studio code coverage results
|
||||
*.coverage
|
||||
*.coveragexml
|
||||
|
||||
# NCrunch
|
||||
_NCrunch_*
|
||||
.*crunch*.local.xml
|
||||
nCrunchTemp_*
|
||||
|
||||
# MightyMoose
|
||||
*.mm.*
|
||||
AutoTest.Net/
|
||||
|
||||
# Web workbench (sass)
|
||||
.sass-cache/
|
||||
|
||||
# Installshield output folder
|
||||
[Ee]xpress/
|
||||
|
||||
# DocProject is a documentation generator add-in
|
||||
DocProject/buildhelp/
|
||||
DocProject/Help/*.HxT
|
||||
DocProject/Help/*.HxC
|
||||
DocProject/Help/*.hhc
|
||||
DocProject/Help/*.hhk
|
||||
DocProject/Help/*.hhp
|
||||
DocProject/Help/Html2
|
||||
DocProject/Help/html
|
||||
|
||||
# Click-Once directory
|
||||
publish/
|
||||
|
||||
# Publish Web Output
|
||||
*.[Pp]ublish.xml
|
||||
*.azurePubxml
|
||||
# Note: Comment the next line if you want to checkin your web deploy settings,
|
||||
# but database connection strings (with potential passwords) will be unencrypted
|
||||
*.pubxml
|
||||
*.publishproj
|
||||
|
||||
# Microsoft Azure Web App publish settings. Comment the next line if you want to
|
||||
# checkin your Azure Web App publish settings, but sensitive information contained
|
||||
# in these scripts will be unencrypted
|
||||
PublishScripts/
|
||||
|
||||
# NuGet Packages
|
||||
*.nupkg
|
||||
# NuGet Symbol Packages
|
||||
*.snupkg
|
||||
# The packages folder can be ignored because of Package Restore
|
||||
**/[Pp]ackages/*
|
||||
# except build/, which is used as an MSBuild target.
|
||||
!**/[Pp]ackages/build/
|
||||
# Uncomment if necessary however generally it will be regenerated when needed
|
||||
#!**/[Pp]ackages/repositories.config
|
||||
# NuGet v3's project.json files produces more ignorable files
|
||||
*.nuget.props
|
||||
*.nuget.targets
|
||||
|
||||
# Microsoft Azure Build Output
|
||||
csx/
|
||||
*.build.csdef
|
||||
|
||||
# Microsoft Azure Emulator
|
||||
ecf/
|
||||
rcf/
|
||||
|
||||
# Windows Store app package directories and files
|
||||
AppPackages/
|
||||
BundleArtifacts/
|
||||
Package.StoreAssociation.xml
|
||||
_pkginfo.txt
|
||||
*.appx
|
||||
*.appxbundle
|
||||
*.appxupload
|
||||
|
||||
# Visual Studio cache files
|
||||
# files ending in .cache can be ignored
|
||||
*.[Cc]ache
|
||||
# but keep track of directories ending in .cache
|
||||
!?*.[Cc]ache/
|
||||
|
||||
# Others
|
||||
ClientBin/
|
||||
~$*
|
||||
*~
|
||||
*.dbmdl
|
||||
*.dbproj.schemaview
|
||||
*.jfm
|
||||
*.pfx
|
||||
*.publishsettings
|
||||
orleans.codegen.cs
|
||||
|
||||
# Including strong name files can present a security risk
|
||||
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
|
||||
#*.snk
|
||||
|
||||
# Since there are multiple workflows, uncomment next line to ignore bower_components
|
||||
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
|
||||
#bower_components/
|
||||
|
||||
# RIA/Silverlight projects
|
||||
Generated_Code/
|
||||
|
||||
# Backup & report files from converting an old project file
|
||||
# to a newer Visual Studio version. Backup files are not needed,
|
||||
# because we have git ;-)
|
||||
_UpgradeReport_Files/
|
||||
Backup*/
|
||||
UpgradeLog*.XML
|
||||
UpgradeLog*.htm
|
||||
ServiceFabricBackup/
|
||||
*.rptproj.bak
|
||||
|
||||
# SQL Server files
|
||||
*.mdf
|
||||
*.ldf
|
||||
*.ndf
|
||||
|
||||
# Business Intelligence projects
|
||||
*.rdl.data
|
||||
*.bim.layout
|
||||
*.bim_*.settings
|
||||
*.rptproj.rsuser
|
||||
*- [Bb]ackup.rdl
|
||||
*- [Bb]ackup ([0-9]).rdl
|
||||
*- [Bb]ackup ([0-9][0-9]).rdl
|
||||
|
||||
# Microsoft Fakes
|
||||
FakesAssemblies/
|
||||
|
||||
# GhostDoc plugin setting file
|
||||
*.GhostDoc.xml
|
||||
|
||||
# Node.js Tools for Visual Studio
|
||||
.ntvs_analysis.dat
|
||||
node_modules/
|
||||
|
||||
# Visual Studio 6 build log
|
||||
*.plg
|
||||
|
||||
# Visual Studio 6 workspace options file
|
||||
*.opt
|
||||
|
||||
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
|
||||
*.vbw
|
||||
|
||||
# Visual Studio 6 auto-generated project file (contains which files were open etc.)
|
||||
*.vbp
|
||||
|
||||
# Visual Studio 6 workspace and project file (working project files containing files to include in project)
|
||||
*.dsw
|
||||
*.dsp
|
||||
|
||||
# Visual Studio 6 technical files
|
||||
*.ncb
|
||||
*.aps
|
||||
|
||||
# Visual Studio LightSwitch build output
|
||||
**/*.HTMLClient/GeneratedArtifacts
|
||||
**/*.DesktopClient/GeneratedArtifacts
|
||||
**/*.DesktopClient/ModelManifest.xml
|
||||
**/*.Server/GeneratedArtifacts
|
||||
**/*.Server/ModelManifest.xml
|
||||
_Pvt_Extensions
|
||||
|
||||
# Paket dependency manager
|
||||
.paket/paket.exe
|
||||
paket-files/
|
||||
|
||||
# FAKE - F# Make
|
||||
.fake/
|
||||
|
||||
# CodeRush personal settings
|
||||
.cr/personal
|
||||
|
||||
# Python Tools for Visual Studio (PTVS)
|
||||
__pycache__/
|
||||
*.pyc
|
||||
|
||||
# Cake - Uncomment if you are using it
|
||||
# tools/**
|
||||
# !tools/packages.config
|
||||
|
||||
# Tabs Studio
|
||||
*.tss
|
||||
|
||||
# Telerik's JustMock configuration file
|
||||
*.jmconfig
|
||||
|
||||
# BizTalk build output
|
||||
*.btp.cs
|
||||
*.btm.cs
|
||||
*.odx.cs
|
||||
*.xsd.cs
|
||||
|
||||
# OpenCover UI analysis results
|
||||
OpenCover/
|
||||
|
||||
# Azure Stream Analytics local run output
|
||||
ASALocalRun/
|
||||
|
||||
# MSBuild Binary and Structured Log
|
||||
*.binlog
|
||||
|
||||
# NVidia Nsight GPU debugger configuration file
|
||||
*.nvuser
|
||||
|
||||
# MFractors (Xamarin productivity tool) working folder
|
||||
.mfractor/
|
||||
|
||||
# Local History for Visual Studio
|
||||
.localhistory/
|
||||
|
||||
# Visual Studio History (VSHistory) files
|
||||
.vshistory/
|
||||
|
||||
# BeatPulse healthcheck temp database
|
||||
healthchecksdb
|
||||
|
||||
# Backup folder for Package Reference Convert tool in Visual Studio 2017
|
||||
MigrationBackup/
|
||||
|
||||
# Ionide (cross platform F# VS Code tools) working folder
|
||||
.ionide/
|
||||
|
||||
# Fody - auto-generated XML schema
|
||||
FodyWeavers.xsd
|
||||
|
||||
# VS Code files for those working on multiple tools
|
||||
.vscode/*
|
||||
!.vscode/settings.json
|
||||
!.vscode/tasks.json
|
||||
!.vscode/launch.json
|
||||
!.vscode/extensions.json
|
||||
*.code-workspace
|
||||
|
||||
# Local History for Visual Studio Code
|
||||
.history/
|
||||
|
||||
# Windows Installer files from build outputs
|
||||
*.cab
|
||||
*.msi
|
||||
*.msix
|
||||
*.msm
|
||||
*.msp
|
||||
|
||||
# JetBrains Rider
|
||||
*.sln.iml
|
||||
.idea
|
||||
|
||||
##
|
||||
## Visual studio for Mac
|
||||
##
|
||||
|
||||
|
||||
# globs
|
||||
Makefile.in
|
||||
*.userprefs
|
||||
*.usertasks
|
||||
config.make
|
||||
config.status
|
||||
aclocal.m4
|
||||
install-sh
|
||||
autom4te.cache/
|
||||
*.tar.gz
|
||||
tarballs/
|
||||
test-results/
|
||||
|
||||
# Mac bundle stuff
|
||||
*.dmg
|
||||
*.app
|
||||
|
||||
# content below from: https://github.com/github/gitignore/blob/master/Global/macOS.gitignore
|
||||
# General
|
||||
.DS_Store
|
||||
.AppleDouble
|
||||
.LSOverride
|
||||
|
||||
# Icon must end with two \r
|
||||
Icon
|
||||
|
||||
|
||||
# Thumbnails
|
||||
._*
|
||||
|
||||
# Files that might appear in the root of a volume
|
||||
.DocumentRevisions-V100
|
||||
.fseventsd
|
||||
.Spotlight-V100
|
||||
.TemporaryItems
|
||||
.Trashes
|
||||
.VolumeIcon.icns
|
||||
.com.apple.timemachine.donotpresent
|
||||
|
||||
# Directories potentially created on remote AFP share
|
||||
.AppleDB
|
||||
.AppleDesktop
|
||||
Network Trash Folder
|
||||
Temporary Items
|
||||
.apdisk
|
||||
|
||||
# content below from: https://github.com/github/gitignore/blob/master/Global/Windows.gitignore
|
||||
# Windows thumbnail cache files
|
||||
Thumbs.db
|
||||
ehthumbs.db
|
||||
ehthumbs_vista.db
|
||||
|
||||
# Dump file
|
||||
*.stackdump
|
||||
|
||||
# Folder config file
|
||||
[Dd]esktop.ini
|
||||
|
||||
# Recycle Bin used on file shares
|
||||
$RECYCLE.BIN/
|
||||
|
||||
# Windows Installer files
|
||||
*.cab
|
||||
*.msi
|
||||
*.msix
|
||||
*.msm
|
||||
*.msp
|
||||
|
||||
# Windows shortcuts
|
||||
*.lnk
|
||||
|
||||
# Vim temporary swap files
|
||||
*.swp
|
||||
167
dotnet/05/05a.cs
Normal file
167
dotnet/05/05a.cs
Normal file
@@ -0,0 +1,167 @@
|
||||
void Main1()
|
||||
{
|
||||
var lines = File.ReadAllLines(Path.Join("..", "..", "05a.txt")).Select(l => l.Trim()).ToList();
|
||||
if (lines.Last() == "")
|
||||
lines.RemoveAt(lines.Count - 1);
|
||||
|
||||
List<Rule> rules = new();
|
||||
foreach (var line in lines.TakeWhile(l => !string.IsNullOrWhiteSpace(l)))
|
||||
{
|
||||
var parts = line.Split('|');
|
||||
rules.Add(new(
|
||||
int.Parse(parts[0]),
|
||||
int.Parse(parts[1])
|
||||
));
|
||||
}
|
||||
|
||||
List<Collection> collections = new();
|
||||
foreach (var line in lines.SkipWhile(l => !string.IsNullOrWhiteSpace(l)).Skip(1))
|
||||
{
|
||||
var parts = line.Split(',').Select(int.Parse);
|
||||
collections.Add(new(parts));
|
||||
}
|
||||
|
||||
int total = 0;
|
||||
foreach (var collection in collections.Where(c => rules.All(r => c.TestRule(r))))
|
||||
{
|
||||
total += collection.Middle();
|
||||
}
|
||||
|
||||
Console.WriteLine(total);
|
||||
}
|
||||
|
||||
void Main2()
|
||||
{
|
||||
var lines = File.ReadAllLines(Path.Join("..", "..", "05a.txt")).Select(l => l.Trim()).ToList();
|
||||
if (lines.Last() == "")
|
||||
lines.RemoveAt(lines.Count - 1);
|
||||
|
||||
List<Rule> rules = new();
|
||||
RuleList rulelist = new();
|
||||
foreach (var line in lines.TakeWhile(l => !string.IsNullOrWhiteSpace(l)))
|
||||
{
|
||||
var parts = line.Split('|');
|
||||
Rule rule = new(
|
||||
int.Parse(parts[0]),
|
||||
int.Parse(parts[1])
|
||||
);
|
||||
rulelist.Add(rule);
|
||||
rules.Add(rule);
|
||||
}
|
||||
|
||||
List<Collection> collections = new();
|
||||
foreach (var line in lines.SkipWhile(l => !string.IsNullOrWhiteSpace(l)).Skip(1))
|
||||
{
|
||||
var parts = line.Split(',').Select(int.Parse);
|
||||
collections.Add(new(parts));
|
||||
}
|
||||
|
||||
var total = 0;
|
||||
var count = 0;
|
||||
foreach (var collection in collections)
|
||||
{
|
||||
var r = collection.Pairs()
|
||||
.Select(p => rulelist.ExtractRule(p.Item1, p.Item2))
|
||||
.Where(r => r is not null)
|
||||
.Select(r => (Rule)r)
|
||||
.ToList();
|
||||
if (!rules.All(collection.TestRule))
|
||||
{
|
||||
collection.Pages.Sort(rulelist.Compare);
|
||||
total += collection.Pages[collection.Pages.Count / 2];
|
||||
count++;
|
||||
}
|
||||
}
|
||||
Console.WriteLine($"Collections: {collections.Count}");
|
||||
Console.WriteLine($"With errors: {count}");
|
||||
Console.WriteLine($"Solution: {total}");
|
||||
}
|
||||
|
||||
Main2();
|
||||
|
||||
record struct Rule(int First, int Second);
|
||||
class RuleList
|
||||
{
|
||||
Dictionary<(int,int), bool> Rules = new();
|
||||
public RuleList()
|
||||
{
|
||||
|
||||
}
|
||||
public void Add(Rule rule)
|
||||
{
|
||||
bool ordered = rule.First < rule.Second;
|
||||
var pair = ordered
|
||||
? (rule.First, rule.Second)
|
||||
: (rule.Second, rule.First);
|
||||
Rules.Add(pair, ordered);
|
||||
}
|
||||
//true if correct order, null if no rule
|
||||
public bool? Check(int a, int b)
|
||||
{
|
||||
bool ordered = a < b;
|
||||
var pair = ordered
|
||||
? (a, b)
|
||||
: (b, a);
|
||||
bool result;
|
||||
return Rules.TryGetValue(pair, out result) ? result ^ ordered : null;
|
||||
}
|
||||
public int Compare(int a, int b)
|
||||
{
|
||||
var check = Check(a, b);
|
||||
if (check is bool _check)
|
||||
return _check ? -1 : 1;
|
||||
return 0;
|
||||
}
|
||||
public Rule? ExtractRule(int a, int b)
|
||||
{
|
||||
var check = Check(a, b);
|
||||
if (check is bool _check)
|
||||
return _check ? new(a, b) : new(b, a);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
class Collection
|
||||
{
|
||||
public readonly List<int> Pages;
|
||||
public Collection(IEnumerable<int> pages)
|
||||
{
|
||||
Pages = pages.ToList();
|
||||
}
|
||||
public bool TestRule(Rule rule)
|
||||
{
|
||||
bool foundFirst = false;
|
||||
bool foundSecond = false;
|
||||
foreach (var page in Pages)
|
||||
{
|
||||
if (page == rule.First)
|
||||
{
|
||||
if (foundSecond)
|
||||
return false;
|
||||
foundFirst = true;
|
||||
}
|
||||
if (page == rule.Second)
|
||||
{
|
||||
if (foundFirst)
|
||||
return true;
|
||||
foundSecond = true;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
public int Middle()
|
||||
{
|
||||
return Pages[Pages.Count / 2];
|
||||
}
|
||||
public List<(int,int)> Pairs()
|
||||
{
|
||||
List<(int,int)> pairs = new();
|
||||
for (int i = 0; i < Pages.Count-1; i++)
|
||||
{
|
||||
for (int j = i+1; j < Pages.Count; j++)
|
||||
{
|
||||
pairs.Add((Pages[i], Pages[j]));
|
||||
}
|
||||
}
|
||||
return pairs;
|
||||
}
|
||||
}
|
||||
238
dotnet/06/06.cs
Normal file
238
dotnet/06/06.cs
Normal file
@@ -0,0 +1,238 @@
|
||||
void Main1()
|
||||
{
|
||||
(var map, var pos) = LoadMap(Path.Join("..", "..", "06a.txt"));
|
||||
Guard guard = new(pos, Direction.North);
|
||||
HashSet<(int,int)> visited = new();
|
||||
while (map.InBounds(guard.position))
|
||||
{
|
||||
var next = Next(guard);
|
||||
if (map.Check(next.position))
|
||||
{
|
||||
guard = new(guard.position, guard.direction.Turn());
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
visited.Add(guard.position);
|
||||
guard = next;
|
||||
}
|
||||
}
|
||||
Console.WriteLine(visited.Count());
|
||||
}
|
||||
|
||||
void Main2()
|
||||
{
|
||||
(var map, var pos) = LoadMap(Path.Join("..", "..", "06a.txt"));
|
||||
Guard guard = new(pos, Direction.North);
|
||||
// for (int i = 0; i < 4; i++)
|
||||
// {
|
||||
// foreach (var obs in map.Obstacles)
|
||||
// {
|
||||
// var row = map.GetRow(obs.Item1 + 1).Where(c => c > obs.Item2);
|
||||
// foreach (var candidate in row)
|
||||
// {
|
||||
// var col = map.GetColumn(candidate - 1).Where(r => r > candidate);
|
||||
// foreach (var third in col)
|
||||
// {
|
||||
// var idea = (third - 1, obs.Item2 - 1);
|
||||
// if (!map.Check(idea))
|
||||
// map.Ideas.Add(idea);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// map = map.Rotated();
|
||||
// }
|
||||
// Console.WriteLine($"Ideas {map.Ideas.Count()}");
|
||||
int count = 0;
|
||||
// foreach (var idea in map.Ideas)
|
||||
// {
|
||||
// Guard guard = new(pos, Direction.North);
|
||||
// // the 5th time the guard hits the obstacle, he must have hit twice from the same side
|
||||
// int hits = 0;
|
||||
// while (map.InBounds(guard.position))
|
||||
// {
|
||||
// var next = Next(guard);
|
||||
// if (next.position == idea)
|
||||
// {
|
||||
// hits++;
|
||||
// if (hits >= 5)
|
||||
// {
|
||||
// count++;
|
||||
// break;
|
||||
// }
|
||||
// guard = new(guard.position, guard.direction.Turn());
|
||||
// }
|
||||
// else if (map.Check(next.position))
|
||||
// {
|
||||
// guard = new(guard.position, guard.direction.Turn());
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// guard = next;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
HashSet<(int,int)> visited = new();
|
||||
int ideaIndex = 0;
|
||||
while (map.InBounds(guard.position))
|
||||
{
|
||||
ideaIndex++;
|
||||
var next = Next(guard);
|
||||
if (map.Check(next.position))
|
||||
{
|
||||
guard = new(guard.position, guard.direction.Turn());
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
visited.Add(guard.position);
|
||||
if (!visited.Contains(next.position) && TestIdea(next.position, guard, map))
|
||||
count++;
|
||||
// Console.WriteLine($"Idea {ideaIndex}");
|
||||
guard = next;
|
||||
}
|
||||
}
|
||||
Console.WriteLine($"Solution {count}");
|
||||
}
|
||||
|
||||
// Main1();
|
||||
Main2();
|
||||
|
||||
(Map,(int,int)) LoadMap(string filename)
|
||||
{
|
||||
var lines = File.ReadAllLines(filename)
|
||||
.Where(s => !string.IsNullOrWhiteSpace(s))
|
||||
.ToList();
|
||||
var guard = (-1,-1);
|
||||
Map map = new();
|
||||
for (int i = 0; i < lines.Count(); i++)
|
||||
{
|
||||
for (int j = 0; j < lines[i].Count(); j++)
|
||||
{
|
||||
if (lines[i][j] == '#')
|
||||
map.Add((i, j));
|
||||
else if (lines[i][j] == '^')
|
||||
guard = (i, j);
|
||||
}
|
||||
}
|
||||
map.XBound = lines[0].Count();
|
||||
map.YBound = lines.Count();
|
||||
return (map, guard);
|
||||
}
|
||||
|
||||
bool TestIdea((int,int) idea, Guard guard, Map map)
|
||||
{
|
||||
HashSet<Guard> history = new();
|
||||
while (map.InBounds(guard.position))
|
||||
{
|
||||
if (history.Contains(guard))
|
||||
return true;
|
||||
history.Add(guard);
|
||||
var next = Next(guard);
|
||||
if (map.Check(next.position) || next.position == idea)
|
||||
{
|
||||
guard = new(guard.position, guard.direction.Turn());
|
||||
}
|
||||
else
|
||||
{
|
||||
guard = next;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//next position IF NO OBSTACLE
|
||||
Guard Next(Guard guard)
|
||||
{
|
||||
var pos = guard.position;
|
||||
return new(guard.direction switch
|
||||
{
|
||||
Direction.North => (pos.Item1-1, pos.Item2),
|
||||
Direction.East => (pos.Item1, pos.Item2+1),
|
||||
Direction.South => (pos.Item1+1, pos.Item2),
|
||||
Direction.West => (pos.Item1, pos.Item2-1),
|
||||
_ => throw new Exception(),
|
||||
}, guard.direction);
|
||||
}
|
||||
|
||||
class Map
|
||||
{
|
||||
public HashSet<(int,int)> Obstacles = new();
|
||||
//1 greater than largest value
|
||||
public int XBound = 0;
|
||||
public int YBound = 0;
|
||||
public HashSet<(int,int)> Ideas = new();
|
||||
public Map()
|
||||
{
|
||||
|
||||
}
|
||||
public void Add((int,int) obstacle)
|
||||
{
|
||||
Obstacles.Add(obstacle);
|
||||
}
|
||||
public bool Check((int,int) pos)
|
||||
{
|
||||
return Obstacles.Contains(pos);
|
||||
}
|
||||
public bool InBounds((int,int) pos)
|
||||
{
|
||||
return pos.Item1 >= 0 && pos.Item2 >= 0
|
||||
&& pos.Item1 < XBound && pos.Item2 < YBound;
|
||||
}
|
||||
//get list of columns with an obstacle in this row
|
||||
public List<int> GetRow(int row)
|
||||
{
|
||||
List<int> items = [];
|
||||
foreach (var pos in Obstacles)
|
||||
{
|
||||
if (pos.Item1 == row)
|
||||
items.Add(pos.Item2);
|
||||
}
|
||||
items.Sort();
|
||||
return items;
|
||||
}
|
||||
//get list of rows with an obstacle in this column
|
||||
public List<int> GetColumn(int column)
|
||||
{
|
||||
List<int> items = [];
|
||||
foreach (var pos in Obstacles)
|
||||
{
|
||||
if (pos.Item2 == column)
|
||||
items.Add(pos.Item1);
|
||||
}
|
||||
items.Sort();
|
||||
return items;
|
||||
}
|
||||
//counterclockwise rotation
|
||||
public Map Rotated()
|
||||
{
|
||||
(int,int) rotate((int,int) o) => (o.Item2, XBound - o.Item1);
|
||||
Map newmap = new();
|
||||
newmap.Obstacles = new(Obstacles.Select(rotate));
|
||||
newmap.Ideas = new(Ideas.Select(rotate));
|
||||
newmap.XBound = YBound;
|
||||
newmap.YBound = XBound;
|
||||
return newmap;
|
||||
}
|
||||
}
|
||||
|
||||
enum Direction
|
||||
{
|
||||
North,
|
||||
East,
|
||||
South,
|
||||
West,
|
||||
}
|
||||
readonly record struct Guard((int,int) position, Direction direction);
|
||||
|
||||
static class Extensions
|
||||
{
|
||||
public static Direction Turn(this Direction direction)
|
||||
{
|
||||
return direction switch
|
||||
{
|
||||
Direction.West => Direction.North,
|
||||
Direction d => d + 1,
|
||||
};
|
||||
}
|
||||
}
|
||||
263
dotnet/07/07a.cs
Normal file
263
dotnet/07/07a.cs
Normal file
@@ -0,0 +1,263 @@
|
||||
void Main1()
|
||||
{
|
||||
var eqs = LoadEqs(Path.Join("..", "..", "07a.txt"));
|
||||
long total = 0;
|
||||
foreach (var eq in eqs)
|
||||
{
|
||||
if (eq.Test1())
|
||||
{
|
||||
total += eq.Target;
|
||||
}
|
||||
}
|
||||
Console.WriteLine($"Solution {total}");
|
||||
}
|
||||
|
||||
void Main2()
|
||||
{
|
||||
var eqs = LoadEqs(Path.Join("..", "..", "07a.txt"));
|
||||
long total = 0;
|
||||
foreach (var eq in eqs)
|
||||
{
|
||||
if (eq.Test2())
|
||||
{
|
||||
total += eq.Target;
|
||||
}
|
||||
}
|
||||
Console.WriteLine($"Solution1 {total}");
|
||||
}
|
||||
|
||||
void Main2_take2()
|
||||
{
|
||||
var eqs = LoadEqs(Path.Join("..", "..", "07a.txt"));
|
||||
long total = 0;
|
||||
foreach (var eq in eqs)
|
||||
{
|
||||
if (eq.Test3())
|
||||
{
|
||||
total += eq.Target;
|
||||
}
|
||||
}
|
||||
Console.WriteLine($"Solution (exp) {total}");
|
||||
}
|
||||
|
||||
void Main2_take3()
|
||||
{
|
||||
var eqs = LoadEqs(Path.Join("..", "..", "07a.txt"));
|
||||
long total = 0;
|
||||
foreach (var eq in eqs)
|
||||
{
|
||||
if (eq.Test4())
|
||||
{
|
||||
total += eq.Target;
|
||||
}
|
||||
}
|
||||
Console.WriteLine($"Solution {total}");
|
||||
}
|
||||
|
||||
void Main2_take2and3()
|
||||
{
|
||||
var eqs = LoadEqs(Path.Join("..", "..", "07a.txt"));
|
||||
long total = 0;
|
||||
foreach (var eq in eqs)
|
||||
{
|
||||
var t3 = eq.Test3();
|
||||
var t4 = eq.Test4();
|
||||
if (t3 != t4)
|
||||
{
|
||||
Console.WriteLine((t4 ? "Pass " : "Fail ") + eq.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Main1();
|
||||
Main2();
|
||||
// Main2_take2();
|
||||
// Main2_take3();
|
||||
// Main2_take2and3();
|
||||
|
||||
List<EQ> LoadEqs(string filepath)
|
||||
{
|
||||
var lines = File.ReadAllLines(filepath).ToList();
|
||||
if (string.IsNullOrWhiteSpace(lines.Last()))
|
||||
lines.RemoveAt(lines.Count()-1);
|
||||
List<EQ> eqs = new();
|
||||
foreach (var line in lines)
|
||||
{
|
||||
var parts = line.Split(':');
|
||||
eqs.Add(new(
|
||||
long.Parse(parts[0]),
|
||||
parts[1].Trim().Split(' ').Select(long.Parse)
|
||||
));
|
||||
}
|
||||
return eqs;
|
||||
}
|
||||
|
||||
class EQ
|
||||
{
|
||||
public long Target;
|
||||
public List<long> Terms;
|
||||
public EQ(long target, IEnumerable<long> terms)
|
||||
{
|
||||
Target = target;
|
||||
Terms = terms.ToList();
|
||||
}
|
||||
public override string ToString()
|
||||
{
|
||||
return $"{Target}: {string.Join(' ', Terms)}";
|
||||
}
|
||||
public bool Test1()
|
||||
{
|
||||
return InnerTest1(Target, Terms.First(), Terms.Skip(1));
|
||||
}
|
||||
private static bool InnerTest1(long target, long current, IEnumerable<long> terms)
|
||||
{
|
||||
if (current > target)
|
||||
return false;
|
||||
var term = terms.Cast<long?>().FirstOrDefault();
|
||||
if (term is long _term)
|
||||
{
|
||||
return InnerTest1(target, current + _term, terms.Skip(1))
|
||||
|| InnerTest1(target, current * _term, terms.Skip(1));
|
||||
}
|
||||
else
|
||||
{
|
||||
return target == current;
|
||||
}
|
||||
}
|
||||
public bool Test2()
|
||||
{
|
||||
return InnerTest2(Target, Terms.First(), Terms, 1);
|
||||
}
|
||||
private static bool InnerTest2(long target, long current, IList<long> terms, int index)
|
||||
{
|
||||
if (current > target)
|
||||
return false;
|
||||
if (index >= terms.Count())
|
||||
return target == current;
|
||||
var term = terms[index];
|
||||
return InnerTest2(target, current + term, terms, index + 1)
|
||||
|| InnerTest2(target, current * term, terms, index + 1)
|
||||
|| InnerTest2(target, Concat(current, term), terms, index + 1);
|
||||
}
|
||||
public bool Test3()
|
||||
{
|
||||
return InnerTest3(Target, Terms.First(), Terms.Skip(1)) == Result.Success;
|
||||
}
|
||||
private static Result InnerTest3(long target, long current, IEnumerable<long> terms)
|
||||
{
|
||||
if (current > target)
|
||||
return Result.AllOverflow;
|
||||
var term = terms.Cast<long?>().FirstOrDefault();
|
||||
var remaining = terms.Skip(1);
|
||||
if (term is long _term)
|
||||
{
|
||||
return current switch
|
||||
{
|
||||
1 => InnerTest3(target, _term, remaining) switch
|
||||
{
|
||||
Result.MixedFailures => InnerTest3(target, 1 + _term, remaining) switch
|
||||
{
|
||||
Result.Success => Result.Success,
|
||||
Result.AllOverflow => Result.MixedFailures,
|
||||
_ => InnerTest3(target, Concat(1, _term), remaining) switch
|
||||
{
|
||||
Result.Success => Result.Success,
|
||||
_ => Result.MixedFailures,
|
||||
},
|
||||
},
|
||||
Result res => res,
|
||||
},
|
||||
0 => InnerTest3(target, 0, remaining) switch
|
||||
{
|
||||
Result.MixedFailures => InnerTest3(target, _term, remaining) switch
|
||||
{
|
||||
Result.Success => Result.Success,
|
||||
_ => Result.MixedFailures,
|
||||
},
|
||||
Result res => res,
|
||||
},
|
||||
long _current => _term switch
|
||||
{
|
||||
1 => InnerTest3(target, _current, remaining) switch
|
||||
{
|
||||
Result.MixedFailures => InnerTest3(target, _current + 1, remaining) switch
|
||||
{
|
||||
Result.Success => Result.Success,
|
||||
Result.MixedFailures => InnerTest3(target, _current * 10 + 1, remaining) switch
|
||||
{
|
||||
Result.Success => Result.Success,
|
||||
_ => Result.MixedFailures,
|
||||
},
|
||||
_ => Result.MixedFailures,
|
||||
},
|
||||
Result res => res,
|
||||
},
|
||||
_ => InnerTest3(target, _current + _term, remaining) switch
|
||||
{
|
||||
Result.MixedFailures => InnerTest3(target, _current * _term, remaining) switch
|
||||
{
|
||||
Result.Success => Result.Success,
|
||||
Result.AllOverflow => Result.MixedFailures,
|
||||
_ => InnerTest3(target, Concat(_current, _term), remaining) switch
|
||||
{
|
||||
Result.Success => Result.Success,
|
||||
_ => Result.MixedFailures,
|
||||
},
|
||||
},
|
||||
Result res => res,
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
return (target - current) switch
|
||||
{
|
||||
//should be impossible due to earlier check
|
||||
< 0 => Result.AllOverflow,
|
||||
0 => Result.Success,
|
||||
> 0 => Result.MixedFailures,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
private static long Concat(long first, long second)
|
||||
{
|
||||
return first * Shift(second) + second;
|
||||
}
|
||||
public bool Test4()
|
||||
{
|
||||
return InnerTest4(Target, Terms, Terms.Count() - 1);
|
||||
}
|
||||
private static bool InnerTest4(long current, IList<long> terms, int index)
|
||||
{
|
||||
long term = terms[index];
|
||||
if (index == 0)
|
||||
return current == term;
|
||||
if (InnerTest4(current - term, terms, index - 1))
|
||||
return true;
|
||||
if (current % term == 0 && InnerTest4(current / term, terms, index - 1))
|
||||
return true;
|
||||
var shift = Shift(term);
|
||||
if ((current % shift == term) && InnerTest4(current / shift, terms, index - 1))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
private static long Shift(long num)
|
||||
{
|
||||
var digits = ((long)Math.Log10(num+0.5)) + 1;
|
||||
long shift = 1;
|
||||
while (digits > 0)
|
||||
{
|
||||
shift *= 10;
|
||||
digits--;
|
||||
}
|
||||
return shift;
|
||||
}
|
||||
enum Result
|
||||
{
|
||||
AllOverflow,
|
||||
MixedFailures,
|
||||
Success,
|
||||
}
|
||||
}
|
||||
174
dotnet/08/08a.cs
Normal file
174
dotnet/08/08a.cs
Normal file
@@ -0,0 +1,174 @@
|
||||
Main1();
|
||||
Main2();
|
||||
|
||||
|
||||
void Main1()
|
||||
{
|
||||
var map = LoadMap(Path.Join("..", "..", "08a.txt"));
|
||||
HashSet<Point> antinodes = new();
|
||||
foreach (var (ch, points) in map.Antennae)
|
||||
{
|
||||
for (int i = 0; i < points.Count-1; i++)
|
||||
{
|
||||
for (int j = i+1; j < points.Count; j++)
|
||||
{
|
||||
antinodes.UnionWith(points[i].GetAntinodes(points[j]).Where(map.Validate));
|
||||
}
|
||||
}
|
||||
}
|
||||
Console.WriteLine($"Solution {antinodes.Count}");
|
||||
}
|
||||
|
||||
void Main2()
|
||||
{
|
||||
var map = LoadMap(Path.Join("..", "..", "08a.txt"));
|
||||
HashSet<Point> antinodes = new();
|
||||
foreach (var (ch, points) in map.Antennae)
|
||||
{
|
||||
for (int i = 0; i < points.Count-1; i++)
|
||||
{
|
||||
for (int j = i+1; j < points.Count; j++)
|
||||
{
|
||||
antinodes.UnionWith(points[i].GetAntinodes2(points[j], map));
|
||||
}
|
||||
}
|
||||
}
|
||||
Console.WriteLine($"Solution {antinodes.Count}");
|
||||
}
|
||||
|
||||
Map LoadMap(string filepath)
|
||||
{
|
||||
var lines = File.ReadAllLines(filepath)
|
||||
.Where(l => !string.IsNullOrWhiteSpace(l))
|
||||
.Select(s => s.Trim())
|
||||
.ToList();
|
||||
Map map = new();
|
||||
foreach (var (line, row) in lines.Select((l, i) => (l, i)))
|
||||
{
|
||||
foreach (var (c, col) in line.Select((ch, i) => (ch, i)))
|
||||
{
|
||||
if (c != '.')
|
||||
{
|
||||
Point p = new(row, col);
|
||||
if (map.Antennae.TryGetValue(c, out var points))
|
||||
{
|
||||
points.Add(p);
|
||||
}
|
||||
else
|
||||
{
|
||||
map.Antennae[c] = new(Enumerable.Repeat(p, 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
map.Width = lines[0].Length;
|
||||
map.Height = lines.Count;
|
||||
return map;
|
||||
}
|
||||
|
||||
public static class Stuff
|
||||
{
|
||||
//I forgot the good algorithm
|
||||
public static int TerribleGcf(int first, int second)
|
||||
{
|
||||
int gcf = 1;
|
||||
while (first % 2 == 0 && second % 2 == 0)
|
||||
{
|
||||
gcf *= 2;
|
||||
first /= 2;
|
||||
second /= 2;
|
||||
}
|
||||
for (int prime = 3; prime < first && prime < second; prime += 2)
|
||||
{
|
||||
while (first % prime == 0 && second % prime == 0)
|
||||
{
|
||||
gcf *= prime;
|
||||
first /= prime;
|
||||
second /= prime;
|
||||
}
|
||||
}
|
||||
return gcf;
|
||||
}
|
||||
//I had to look up the right way
|
||||
public static int EuclideanGcf(int first, int second)
|
||||
{
|
||||
if (first == 0 || second == 0)
|
||||
return 0;
|
||||
first = Math.Abs(first);
|
||||
second = Math.Abs(second);
|
||||
while (first != second)
|
||||
{
|
||||
if (second > first)
|
||||
{
|
||||
first = first ^ second;
|
||||
second = first ^ second;
|
||||
first = first ^ second;
|
||||
}
|
||||
first = first - second;
|
||||
}
|
||||
return first;
|
||||
}
|
||||
}
|
||||
|
||||
class Map
|
||||
{
|
||||
public Dictionary<char, List<Point>> Antennae = new();
|
||||
public int Width;
|
||||
public int Height;
|
||||
public Map()
|
||||
{
|
||||
|
||||
}
|
||||
public bool Validate(Point p)
|
||||
=> p.Row >= 0 && p.Row < Width && p.Col >= 0 && p.Col < Height;
|
||||
}
|
||||
|
||||
record struct Point(int Row, int Col)
|
||||
{
|
||||
public static Vector operator -(Point first, Point second)
|
||||
=> new(first.Row - second.Row, first.Col - second.Col);
|
||||
public static Point operator +(Point first, Vector second)
|
||||
=> new(first.Row + second.Row, first.Col + second.Col);
|
||||
public static Point operator -(Point first, Vector second)
|
||||
=> new(first.Row - second.Row, first.Col - second.Col);
|
||||
public readonly IEnumerable<Point> GetAntinodes(Point other)
|
||||
{
|
||||
var diff = this - other;
|
||||
yield return this + diff;
|
||||
yield return other - diff;
|
||||
if (diff.Row % 3 == 0 && diff.Col % 3 == 0)
|
||||
{
|
||||
Console.WriteLine("inline");
|
||||
yield return other + (diff / 3);
|
||||
yield return other + (diff * 2 / 3);
|
||||
}
|
||||
}
|
||||
public IEnumerable<Point> GetAntinodes2(Point other, Map map)
|
||||
{
|
||||
var diff = this - other;
|
||||
// diff /= Stuff.TerribleGcf(diff.Row, diff.Col);
|
||||
diff /= Stuff.EuclideanGcf(diff.Row, diff.Col);
|
||||
var running = this;
|
||||
while (map.Validate(running))
|
||||
{
|
||||
yield return running;
|
||||
running -= diff;
|
||||
}
|
||||
running = this + diff;
|
||||
while (map.Validate(running))
|
||||
{
|
||||
yield return running;
|
||||
running += diff;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
record struct Vector(int Row, int Col)
|
||||
{
|
||||
public static Vector operator +(Vector first, Vector second)
|
||||
=> new(first.Row + second.Row, first.Col + second.Col);
|
||||
public static Vector operator *(Vector first, int second)
|
||||
=> new(first.Row * second, first.Col * second);
|
||||
public static Vector operator /(Vector first, int second)
|
||||
=> new(first.Row / second, first.Col / second);
|
||||
}
|
||||
138
dotnet/09/09.cs
Normal file
138
dotnet/09/09.cs
Normal file
@@ -0,0 +1,138 @@
|
||||
using System.Numerics;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
|
||||
// Main1();
|
||||
Main2();
|
||||
|
||||
void Main1()
|
||||
{
|
||||
var data = LoadData1(Path.Join("..", "..", "09a.txt"));
|
||||
int i = 0;
|
||||
int j = data.Length - 1;
|
||||
while (i < j)
|
||||
{
|
||||
if (data[i] == -1)
|
||||
{
|
||||
while (data[j] == -1)
|
||||
j--;
|
||||
data[i] = data[j];
|
||||
data[j] = -1;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
i--;
|
||||
BigInteger checksum = 0;
|
||||
while (i >= 0)
|
||||
{
|
||||
if (data[i] < 0)
|
||||
throw new Exception($"Index {i} Value {data[i]}");
|
||||
checksum += i * data[i];
|
||||
i--;
|
||||
}
|
||||
Console.WriteLine($"Part1: {checksum,15}");
|
||||
}
|
||||
|
||||
void Main2()
|
||||
{
|
||||
var (files, empties) = LoadData2(Path.Join("..", "..", "09a.txt"));
|
||||
for (int i = files.Count-1; i >= 1; i--)
|
||||
{
|
||||
var file = files[i];
|
||||
for (int j = 0; j < empties.Count; j++)
|
||||
{
|
||||
var empty = empties[j];
|
||||
if (file.Location < empty.Location)
|
||||
break;
|
||||
if (file.Length <= empty.Length)
|
||||
{
|
||||
file.Location = empty.Location;
|
||||
empties[j] = new(empty.Location + file.Length, empty.Length - file.Length);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
//long is big enough but changing it didn't help execution time so...
|
||||
BigInteger checksum = 0;
|
||||
foreach (var f in files)
|
||||
{
|
||||
for (int i = 0; i < f.Length; i++)
|
||||
{
|
||||
checksum += f.Id * (f.Location + i);
|
||||
}
|
||||
}
|
||||
Console.WriteLine($"Part2: {checksum,15}");
|
||||
}
|
||||
|
||||
int[] LoadData1(string filepath)
|
||||
{
|
||||
int next_id = 0;
|
||||
bool next_is_blank = false;
|
||||
int GetId()
|
||||
{
|
||||
if (next_is_blank)
|
||||
{
|
||||
next_is_blank = false;
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
next_is_blank = true;
|
||||
return next_id++;
|
||||
}
|
||||
}
|
||||
var data = File.ReadAllText(filepath).Trim().SelectMany(c => Enumerable.Repeat(GetId(), c - '0')).ToArray();
|
||||
return data;
|
||||
}
|
||||
|
||||
(List<Filelike>,List<Empty>) LoadData2(string filepath)
|
||||
{
|
||||
short next_id = 0;
|
||||
bool next_is_blank = false;
|
||||
int location = 0;
|
||||
List<Filelike> files = [];
|
||||
List<Empty> empties = [];
|
||||
foreach (char c in File.ReadAllText(filepath).Trim())
|
||||
{
|
||||
int length = c - '0';
|
||||
if (next_is_blank)
|
||||
{
|
||||
if (length > 0)
|
||||
empties.Add(new (location, length));
|
||||
next_is_blank = false;
|
||||
location += length;
|
||||
}
|
||||
else
|
||||
{
|
||||
next_is_blank = true;
|
||||
if (length > 0)
|
||||
files.Add(new (location, length, next_id));
|
||||
location += length;
|
||||
next_id++;
|
||||
}
|
||||
}
|
||||
return (files,empties);
|
||||
}
|
||||
|
||||
class Filelike(int Location, int Length, short Id)
|
||||
{
|
||||
public int Location = Location;
|
||||
public int Length = Length;
|
||||
public short Id = Id;
|
||||
}
|
||||
class Empty(int Location, int Length)
|
||||
{
|
||||
public int Location = Location;
|
||||
public int Length = Length;
|
||||
}
|
||||
|
||||
// class Filelike(int Location, int Length, int Id)
|
||||
// {
|
||||
// public int Location = Location;
|
||||
// public int Length = Length;
|
||||
// public int Id = Id;
|
||||
// }
|
||||
// class Empty(int Location, int Length)
|
||||
// {
|
||||
// public int Location = Location;
|
||||
// public int Length = Length;
|
||||
// }
|
||||
Reference in New Issue
Block a user