1
+ /*
2
+ input: string, lines: string[], dblines: string[][]
3
+ copy(text: string) → clipboard
4
+ error(message: string) → thrown error
5
+ -5..mod(3) → @mod(-5, 3)
6
+ */
7
+
8
+ // Cardinals:
9
+ // [[1,0],[-1,0],[0,1],[0,-1]]
10
+ // +Diagonals:
11
+ // [[1,0],[-1,0],[0,1],[0,-1],[-1,-1],[-1,1],[1,-1],[1,1]]
12
+
13
+ export { } ;
14
+
15
+ const practice = `7,4,9,5,11,17,23,2,0,14,21,24,10,16,13,6,15,25,12,22,18,20,8,19,3,26,1
16
+
17
+ 22 13 17 11 0
18
+ 8 2 23 4 24
19
+ 21 9 14 16 7
20
+ 6 10 3 18 5
21
+ 1 12 20 15 19
22
+
23
+ 3 15 0 2 22
24
+ 9 18 13 17 5
25
+ 19 8 7 25 23
26
+ 20 11 10 24 4
27
+ 14 21 16 12 6
28
+
29
+ 14 21 17 24 4
30
+ 10 16 15 9 19
31
+ 18 8 23 26 20
32
+ 22 11 13 6 5
33
+ 2 0 12 3 7` ;
34
+ // input = practice;
35
+
36
+
37
+ let [ selections , ...boardsraw ] = input . split ( "\n\n" ) ;
38
+
39
+ let boards = boardsraw . map ( b => {
40
+ const v = b . trim ( ) . split ( "\n" ) . map ( l => l . trim ( ) . split ( / + / ) ) ;
41
+ return v ;
42
+ } ) ;
43
+ boards . dwth ( log ) ;
44
+
45
+ function checkWin ( board : string [ ] [ ] ) : boolean {
46
+ let win = false ;
47
+ range ( 5 ) . forEach ( y => {
48
+ if ( ! win ) win = range ( 5 ) . every ( x => {
49
+ return board [ y ] [ x ] === "X" ;
50
+ } ) ;
51
+ } ) ;
52
+ range ( 5 ) . forEach ( x => {
53
+ if ( ! win ) win = range ( 5 ) . every ( y => {
54
+ return board [ y ] [ x ] === "X" ;
55
+ } ) ;
56
+ } ) ;
57
+ return win ;
58
+ }
59
+
60
+ let wnext = false ;
61
+ for ( const selection of selections . split ( "," ) ) {
62
+ let nwin = false ;
63
+ boards = boards . map ( board => {
64
+ // if(nwin) return board;
65
+ const res = board . map ( line => line . map ( col => col === selection ? "X" : col ) )
66
+ // if(checkWin(res)) nwin = true;
67
+ return res ;
68
+ } ) ;
69
+ if ( wnext ) {
70
+ selection . dwth ( log ) ;
71
+ const board = boards [ 0 ] ;
72
+ const res = board . reduce ( ( a , b ) => a + b . reduce ( ( t , v ) => t + ( v === "X" ? 0 : + v ) , 0 ) , 0 ) ;
73
+ res . dwth ( log ) ;
74
+ ( res * + selection ) . dwth ( log ) ; // expect-equal 7075
75
+ throw new Error ( `${ board } wins` ) ;
76
+ }
77
+ boards = boards . dwth ( log ) . filter ( board => ! checkWin ( board ) ) ;
78
+
79
+ if ( boards . length === 1 ) {
80
+ wnext = true ;
81
+ }
82
+ }
83
+
84
+
85
+
86
+
87
+
88
+
89
+
90
+
91
+
92
+
93
+ type nobi = number | bigint ;
94
+ type Board < T > = {
95
+ get ( pos : Point2D ) : T ;
96
+ set ( pos : Point2D , t : T ) : void ;
97
+ clear ( ) : void ;
98
+ forEach ( visitor : ( v : T , pos : Point2D ) => void ) : void ;
99
+ print ( printer ?: ( v : T , pos : Point2D ) => string | nobi ) : string ;
100
+ copy ( ) : Board < T > ;
101
+ } ;
102
+ function makeBoard < T > ( fill : T ) : Board < T > {
103
+ // it would be useful if board could center at 0,0 and expand infinitely
104
+ let board : T [ ] [ ] = [ ] ;
105
+ let limits :
106
+ | { min : Point2D , max : Point2D }
107
+ | undefined ;
108
+ let reso : Board < T > = {
109
+ clear : ( ) => {
110
+ board = [ ] ;
111
+ } ,
112
+ get : ( pos ) => {
113
+ if ( ! limits ) return fill ;
114
+ if (
115
+ pos . op ( limits . min , ( a , b ) => a < b ) . some ( w => w ) ||
116
+ pos . op ( limits . max , ( a , b ) => a > b ) . some ( w => w )
117
+ ) return fill ;
118
+ if ( ! board [ pos . y ] ) return fill ;
119
+ let bval = board [ pos . y ] [ pos . x ] ;
120
+ return bval === undefined ? fill : bval ;
121
+ } ,
122
+ set : ( pos , v ) => {
123
+ if ( ! limits ) {
124
+ limits = { min : dupe ( pos ) , max : dupe ( pos ) } ;
125
+ }
126
+ limits . min = pos . op ( limits . min , ( a , b ) => Math . min ( a , b ) ) ;
127
+ limits . max = pos . op ( limits . max , ( a , b ) => Math . max ( a , b ) ) ;
128
+ if ( ! board [ pos . y ] ) board [ pos . y ] = [ ] ;
129
+ board [ pos . y ] [ pos . x ] = v ;
130
+ } ,
131
+ forEach : visitor => {
132
+ if ( ! limits ) return ;
133
+ for ( let y = limits . min . y ; y <= limits . max . y ; y ++ ) {
134
+ for ( let x = limits . min . x ; x <= limits . max . x ; x ++ ) {
135
+ visitor ( reso . get ( [ x , y ] ) , [ x , y ] ) ;
136
+ }
137
+ }
138
+ } ,
139
+ copy : ( ) => {
140
+ let nb = makeBoard < T > ( fill ) ;
141
+ reso . forEach ( ( v , pos ) => nb . set ( pos , v ) ) ;
142
+ return nb ;
143
+ } ,
144
+ print : ( printer = v => v as any ) : string => {
145
+ // ratelimit print
146
+ if ( ! limits ) return "*no board to print*" ;
147
+ let ylength = 0 ;
148
+ for ( let y = limits . min . y - 1 ; y <= limits . max . y + 1 ; y ++ ) {
149
+ ylength = Math . max ( y . toString ( ) . length , ylength ) ;
150
+ }
151
+ const resc : string [ ] = [ ] ;
152
+ let llen : number = limits . max . x - limits . min . x + 3 ;
153
+ for ( let y = limits . min . y - 1 ; y <= limits . max . y + 1 ; y ++ ) {
154
+ let line = "" ;
155
+ for ( let x = limits . min . x - 1 ; x <= limits . max . x + 1 ; x ++ ) {
156
+ line += printer ( reso . get ( [ x , y ] ) , [ x , y ] ) ;
157
+ }
158
+ if ( line . length > llen ) llen = line . length ;
159
+ resc . push ( y . toString ( ) . padStart ( ylength , " " ) + " | " + line + " |" ) ;
160
+ }
161
+ resc . unshift (
162
+ " " . repeat ( ylength ) +
163
+ " .-" +
164
+ "-" . repeat ( llen ) +
165
+ "-. " + ( limits . min . y - 1 ) + " .. " + ( limits . max . y + 1 ) ,
166
+ ) ;
167
+ resc . push (
168
+ " " . repeat ( ylength ) +
169
+ " '-" +
170
+ "-" . repeat ( llen ) +
171
+ "-'" ,
172
+ ) ;
173
+ return resc . join ( "\n" ) ;
174
+ } ,
175
+ } ;
176
+ return reso ;
177
+ }
0 commit comments