cem 0.1.4 → 0.1.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. checksums.yaml +4 -4
  2. data/examples/aoc2018/.gitignore +2 -0
  3. data/examples/aoc2018/day10.rb +61 -0
  4. data/examples/aoc2018/day11.rb +66 -0
  5. data/examples/aoc2018/day12.rb +61 -0
  6. data/examples/aoc2018/day13.rb +167 -0
  7. data/examples/aoc2018/day14.rb +31 -0
  8. data/examples/aoc2018/day14_2.rb +71 -0
  9. data/examples/aoc2018/day15.rb +271 -0
  10. data/examples/aoc2018/day16.rb +158 -0
  11. data/examples/aoc2018/day17.rb +203 -0
  12. data/examples/aoc2018/day18.rb +113 -0
  13. data/examples/aoc2018/day18_rspec.rb +131 -0
  14. data/examples/aoc2018/day19.rb +145 -0
  15. data/examples/aoc2018/day20.rb +103 -0
  16. data/examples/aoc2018/day21.rb +158 -0
  17. data/examples/aoc2018/day21_v2.rb +137 -0
  18. data/examples/aoc2018/day21_v3.rb +157 -0
  19. data/examples/aoc2018/day21_v4.rb +141 -0
  20. data/examples/aoc2018/day22.rb +212 -0
  21. data/examples/aoc2018/day23.rb +148 -0
  22. data/examples/aoc2018/day24.rb +156 -0
  23. data/examples/aoc2018/day25.rb +52 -0
  24. data/examples/aoc2018/day9.rb +51 -0
  25. data/examples/aoc2018/day9_circular.rb +125 -0
  26. data/examples/aoc2018/inputs/day10_input.txt +395 -0
  27. data/examples/aoc2018/inputs/day11_input.txt +1 -0
  28. data/examples/aoc2018/inputs/day12_input.txt +34 -0
  29. data/examples/aoc2018/inputs/day12_input2.txt +16 -0
  30. data/examples/aoc2018/inputs/day13_input.txt +150 -0
  31. data/examples/aoc2018/inputs/day13_test.txt +6 -0
  32. data/examples/aoc2018/inputs/day14_input.txt +1 -0
  33. data/examples/aoc2018/inputs/day15_input.txt +32 -0
  34. data/examples/aoc2018/inputs/day15_input10.txt +32 -0
  35. data/examples/aoc2018/inputs/day15_input11.txt +32 -0
  36. data/examples/aoc2018/inputs/day15_input12.txt +32 -0
  37. data/examples/aoc2018/inputs/day15_input13.txt +32 -0
  38. data/examples/aoc2018/inputs/day15_input14.txt +32 -0
  39. data/examples/aoc2018/inputs/day15_input2.txt +7 -0
  40. data/examples/aoc2018/inputs/day15_input3.txt +9 -0
  41. data/examples/aoc2018/inputs/day15_input4.txt +7 -0
  42. data/examples/aoc2018/inputs/day15_input5.txt +7 -0
  43. data/examples/aoc2018/inputs/day15_input6.txt +7 -0
  44. data/examples/aoc2018/inputs/day15_input7.txt +7 -0
  45. data/examples/aoc2018/inputs/day15_input8.txt +5 -0
  46. data/examples/aoc2018/inputs/day15_input9.txt +7 -0
  47. data/examples/aoc2018/inputs/day15_test.txt +9 -0
  48. data/examples/aoc2018/inputs/day16_input.txt +3865 -0
  49. data/examples/aoc2018/inputs/day17_input.txt +2229 -0
  50. data/examples/aoc2018/inputs/day17_input_test.txt +8 -0
  51. data/examples/aoc2018/inputs/day18_input.txt +50 -0
  52. data/examples/aoc2018/inputs/day18_test.txt +10 -0
  53. data/examples/aoc2018/inputs/day19_input.txt +48 -0
  54. data/examples/aoc2018/inputs/day20_input.txt +1 -0
  55. data/examples/aoc2018/inputs/day21_input.txt +32 -0
  56. data/examples/aoc2018/inputs/day22_input.txt +2 -0
  57. data/examples/aoc2018/inputs/day23_input.txt +1000 -0
  58. data/examples/aoc2018/inputs/day23_input2.txt +9 -0
  59. data/examples/aoc2018/inputs/day24_input.txt +24 -0
  60. data/examples/aoc2018/inputs/day25_input.txt +1483 -0
  61. data/examples/aoc2018/inputs/day9_input.txt +1 -0
  62. data/lib/cem.rb +0 -6
  63. data/lib/cem/ccommon.rb +45 -0
  64. data/lib/cem/cruzzles.rb +93 -38
  65. data/lib/cem/version.rb +1 -1
  66. metadata +62 -2
