Skip to content

Commit c88105f

Browse files
committed
Add Day 3 (the first part)
1 parent cf85d30 commit c88105f

File tree

1 file changed

+259
-0
lines changed

1 file changed

+259
-0
lines changed

03.exs

Lines changed: 259 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,259 @@
1+
defmodule Puzzle do
2+
defmodule Spiral do
3+
defstruct [:base, :level, :range]
4+
5+
def distance(spiral, square) do
6+
side_centers = Enum.map(0..3, fn x ->
7+
spiral.range.last -
8+
div(spiral.base, 2) -
9+
(spiral.base - 1) * x
10+
end)
11+
12+
min_center_dist =
13+
side_centers
14+
|> Enum.map(fn x -> abs(x - square) end)
15+
|> Enum.min
16+
17+
min_center_dist
18+
end
19+
end
20+
21+
require Integer
22+
23+
def stress_test_value(0), do: 1
24+
def stress_test_value(n) do
25+
prev_value = stress_test_value(n - 1)
26+
diagonal_value = 0
27+
28+
prev_value + diagonal_value
29+
end
30+
31+
def adjacent(memory, n) do
32+
[]
33+
end
34+
35+
def coords(memory, 1), do: {0, 0}
36+
def coords(memory, n) do
37+
{0, 0}
38+
end
39+
40+
def distance(1), do: 0
41+
def distance(square) do
42+
spiral = square |> spiral_base |> build_spiral
43+
44+
spiral.level + Spiral.distance(spiral, square)
45+
end
46+
47+
def build_spiral(1), do: %Spiral{level: 0, base: 1, range: 1..1}
48+
def build_spiral(base) do
49+
level = div((base - 1), 2)
50+
prev_base = base - 2
51+
range = (prev_base * prev_base + 1)..(base * base)
52+
%Spiral{level: level, base: base, range: range}
53+
end
54+
55+
def spiral_base(square) do
56+
square
57+
|> :math.sqrt
58+
|> Float.ceil
59+
|> round_to_odd
60+
end
61+
62+
defp round_to_odd(n) do
63+
int_n = round(n)
64+
65+
if Integer.is_odd(int_n) do
66+
int_n
67+
else
68+
int_n + 1
69+
end
70+
end
71+
end
72+
73+
mode = List.first(System.argv)
74+
75+
if mode == "test" do
76+
ExUnit.start()
77+
78+
defmodule PuzzleTest do
79+
use ExUnit.Case
80+
81+
describe "distance(square)" do
82+
test "square = 1" do
83+
dist = Puzzle.distance(1)
84+
assert dist == 0
85+
end
86+
87+
test "square = 12" do
88+
dist = Puzzle.distance(12)
89+
assert dist == 3
90+
end
91+
92+
test "square = 23" do
93+
dist = Puzzle.distance(23)
94+
assert dist == 2
95+
end
96+
97+
test "square = 1024" do
98+
dist = Puzzle.distance(1024)
99+
assert dist == 31
100+
end
101+
end
102+
103+
describe "spiral_base(square)" do
104+
test "square = 1" do
105+
n = Puzzle.spiral_base(1)
106+
assert n == 1
107+
end
108+
109+
test "square = 2" do
110+
n = Puzzle.spiral_base(2)
111+
assert n == 3
112+
end
113+
114+
test "square = 9" do
115+
n = Puzzle.spiral_base(9)
116+
assert n == 3
117+
end
118+
119+
test "square = 27" do
120+
n = Puzzle.spiral_base(27)
121+
assert n == 7
122+
end
123+
end
124+
125+
describe "build_spiral(base)" do
126+
test "base = 1" do
127+
spiral = Puzzle.build_spiral(1)
128+
assert(
129+
spiral == %Puzzle.Spiral{level: 0, base: 1, range: 1..1}
130+
)
131+
end
132+
133+
test "base = 5" do
134+
spiral = Puzzle.build_spiral(5)
135+
assert(
136+
spiral == %Puzzle.Spiral{level: 2, base: 5, range: 10..25}
137+
)
138+
end
139+
140+
test "base = 11" do
141+
spiral = Puzzle.build_spiral(11)
142+
assert(
143+
spiral == %Puzzle.Spiral{level: 5, base: 11, range: 82..121}
144+
)
145+
end
146+
end
147+
148+
describe "stress_test_value(n)" do
149+
test "when n == 1" do
150+
value = Puzzle.stress_test_value(1)
151+
assert value == 1
152+
end
153+
154+
test "when n == 2" do
155+
value = Puzzle.stress_test_value(2)
156+
assert value == 1
157+
end
158+
159+
test "when n == 6" do
160+
value = Puzzle.stress_test_value(6)
161+
assert value == 10
162+
end
163+
164+
test "when n == 13" do
165+
value = Puzzle.stress_test_value(13)
166+
assert value == 59
167+
end
168+
169+
test "when n == 14" do
170+
value = Puzzle.stress_test_value(14)
171+
assert value == 122
172+
end
173+
174+
test "when n == 15" do
175+
value = Puzzle.stress_test_value(15)
176+
assert value == 133
177+
end
178+
end
179+
180+
# describe "adjacent(memory, n)" do
181+
# setup [:build_3x3_memory]
182+
#
183+
# test "when n = 1", context do
184+
# adjacent = Puzzle.adjacent(context[:memory], 1)
185+
#
186+
# diff = List.myers_difference(
187+
# adjacent,
188+
# [5, 4, 2, 10, 1, 11, 23, 25]
189+
# )
190+
#
191+
# refute diff[:del]
192+
# refute diff[:ins]
193+
# end
194+
#
195+
# test "when n = 3", context do
196+
# adjacent = Puzzle.adjacent(context[:memory], 3)
197+
#
198+
# diff = List.myers_difference(
199+
# adjacent,
200+
# [1, 1, 4]
201+
# )
202+
#
203+
# refute diff[:del]
204+
# refute diff[:ins]
205+
# end
206+
#
207+
# test "when n = 6", context do
208+
# adjacent = Puzzle.adjacent(context[:memory], 6)
209+
#
210+
# diff = List.myers_difference(
211+
# adjacent,
212+
# [5, 11, 4, 1, 23]
213+
# )
214+
#
215+
# refute diff[:del]
216+
# refute diff[:ins]
217+
# end
218+
# end
219+
#
220+
# describe "coords(memory, n)" do
221+
# test "when n = 1", context do
222+
# coords = Puzzle.coords(context[:memory], 1)
223+
# assert coords == {0, 0}
224+
# end
225+
#
226+
# test "when n = 3", context do
227+
# coords = Puzzle.coords(context[:memory], 3)
228+
# assert coords == {1, -1}
229+
# end
230+
#
231+
# test "when n = 4", context do
232+
# coords = Puzzle.coords(context[:memory], 4)
233+
# assert coords == {0, -1}
234+
# end
235+
#
236+
# test "when n = 7", context do
237+
# coords = Puzzle.coords(context[:memory], 7)
238+
# assert coords == {-1, -1}
239+
# end
240+
# end
241+
#
242+
# defp build_3x3_memory(context) do
243+
# memory = [
244+
# [5, 10, 11],
245+
# [4, 1, 23],
246+
# [2, 1, 25]
247+
# ]
248+
#
249+
# [memory: memory]
250+
# end
251+
end
252+
else
253+
data = 361_527
254+
distance = Puzzle.distance(data)
255+
IO.inspect(distance, label: "The distance is:")
256+
# data = "03.txt" |> File.read! |> String.trim_trailing
257+
# checksum = Puzzle.checksum(data)
258+
# IO.puts "The checksum is: #{checksum}"
259+
end

0 commit comments

Comments
 (0)