1- require 'set'
1+ def find_intersection ( ax , ay , bx , by , tx , ty )
2+ # Find a and b where:
3+ # ax*a + bx*b = tx
4+ # ay*a + by*b = ty
25
3- class Array
4- def zmr ( other )
5- self . zip ( other ) . map { _1 . reduce { |x , y | yield x , y } }
6- end
7- end
8-
9- def calculate_prize ( a , b , target )
10- visited = Set [ ]
11- queue = [ ]
12- queue << [ 0 , [ 0 , 0 ] ]
13-
14- until queue . empty? do
15- cost , pos = queue . pop
16- return cost if pos == target
17- next unless visited . add? pos
6+ a = ( tx *by - ty *bx ) . to_f / ( ax *by - ay *bx )
7+ b = ( ty - ay * a ) . to_f / by
188
19- na = pos . zmr ( a , &:+ )
20- nb = pos . zmr ( b , &:+ )
21-
22- queue . push [ cost +1 , nb ] unless nb . zmr ( target , &:> ) . any?
23- queue . push [ cost +3 , na ] unless na . zmr ( target , &:> ) . any?
24- end
9+ return [ a , b ] if a %1 == 0 && b %1 == 0
10+ end
2511
26- return 0
12+ def solve ( input )
13+ input
14+ . filter_map { |a , b , target | find_intersection ( *a , *b , *target ) }
15+ . sum { |a , b | a * 3 + b }
16+ . to_i
2717end
2818
2919
@@ -33,4 +23,5 @@ def calculate_prize(a, b, target)
3323 . map { _1 . scan ( /\d +/ ) . map ( &:to_i ) . each_slice ( 2 ) . to_a }
3424
3525
36- p input . sum { |a , b , target | calculate_prize ( a , b , target ) }
26+ p solve ( input )
27+ p solve ( input . map { |a , b , target | [ a , b , target . map { _1 + 10000000000000 } ] } )
0 commit comments