@@ -0,0 +1,113 @@
1
+
2
+ #
3
+ # https://adventofcode.com/2018/day/18 part 1 and 2
4
+ #
5
+ # Demonstrates Grid and Object#peql. For an rspec based variant see day18_rspec.rb
6
+ #
7
+
8
+ require 'cem'
9
+ require 'set'
10
+
11
+ def run(inputFilename, part1, debug)
12
+
13
+ lines = []
14
+ File.readlines(inputFilename, chomp: true).each { |line|
15
+ lines << line.rstrip
16
+ }
17
+
18
+ maxY = lines.size
19
+ maxX = lines[0].length
20
+
21
+ @m = Grid.new(maxX, maxY, '.')
22
+
23
+ @map = []
24
+ lines.each_with_index { |l, y|
25
+ result = []
26
+
27
+ l.chars.each_with_index { |c, x|
28
+ result << c
29
+ @m[y,x] = c
30
+ }
31
+ @map << result
32
+ }
33
+
34
+ puts "Initial State" if debug
35
+ puts @m if debug
36
+
37
+ intermediates = Set.new
38
+
39
+ startIteration = nil
40
+ periodicity = nil
41
+ tickResultCache = nil
42
+
43
+ # Read board
44
+ (1..1000000000).each { |i|
45
+
46
+ @m2 = @m.clone
47
+
48
+ @map.each_with_index { |l, y|
49
+
50
+ l.each_with_index { |c, x|
51
+
52
+ # puts "Adja: #{x} #{y}"
53
+ ajda = @m.adja_index(x,y)
54
+ case @m[y,x]
55
+ when '.'
56
+ @m2[y,x] = ajda.select { |p| @m[p] == '|' }.size >= 3 ? '|' : '.'
57
+ when '|'
58
+ @m2[y,x] = ajda.select { |p| @m[p] == '#' }.size >= 3 ? '#' : '|'
59
+ when '#'
60
+ @m2[y,x] = ajda.select { |p| @m[p] == '#' }.size >= 1 && ajda.select { |p| @m[p] == '|' }.size >= 1 ? '#' : '.'
61
+ end
62
+
63
+ puts "#{y} #{x} was #{@m[y,x]} is now #{@m2[y,x]}: #{ajda.inspect}" if debug
64
+
65
+ }
66
+ }
67
+
68
+ @m = @m2
69
+
70
+ if part1 && i == 10
71
+ puts "Part 1: Score after #{i} tick is #{@m.count('#') * @m.count('|')}" # if debug
72
+ break
73
+ end
74
+
75
+ puts @m if debug if debug
76
+ gets if debug
77
+
78
+ if !part1
79
+ tickResult = @m.to_a
80
+
81
+ if periodicity == nil && tickResultCache == tickResult
82
+ periodicity = i - startIteration
83
+ # puts periodicity
84
+ elsif periodicity
85
+ if ((1000000000 - i) % periodicity) == 0
86
+ break
87
+ end
88
+ end
89
+
90
+ if startIteration == nil && intermediates.include?(tickResult)
91
+ startIteration = i
92
+ tickResultCache = tickResult
93
+ elsif startIteration == nil
94
+ intermediates.add(tickResult)
95
+ end
96
+
97
+ end
98
+ }
99
+
100
+ @m.count('#') * @m.count('|')
101
+ end
102
+
103
+ debug = false
104
+
105
+ {
106
+ "inputs/day18_test.txt" => [1147, 0],
107
+ "inputs/day18_input.txt" => [589931, 222332],
108
+ }.each_pair { |k,v|
109
+
110
+ peql(run(k, true, debug), v[0], "Testing #{k.inspect} part 1")
111
+ peql(run(k, false, debug), v[1], "Testing #{k.inspect} part 2")
112
+
113
+ }
@@ -0,0 +1,131 @@
1
+
2
+ #
3
+ # https://adventofcode.com/2018/day/18 part 1 and 2
4
+ #
5
+ # Demonstrates Grid and Object#peql. For a variant without rspec see day18.rb
6
+ #
7
+
8
+ require 'cem'
9
+ require 'set'
10
+
11
+ def run(inputFilename, part1, debug)
12
+
13
+ lines = []
14
+ File.readlines(inputFilename, chomp: true).each { |line|
15
+ lines << line.rstrip
16
+ }
17
+
18
+ maxY = lines.size
19
+ maxX = lines[0].length
20
+
21
+ @m = Grid.new(maxX, maxY, '.')
22
+
23
+ @map = []
24
+ lines.each_with_index { |l, y|
25
+ result = []
26
+
27
+ l.chars.each_with_index { |c, x|
28
+ result << c
29
+ @m[y,x] = c
30
+ }
31
+ @map << result
32
+ }
33
+
34
+ puts "Initial State" if debug
35
+ puts @m if debug
36
+
37
+ intermediates = Set.new
38
+
39
+ startIteration = nil
40
+ periodicity = nil
41
+ tickResultCache = nil
42
+
43
+ # Read board
44
+ (1..1000000000).each { |i|
45
+
46
+ @m2 = @m.clone
47
+
48
+ @map.each_with_index { |l, y|
49
+
50
+ l.each_with_index { |c, x|
51
+
52
+ # puts "Adja: #{x} #{y}"
53
+ ajda = @m.adja_index(x,y)
54
+ case @m[y,x]
55
+ when '.'
56
+ @m2[y,x] = ajda.select { |p| @m[p] == '|' }.size >= 3 ? '|' : '.'
57
+ when '|'
58
+ @m2[y,x] = ajda.select { |p| @m[p] == '#' }.size >= 3 ? '#' : '|'
59
+ when '#'
60
+ @m2[y,x] = ajda.select { |p| @m[p] == '#' }.size >= 1 && ajda.select { |p| @m[p] == '|' }.size >= 1 ? '#' : '.'
61
+ end
62
+
63
+ puts "#{y} #{x} was #{@m[y,x]} is now #{@m2[y,x]}: #{ajda.inspect}" if debug
64
+
65
+ }
66
+ }
67
+
68
+ @m = @m2
69
+
70
+ if part1 && i == 10
71
+ puts "Part 1: Score after #{i} tick is #{@m.count('#') * @m.count('|')}" # if debug
72
+ break
73
+ end
74
+
75
+ puts @m if debug if debug
76
+ gets if debug
77
+
78
+ if !part1
79
+ tickResult = @m.to_a
80
+
81
+ if periodicity == nil && tickResultCache == tickResult
82
+ periodicity = i - startIteration
83
+ # puts periodicity
84
+ elsif periodicity
85
+ if ((1000000000 - i) % periodicity) == 0
86
+ break
87
+ end
88
+ end
89
+
90
+ if startIteration == nil && intermediates.include?(tickResult)
91
+ startIteration = i
92
+ tickResultCache = tickResult
93
+ elsif startIteration == nil
94
+ intermediates.add(tickResult)
95
+ end
96
+
97
+ end
98
+ }
99
+
100
+ @m.count('#') * @m.count('|')
101
+ end
102
+
103
+ debug = false
104
+
105
+ require 'rspec'
106
+
107
+ RSpec.configure do |config|
108
+ config.color = true # Use color in STDOUT
109
+ config.tty = true # Use color not only in STDOUT but also in pagers and files
110
+ config.formatter = :documentation
111
+ end
112
+
113
+ describe $__FILE__ do
114
+
115
+ {
116
+ "inputs/day18_test.txt" => [1147, 1],
117
+ "inputs/day18_input.txt" => [589931, 222332],
118
+ }.each_pair { |k,v|
119
+
120
+ it "testing #{k.inspect} part 1" do
121
+ expect(run(k, true, debug)).to eq(v[0])
122
+ end
123
+
124
+ it "testing #{k.inspect} part 2" do
125
+ expect(run(k, false, debug)).to eq(v[1])
126
+ end
127
+ }
128
+
129
+ end
130
+
131
+ RSpec::Core::Runner.run([$__FILE__])
@@ -0,0 +1,145 @@
1
+ #
2
+ # https://adventofcode.com/2018/day/19 part 1 and 2
3
+ #
4
+
5
+ # My code was too slow to handle this problem, so this is really more analytical from observing the state of the machine and figuring out what it does.
6
+
7
+ shortcut = true
8
+ if shortcut
9
+
10
+ result = 0
11
+ (1..930).each { |i|
12
+ result += i if 930 % i == 0
13
+ }
14
+ puts "Part 1: #{result}"
15
+
16
+ result = 0
17
+ (1..10551330).each { |i|
18
+ result += i if 10551330 % i == 0
19
+ }
20
+ puts "Part 2: #{result}"
21
+ exit
22
+ end
23
+
24
+
25
+ [1,2].each { |part|
26
+
27
+ lines = File.readlines("inputs/day19_input.txt", chomp: true)
28
+
29
+ commandQueue = []
30
+
31
+ reg = [part - 1, 0, 0, 0, 0, 0]
32
+
33
+ ip = nil
34
+ lines.each { |line|
35
+
36
+ if line =~ /^#ip ([+-]?\d+)$/
37
+ ip = $1.to_i
38
+ end
39
+
40
+ if line =~ /^(\w+) ([+-]?\d+) ([+-]?\d+) ([+-]?\d+)$/
41
+ verb = $1
42
+ v1 = $2.to_i
43
+ v2 = $3.to_i
44
+ v3 = $4.to_i
45
+
46
+ commandQueue << [verb, v1, v2, v3]
47
+ end
48
+ }
49
+
50
+ if false
51
+ puts "Command queue:"
52
+ commandQueue.each { |x|
53
+ puts " " + x.inspect
54
+ }
55
+ end
56
+
57
+ ipp = 0
58
+ i = 0
59
+ reset = true
60
+
61
+ while ipp >= 0 && ipp < commandQueue.size
62
+
63
+ reg[ip] = ipp
64
+ command = commandQueue[ipp]
65
+
66
+ puts command.inspect + " " + reg.inspect if i % (256*1024) == 0
67
+ i += 1
68
+
69
+ case command[0]
70
+
71
+ when "addr"
72
+ # addr (add register) stores into register C the result of adding register A and register B.
73
+ reg[command[3]] = reg[command[1]] + reg[command[2]]
74
+
75
+ when "addi"
76
+ # addi (add immediate) stores into register C the result of adding register A and value B.
77
+ reg[command[3]] = reg[command[1]] + command[2]
78
+
79
+ when "mulr"
80
+ # mulr (multiply register) stores into register C the result of multiplying register A and register B.
81
+ reg[command[3]] = reg[command[1]] * reg[command[2]]
82
+
83
+ when "muli"
84
+ # muli (multiply immediate) stores into register C the result of multiplying register A and value B.
85
+ reg[command[3]] = reg[command[1]] * command[2]
86
+
87
+ when "banr"
88
+ # banr (bitwise AND register) stores into register C the result of the bitwise AND of register A and register B.
89
+ reg[command[3]] = reg[command[1]] & reg[command[2]]
90
+
91
+ when "bani"
92
+ # bani (bitwise AND immediate) stores into register C the result of the bitwise AND of register A and value B.
93
+ reg[command[3]] = reg[command[1]] & command[2]
94
+
95
+ when "borr"
96
+ # borr (bitwise OR register) stores into register C the result of the bitwise OR of register A and register B.
97
+ reg[command[3]] = reg[command[1]] | reg[command[2]]
98
+
99
+ when "bori"
100
+ # bori (bitwise OR immediate) stores into register C the result of the bitwise OR of register A and value B.
101
+ reg[command[3]] = reg[command[1]] | command[2]
102
+
103
+ when "setr"
104
+ # setr (set register) copies the contents of register A into register C. (Input B is ignored.)
105
+ reg[command[3]] = reg[command[1]]
106
+
107
+ when "seti"
108
+ # seti (set immediate) stores value A into register C. (Input B is ignored.)
109
+ reg[command[3]] = command[1]
110
+
111
+ when "gtir"
112
+ # gtir (greater-than immediate/register) sets register C to 1 if value A is greater than register B. Otherwise, register C is set to 0.
113
+ reg[command[3]] = command[1] > reg[command[2]] ? 1 : 0
114
+
115
+ when "gtri"
116
+ # gtri (greater-than register/immediate) sets register C to 1 if register A is greater than value B. Otherwise, register C is set to 0.
117
+ reg[command[3]] = reg[command[1]] > command[2] ? 1 : 0
118
+
119
+ when "gtrr"
120
+ # gtrr (greater-than register/register) sets register C to 1 if register A is greater than register B. Otherwise, register C is set to 0.
121
+ reg[command[3]] = reg[command[1]] > reg[command[2]] ? 1 : 0
122
+
123
+ when "eqir"
124
+ # eqir (equal immediate/register) sets register C to 1 if value A is equal to register B. Otherwise, register C is set to 0.
125
+ reg[command[3]] = command[1] == reg[command[2]] ? 1 : 0
126
+
127
+ when "eqri"
128
+ # eqri (equal register/immediate) sets register C to 1 if register A is equal to value B. Otherwise, register C is set to 0.
129
+ reg[command[3]] = reg[command[1]] == command[2] ? 1 : 0
130
+
131
+ when "eqrr"
132
+ # eqrr (equal register/register) sets register C to 1 if register A is equal to register B. Otherwise, register C is set to 0.
133
+ reg[command[3]] = reg[command[1]] == reg[command[2]] ? 1 : 0
134
+
135
+ else
136
+ raise "Error"
137
+ end
138
+
139
+ ipp = reg[ip]
140
+ ipp += 1
141
+ end
142
+
143
+ puts reg.inspect
144
+ puts "Part#{part}: #{reg[0]}"
145
+ }
@@ -0,0 +1,103 @@
1
+ #
2
+ # https://adventofcode.com/2018/day/20 part 1 and 2
3
+ #
4
+ # Took 1:10 min for both parts (not bad!)
5
+ #
6
+ # Could have been faster, but ruzzles parts had to be created for this:
7
+ #
8
+ # - Grid.minmax
9
+ # - Point2D.from_s
10
+ # - Point2D.to_dir_bitmask / from_dir_bitmask
11
+ # - Dirs2D
12
+ #
13
+
14
+ require 'cem'
15
+
16
+ line = File.read("inputs/day20_input.txt")
17
+
18
+ stack = [[Point2D.new(500,500)]]
19
+
20
+ grid = Grid.new(1000, 1000, 0)
21
+
22
+ line.chars.each { |c|
23
+ case c
24
+
25
+ when '$'
26
+ # ignore
27
+ when '^'
28
+ # ignore
29
+ when "\n"
30
+ # ignore
31
+
32
+ when '('
33
+ newCurCursor = stack.last.map { |p| p.dup }
34
+ stack << [] # One below top() are all cursors we collected as part of this opening brace group
35
+ stack << newCurCursor # Stack.top() is all current cursor position we are tracking
36
+
37
+ when ')'
38
+ lastGroup = stack.pop
39
+ otherGroupsInBrace = stack.pop
40
+ replacedGroup = stack.pop
41
+ stack << (lastGroup + otherGroupsInBrace).uniq
42
+
43
+ when 'E', 'N', 'S', 'W'
44
+ dir = Point2D.from_s(c)
45
+
46
+ stack.last.map! { |p|
47
+ grid[p] |= dir.to_dir_bitmask
48
+ p += dir
49
+ grid[p] |= dir.flip.to_dir_bitmask
50
+ p
51
+ }
52
+ when '|'
53
+ lastGroup = stack.pop
54
+ stack.last.concat lastGroup
55
+ stack << stack[-2].map { |p| p.dup }
56
+
57
+ else
58
+ raise "Unknown char '#{c.inspect}'"
59
+ end
60
+ }
61
+
62
+ if false # Print Grid for debugging
63
+
64
+ min, max = grid.minmax(0)
65
+ count = 0
66
+
67
+ (min.y..max.y).each {|y|
68
+ a = ""
69
+ b = ""
70
+ (min.x..max.x).each { |x|
71
+ count += 1 if grid[y,x] > 0
72
+ a += "#" + (grid[y,x] & 1 == 1 ? "|" : "#")
73
+ b += (grid[y,x] & 8 == 8 ? "-" : "#") + (grid[y,x] > 0 ? "." : "#")
74
+ }
75
+ puts a + "#"
76
+ puts b + "#"
77
+ }
78
+
79
+ end
80
+
81
+ # Run BFS search
82
+ q = [[Point2D.new(500,500), 0]]
83
+
84
+ maxSteps = 0
85
+ rooms = 0
86
+ while q.size > 0
87
+ p, maxSteps = q.shift
88
+
89
+ if maxSteps >= 1000
90
+ rooms += 1
91
+ end
92
+
93
+ Point2D.from_dir_bitmask(grid[p]).each { |dir|
94
+ grid[p+dir] &= ~dir.flip.to_dir_bitmask # Close door we walked through. Due to BFS, we never have to get to it again
95
+
96
+ q << [p+dir, maxSteps+1]
97
+ }
98
+ grid[p] = 0
99
+
100
+ end
101
+
102
+ puts "Part 1: #{maxSteps}"
103
+ puts "Part 2: #{rooms}"