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