commit 920a400eeef874eea357335de03a0827823093f6
Author: olikru <olikru@tkruger.se>
Date: Fri, 5 Jan 2024 23:05:23 +0100
happy bday jesus 2022
Diffstat:
220 files changed, 35682 insertions(+), 0 deletions(-)
diff --git a/Makefile b/Makefile
@@ -0,0 +1,13 @@
+MAKE_SUBDIRS=utils day1 day2 day3 day4 day5 day6 day7 day8 day9 day10 day11 day12 day13 day14 day15 day16 day17 day18 day19 day20 day21 day22 day23 day24 day25
+SMAKER=$(addsuffix maker,$(MAKE_SUBDIRS))
+SCLEAN=$(addsuffix clean,$(MAKE_SUBDIRS))
+
+all: $(SMAKER)
+
+clean: $(SCLEAN)
+
+%maker: %
+ make -C $<
+
+%clean: %
+ make -C $< clean
diff --git a/README.md b/README.md
@@ -0,0 +1,22 @@
+Advent of Code '23
+==================
+
+Mine (krutimyltan2's) solutions for the challenges in Advent of Code
+2022. Primarily I try to use C and build a library of useful tools
+that may be reused.
+
+To initialize a new day of solutions, copy the `template` directory to
+a directory called `day<n>`.
+
+Utilities
+---------
+
+The following util modules are available:
+
+* __reading__ -- utils for reading input for file (e.g. readlines)
+* __sd__ -- sized data
+* __smallset__ -- subsets of [n] for small [n], binary impl
+* __stack_sd__ -- stack for sd
+* __stack_str__ -- stack for strings (char pointers)
+* __stack_u64__ -- stack for uint64_t's
+* __ht__ -- hashtable for sd's
diff --git a/TODO b/TODO
@@ -0,0 +1 @@
+- rewrite day19 to an actual solution (meet-in-the-middle)
diff --git a/day1/Makefile b/day1/Makefile
@@ -0,0 +1,23 @@
+CC=clang
+UTILS=../utils/reading.o ../utils/stack_u64.o
+INCLUDES=-I../utils
+
+all: utils common.o uppga uppgb playa
+
+common.o: common.c common.h
+ $(CC) $(CFLAGS) -c common.c $(INCLUDES)
+
+uppga: $(UTILS) common.o uppga.c
+ $(CC) -Wall -o uppga uppga.c common.o $(UTILS) $(INCLUDES)
+
+uppgb: $(UTILS) common.o uppgb.c
+ $(CC) -Wall -o uppgb uppgb.c common.o $(UTILS) $(INCLUDES)
+
+playa: playa.c
+ $(CC) -o playa playa.c
+
+utils:
+ make -C ../utils
+
+clean:
+ rm -rf common.o uppga uppgb playa
diff --git a/day1/common.c b/day1/common.c
@@ -0,0 +1,44 @@
+#include "common.h"
+
+size_t count_elves(char** lines, size_t nlines)
+{
+ size_t c = 0;
+ size_t i = 0;
+ for(i = 0; i < nlines; i++) {
+ if(lines[i][0] == '\n') {
+ c++;
+ }
+ }
+
+ return c+1;
+}
+
+void get_estack(stack_u64* estack, size_t nelves, char** lines, size_t nlines)
+{
+ size_t i;
+ size_t celf = 0;
+
+ if(nelves == 0) return;
+
+ stack_u64_init(&estack[0]);
+
+ for(i = 0; i < nlines; i++) {
+ assert(celf < nelves);
+
+ if(lines[i][0] == '\n') {
+ celf++;
+ stack_u64_init(&estack[celf]);
+ } else {
+ stack_u64_push(&estack[celf], strtoul(lines[i], NULL, 10));
+ }
+ }
+}
+
+void comp_sums(uint64_t* sums, stack_u64* estack, size_t nelves)
+{
+ size_t i,j;
+ for(i = 0; i < nelves; i++) {
+ sums[i] = 0;
+ for(j = 0; j < estack[i].nmemb; j++) sums[i] += estack[i].data[j];
+ }
+}
diff --git a/day1/common.h b/day1/common.h
@@ -0,0 +1,14 @@
+#ifndef COMMON_H_
+#define COMMON_H_
+
+#include <stdio.h>
+#include <stdint.h>
+#include <assert.h>
+#include <reading.h>
+#include <stack_u64.h>
+
+size_t count_elves(char** lines, size_t nlines);
+void get_estack(stack_u64* estack, size_t nelves, char** lines, size_t nlines);
+void comp_sums(uint64_t* sums, stack_u64* estack, size_t nelves);
+
+#endif
diff --git a/day1/input.txt b/day1/input.txt
@@ -0,0 +1,2246 @@
+9057
+8878
+2753
+7027
+3880
+7154
+8022
+6710
+5721
+
+4863
+3690
+3333
+1831
+5293
+6258
+1212
+4255
+2331
+3785
+1505
+3355
+3353
+4416
+
+5918
+3076
+2145
+2712
+6087
+4310
+1084
+5807
+1342
+2770
+5095
+4696
+5842
+4555
+5388
+
+20770
+
+3968
+15647
+3933
+15427
+16179
+
+40721
+
+5837
+4419
+2159
+5173
+5215
+1991
+4842
+5642
+5435
+2853
+1055
+1667
+4361
+2316
+1974
+
+24315
+6376
+6153
+
+3142
+4989
+8864
+3819
+9260
+1273
+2773
+
+9320
+4936
+3707
+2103
+8804
+10586
+2018
+3779
+
+4129
+1019
+5054
+9429
+10526
+6314
+
+13364
+14437
+14046
+7931
+11712
+
+2615
+9583
+7471
+3552
+7532
+5797
+1528
+6479
+2595
+
+8758
+1774
+3734
+5159
+7046
+2195
+9245
+
+12116
+3801
+10950
+1935
+11450
+1091
+5891
+
+7792
+4901
+9062
+8640
+6065
+6405
+3606
+2487
+6606
+
+5460
+3272
+1310
+1439
+3753
+3947
+4472
+4155
+2056
+2435
+2235
+3662
+2933
+1110
+1024
+
+1590
+6814
+12646
+1548
+13624
+5239
+
+3955
+2469
+3104
+1548
+4551
+2307
+4450
+4491
+2233
+4706
+5950
+3395
+6592
+
+17731
+18903
+
+6164
+7718
+7297
+3277
+3592
+3462
+7405
+6164
+2559
+5171
+3337
+
+4797
+9455
+13275
+5801
+12597
+2687
+
+3091
+1153
+1733
+5022
+4441
+3163
+2375
+6388
+6061
+1444
+3255
+5828
+4414
+6171
+
+2841
+17670
+14820
+
+2600
+2598
+14037
+10164
+
+10425
+4618
+7656
+6910
+8761
+11429
+11611
+
+2787
+4826
+1527
+5024
+4252
+1393
+6744
+5665
+4601
+4129
+
+6876
+8156
+7854
+6190
+5234
+8616
+1414
+1076
+5161
+
+6343
+7372
+7806
+2309
+7352
+7249
+4239
+5572
+7220
+3920
+6979
+
+11380
+9322
+10505
+1250
+1122
+1996
+5199
+
+7569
+12600
+14729
+2514
+6841
+
+9414
+9386
+10521
+4974
+11016
+11238
+1334
+
+21696
+27477
+
+11623
+11309
+7708
+6139
+2284
+2789
+4566
+
+16850
+5171
+7647
+5516
+
+24499
+
+4040
+7221
+3197
+7251
+8117
+2221
+1881
+5914
+8381
+
+3786
+2055
+5301
+4144
+2543
+1406
+5609
+5064
+2447
+4892
+2306
+1654
+1650
+3528
+
+4187
+2576
+11910
+8331
+11613
+9093
+2752
+
+4166
+6057
+4585
+1942
+5747
+3102
+2501
+4831
+5681
+6596
+4455
+1125
+4887
+
+2083
+10447
+16506
+
+4971
+3313
+1821
+1493
+5920
+3617
+4857
+3995
+5608
+3679
+1463
+3539
+2600
+3574
+2636
+
+2804
+17188
+6966
+15585
+
+13184
+15490
+9948
+14350
+12788
+
+31669
+
+3318
+2544
+7560
+2170
+9138
+2905
+7010
+
+3933
+4835
+4704
+2140
+1896
+4951
+3870
+4241
+2819
+1065
+3605
+5667
+2361
+2642
+1926
+
+6614
+3288
+3982
+7283
+7086
+2308
+3237
+7365
+6767
+6931
+5417
+5180
+
+40453
+
+4946
+4257
+2590
+5342
+3880
+6297
+1472
+2441
+4054
+3490
+5054
+
+26102
+29920
+
+3726
+
+18600
+1537
+7197
+3487
+
+8193
+8147
+5901
+1975
+3872
+8834
+1623
+6604
+
+4501
+3385
+5321
+6771
+2517
+3943
+2744
+1330
+2277
+2344
+6399
+2090
+3571
+
+8236
+6575
+6362
+3878
+7021
+8613
+3520
+3424
+2606
+5607
+
+10326
+9793
+3341
+7238
+3008
+8188
+11807
+
+3755
+16826
+7885
+11677
+
+5980
+6793
+2393
+5757
+2525
+6496
+6420
+6902
+6755
+1023
+4226
+1451
+5006
+
+6122
+3263
+4273
+2775
+2251
+1076
+2995
+5662
+4189
+2687
+5552
+6586
+2418
+
+9994
+10470
+7802
+9572
+9292
+8390
+8803
+4013
+
+28290
+
+3210
+9126
+1346
+7538
+11536
+10544
+7409
+
+20799
+16110
+
+3374
+3818
+1924
+1637
+3258
+5224
+4741
+2689
+1455
+5948
+4813
+3549
+2772
+2562
+4358
+
+6843
+10575
+7103
+9314
+9901
+3356
+9120
+4552
+
+7709
+3977
+6868
+4640
+4665
+7109
+2662
+5682
+5388
+4256
+7249
+
+69796
+
+8596
+1275
+2723
+2202
+5544
+3687
+4055
+3062
+4137
+4407
+
+4870
+2559
+2177
+5239
+1059
+4440
+2536
+1728
+1520
+2572
+2977
+6815
+4679
+
+9042
+8883
+2705
+16255
+7889
+
+2318
+4232
+1042
+3075
+6202
+7568
+2519
+5918
+1812
+3750
+3845
+
+13323
+33324
+
+13742
+1087
+17146
+14863
+
+2686
+4132
+5052
+4751
+4695
+4528
+4801
+5741
+6027
+1754
+5633
+2427
+4679
+5777
+3143
+
+1533
+4361
+2196
+10184
+3981
+6223
+9273
+
+1296
+11261
+5647
+8657
+7235
+1788
+
+3467
+5537
+10807
+4793
+3452
+12209
+
+5745
+5137
+4002
+4824
+2655
+7597
+5748
+5931
+5264
+4469
+8009
+
+4436
+4866
+3784
+5181
+6240
+6027
+3343
+5780
+2258
+6389
+3827
+6496
+6378
+4831
+
+5894
+7587
+6913
+10950
+6733
+5617
+8084
+
+2446
+5375
+4555
+5327
+1233
+2773
+2701
+5454
+3377
+1217
+5889
+6168
+1056
+
+3468
+2402
+7848
+5652
+1448
+1954
+1021
+7860
+4305
+
+2234
+17391
+5472
+
+2028
+5812
+3091
+5508
+5531
+3554
+3706
+2667
+5670
+4845
+2749
+5569
+4811
+3090
+1063
+
+2144
+5088
+
+20000
+9957
+9049
+3092
+
+12235
+6601
+3496
+16002
+1378
+
+8800
+1236
+5552
+5693
+8482
+3003
+1126
+4612
+5833
+8430
+
+6223
+4640
+1392
+2667
+1602
+2308
+4433
+4148
+6467
+1817
+2926
+3884
+6015
+
+2273
+3007
+4509
+2902
+4170
+2731
+4409
+4873
+4237
+2667
+4243
+5788
+3673
+4582
+4696
+
+27388
+26736
+
+44158
+
+4877
+2172
+5968
+1222
+6456
+6920
+3593
+3631
+7213
+3968
+2398
+7264
+
+7126
+30978
+
+4024
+2766
+2721
+2774
+2807
+1584
+2429
+3517
+5260
+4234
+2381
+5066
+4204
+4737
+4031
+
+1528
+2205
+4533
+5873
+1587
+2708
+4198
+5560
+3413
+4058
+1799
+1088
+4285
+6233
+
+44226
+
+12933
+6090
+14830
+
+5766
+2184
+2552
+4757
+1895
+2328
+1265
+5829
+2645
+6110
+6499
+5920
+6421
+2505
+
+5039
+6271
+5081
+10068
+3856
+7103
+
+5441
+2606
+1249
+2526
+1241
+1914
+3734
+4464
+3855
+4761
+5528
+1419
+2772
+1825
+
+3554
+
+8766
+2123
+7372
+7752
+6260
+5632
+3802
+9546
+7769
+
+9108
+4838
+
+1374
+3720
+7558
+4646
+6793
+4704
+3361
+8038
+6147
+2160
+1983
+
+3133
+3621
+6073
+2533
+1644
+5277
+4276
+1921
+6251
+5273
+1571
+3769
+2155
+
+2721
+3793
+4935
+2950
+2399
+1083
+4213
+4958
+1139
+1140
+2454
+3291
+3865
+1667
+4798
+
+5676
+5904
+1356
+1439
+3241
+2933
+4164
+3887
+4712
+2759
+4390
+1274
+6220
+2557
+
+2049
+4787
+1819
+3172
+5511
+1006
+1373
+6094
+3054
+4914
+6057
+4883
+2867
+5363
+3916
+
+11348
+3724
+6793
+7336
+4032
+11297
+
+4231
+4277
+2982
+2408
+5673
+6805
+4710
+7659
+6866
+
+2950
+4018
+6167
+8316
+7308
+4955
+8341
+1512
+3167
+8493
+
+15665
+14654
+1249
+15313
+4636
+
+1494
+3325
+5902
+1393
+6813
+3900
+2827
+5936
+6589
+6847
+4658
+
+11492
+14548
+5203
+15187
+5937
+
+1358
+2801
+1086
+5190
+4022
+5013
+3511
+4398
+1774
+2194
+1887
+5704
+2012
+1259
+
+4763
+2250
+6915
+4281
+1246
+7242
+6049
+5113
+1187
+2486
+6688
+3275
+
+22345
+1336
+11325
+
+6000
+3641
+1082
+2924
+5477
+3336
+4126
+3981
+5359
+1053
+4299
+5952
+4655
+
+46233
+
+17242
+6366
+7866
+
+12504
+4031
+12664
+9756
+12750
+
+3373
+
+3091
+11142
+15034
+1144
+11747
+
+3129
+2007
+8482
+7205
+7734
+8770
+2213
+5582
+5437
+3223
+
+4471
+2591
+3286
+4446
+5388
+3600
+3357
+2644
+5028
+5569
+5055
+3284
+5597
+4116
+1076
+
+3792
+2354
+8030
+3269
+2483
+1302
+7427
+6148
+3836
+7834
+1663
+
+2930
+5964
+1707
+2899
+4160
+2193
+2705
+5799
+4612
+2741
+2333
+4969
+3117
+5276
+1747
+
+62287
+
+4321
+22825
+5690
+
+7287
+1774
+4464
+2273
+2903
+8920
+4092
+8072
+8763
+
+8885
+7470
+3145
+3523
+5647
+1067
+3048
+
+6923
+6463
+4032
+5923
+1982
+4331
+6323
+1192
+5583
+5470
+6476
+5889
+2991
+
+6697
+1560
+5520
+4516
+4845
+3035
+6047
+4906
+4596
+1934
+7245
+4476
+
+4001
+7227
+5720
+3195
+8505
+6612
+4012
+4050
+8659
+3804
+
+8332
+3362
+4926
+4307
+4779
+1856
+7350
+4068
+8592
+2415
+
+60630
+
+4263
+1716
+8004
+5253
+2004
+5381
+5614
+3020
+5985
+5587
+3563
+
+18645
+10906
+3077
+2255
+
+59591
+
+3203
+7739
+2234
+1421
+3353
+5031
+6395
+5614
+
+6259
+8748
+4341
+7788
+1074
+8497
+3996
+1294
+5197
+5779
+
+10765
+5009
+3541
+2298
+10698
+13317
+
+6181
+1305
+6527
+2125
+9085
+2889
+8794
+3265
+4166
+
+3607
+1912
+1927
+6455
+1043
+6949
+2542
+1552
+3064
+2009
+6587
+
+5574
+4632
+5869
+4312
+1703
+6124
+6479
+4556
+5917
+5890
+4949
+5614
+5576
+
+2267
+7221
+5412
+5721
+2931
+3149
+6934
+3520
+6237
+4317
+1295
+6450
+
+12143
+7105
+2050
+9391
+3017
+10750
+
+4649
+2052
+1856
+3055
+2132
+6630
+5964
+5505
+3395
+2080
+
+4388
+6963
+2613
+1055
+6588
+1348
+3752
+5538
+4524
+7994
+3977
+
+5444
+6078
+8572
+10427
+5423
+3812
+1984
+
+9248
+17691
+12948
+17445
+
+5807
+3737
+5304
+1495
+5162
+1178
+6053
+5597
+5645
+2267
+4333
+3455
+4086
+2024
+4127
+
+5502
+3665
+3494
+1502
+4702
+4563
+5216
+6486
+1931
+6493
+4618
+3960
+1149
+5109
+
+2198
+1411
+4511
+1913
+4173
+4446
+6176
+2305
+4748
+4560
+4048
+5361
+4481
+
+30924
+
+15726
+4014
+20018
+2880
+
+3345
+2576
+4787
+2186
+2156
+2989
+4400
+5147
+5393
+2830
+5869
+4839
+2860
+2134
+
+2400
+2009
+2634
+4431
+7342
+5534
+2072
+5520
+5518
+2998
+3686
+4906
+
+10948
+12532
+11104
+7815
+
+5883
+6111
+4117
+3590
+3295
+3984
+2950
+6814
+1123
+4642
+1770
+2029
+4406
+
+19302
+1549
+10378
+13976
+
+4852
+7261
+4206
+12867
+8400
+11611
+
+2587
+3559
+1415
+5308
+3732
+6752
+3804
+1720
+2570
+5106
+6658
+5105
+6156
+
+7380
+10456
+8378
+10778
+9788
+1299
+10299
+
+3596
+5969
+8288
+3025
+8196
+6410
+5966
+3060
+3015
+1270
+
+14103
+5510
+13362
+19169
+
+3056
+3546
+7784
+2262
+3791
+3159
+5386
+6489
+3421
+7995
+4498
+
+27239
+
+9345
+8921
+5252
+1154
+3189
+1175
+3216
+3282
+9392
+
+2821
+7731
+8002
+1351
+5951
+4544
+3688
+4855
+8082
+1428
+5613
+
+6506
+2529
+6614
+3938
+4404
+5581
+1984
+6242
+7589
+
+8393
+6631
+5200
+9914
+10229
+2405
+3933
+9333
+
+6766
+3486
+11457
+3098
+
+5091
+4105
+1368
+4682
+3094
+4077
+5876
+1958
+1641
+3925
+2969
+3780
+5489
+
+10434
+2285
+2830
+6976
+3561
+6756
+
+3944
+2998
+1874
+4642
+4634
+2155
+2221
+2270
+2446
+1514
+5382
+4333
+5441
+2412
+1789
+
+2433
+4036
+6005
+1551
+7281
+8466
+2141
+4190
+
+5103
+6956
+5839
+2237
+7177
+6397
+11533
+
+7100
+3476
+4592
+6502
+3322
+10524
+2973
+10712
+
+3440
+1323
+1316
+1979
+1168
+6432
+3512
+5739
+2131
+4504
+5233
+3726
+6371
+6125
+
+1917
+3442
+4104
+6123
+1657
+3139
+1690
+3323
+1269
+1407
+5603
+4819
+1787
+2340
+
+11143
+9483
+9438
+12565
+7187
+13478
+
+6406
+2289
+8029
+1790
+5009
+6300
+2521
+
+8040
+6772
+3244
+5246
+6455
+6715
+4024
+3855
+6458
+4945
+4207
+
+4628
+4872
+3344
+5675
+3761
+4467
+5113
+5746
+4140
+
+9532
+1992
+5741
+8559
+4606
+6310
+5183
+
+7530
+13402
+8481
+8327
+
+17909
+7813
+12567
+9674
+
+3329
+6032
+5539
+5513
+2555
+4767
+1085
+3329
+5138
+4448
+4082
+5569
+2732
+3326
+
+2019
+3327
+3701
+3145
+1943
+1467
+1913
+5141
+7475
+7026
+4964
+2353
+
+3375
+1186
+2890
+1248
+5696
+5993
+3804
+1133
+2035
+5068
+4280
+2123
+1890
+
+8675
+10684
+22636
+
+2704
+1093
+9357
+7940
+4843
+1118
+5533
+8943
+6492
+
+67791
+
+7101
+3406
+8840
+3652
+9258
+5329
+4562
+5314
+9146
+
+3673
+13526
+2792
+5659
+13396
+8400
+
+2492
+5265
+5244
+2173
+5032
+1182
+1486
+4561
+4673
+2480
+5148
+1375
+1093
+
+1368
+5899
+6527
+7584
+2148
+2960
+7701
+5381
+6149
+2589
+7496
+
+12206
+11842
+11444
+12447
+
+3417
+5044
+7116
+5491
+9020
+8610
+1047
+5725
+2712
+
+9153
+1836
+3337
+1686
+6044
+8786
+7476
+1688
+
+17559
+10138
+16446
+
+15625
+16403
+16979
+7402
+
+3561
+2910
+12805
+8128
+13171
+5786
+
+1332
+
+1135
+5954
+9216
+5471
+3494
+9353
+6330
+4152
+
+2031
+2180
+1544
+2509
+3894
+2882
+1460
+6647
+4655
+3164
+6691
+2156
+5754
+
+2309
+5397
+6055
+5585
+9712
+9731
+9274
+
+9865
+7291
+4863
+10688
+4135
+4572
+7321
+5603
+
+1428
+5533
+4032
+1648
+1676
+5556
+1186
+4594
+5915
+2477
+4923
+5393
+2101
+2509
+1250
+
+2388
+2255
+3768
+5340
+4357
+5600
+4198
+6423
+5974
+5673
+3717
+3275
+5871
+3250
+
+11192
+1266
+3583
+10707
+11653
+3264
+6641
+
+2009
+12343
+2394
+2147
+1560
+4352
+
+5152
+6000
+6725
+3479
+1229
+1599
+3971
+6829
+8654
+
+7486
+15798
+2011
+9551
+15283
+
+8934
+27039
+
+2048
+7506
+3661
+7298
+8557
+6387
+6496
+4471
+8596
+5325
+
+1760
+2615
+1038
+9295
+6394
+7329
+5015
+4727
+9584
+
+40347
+
+5992
+9771
+14112
+
+13049
+14348
+13202
+10630
+9351
+
+8778
+9152
+10173
+8648
+4552
+4300
+5921
+9924
+
+26578
+34718
+
+2974
+3130
+4319
+4116
+3484
+5362
+5583
+2885
+4526
+2756
+5977
+2629
+2429
+1755
+1278
+
+2848
+4821
+2207
+6922
+6699
+1999
+2354
+1922
+2133
+4496
+2510
+6509
+6929
+
+5345
+3244
+2145
+1243
+1245
+2210
+5939
+3311
+6482
+5700
+3395
+2508
+3893
+6405
+
+3618
+2718
+4854
+1334
+3478
+3043
+3466
+1028
+2627
+3873
+4878
+5160
+6017
+4880
+1342
+
+9909
+7167
+7465
+7787
+10618
+6259
+3751
+1488
+
+24782
+13684
+1905
+
+5325
+9319
+7321
+6398
+8841
+3773
+2807
+9032
+2572
+
+5346
+7500
+8693
+9429
+1728
+1303
+2467
+3959
+8196
+
+6220
+6193
+4246
+3802
+6433
+4710
+3059
+2880
+6077
+1924
+5892
+
+3421
+1973
+9474
+3990
+15878
+
+6757
+9558
+9440
+8896
+5221
+3819
+6669
+1578
+7307
+
+2015
+5934
+2351
+4738
+6504
+1748
+5112
+4067
+1623
+1944
+6297
+3300
+1089
+
+1757
+4617
+8124
+6837
+4685
+9532
+11427
+
+9094
+6552
+3882
+5341
+10752
+5572
+5882
+
+5806
+3599
+1885
+4608
+6756
+4656
+1160
+4783
+2759
+3006
+3044
+5491
+6877
+
+6295
+18921
+23198
+
+2201
+2488
+1050
+1414
+2799
+3883
+7092
+4746
+3719
+3211
+1548
+
+2656
+3600
+5148
+2300
+5547
+8226
+6952
+2611
+2268
+6490
+
+5499
+8937
+12091
+1429
+9253
+2187
+2660
+
+12898
+
+3536
+3120
+6811
+2427
+2710
+2100
+2030
+7003
+3932
+3514
+6390
+6017
+
+7645
+3909
+2219
+2290
+1401
+1812
+3180
+7733
+2547
+2653
diff --git a/day1/playa.c b/day1/playa.c
@@ -0,0 +1,23 @@
+#include <stdio.h>
+
+int main()
+{
+ FILE* f = fopen("input.txt", "r");
+
+ int c, a=0, b=0, lc=0, ca=0, m=0;
+ while((c = getc(f)) != EOF) {
+ if(c == '\n') {
+ if(lc == '\n') {
+ if(m < b) m = b;
+ b = 0;
+ } else {
+ b += ca;
+ ca = 0;
+ }
+ } else {
+ ca = 10*ca + (int) (c - '0');
+ }
+ lc = c;
+ }
+ printf("%d\n", m);
+}
diff --git a/day1/uppga.c b/day1/uppga.c
@@ -0,0 +1,28 @@
+#include "common.h"
+
+uint64_t max(uint64_t* sums, size_t nelves)
+{
+ size_t i;
+ uint64_t cmax = 0;
+ for(i = 0; i < nelves; i++) {
+ if(sums[i] > cmax) cmax = sums[i];
+ }
+
+ return cmax;
+}
+
+int main(int argc, char** argv)
+{
+ char** lines;
+ size_t nlines = readlines(&lines, "input.txt");
+ printf("#lines: %zu\n", nlines);
+ size_t nelves = count_elves(lines, nlines);
+ printf("#elves: %zu\n", nelves);
+
+ stack_u64 estack[nelves];
+ get_estack(estack, nelves, lines, nlines);
+ uint64_t sums[nelves];
+ comp_sums(sums, estack, nelves);
+
+ printf("max: %llu\n", max(sums, nelves));
+}
diff --git a/day1/uppgb.c b/day1/uppgb.c
@@ -0,0 +1,41 @@
+#include "common.h"
+
+static inline int _rcmpu64(uint64_t n, uint64_t m)
+{
+ if(n < m) {
+ return -1;
+ } else if(n == m) {
+ return 0;
+ }
+
+ return 1;
+}
+
+static int cmpu64(const void *p1, const void *p2)
+{
+ return _rcmpu64(*(uint64_t*) p1, *(uint64_t*) p2);
+}
+
+void sort(uint64_t* sums, size_t nelves)
+{
+ qsort(sums, nelves, sizeof(*sums), cmpu64);
+}
+
+int main(int argc, char** argv)
+{
+ char** lines;
+ size_t nlines = readlines(&lines, "input.txt");
+ printf("#lines: %zu\n", nlines);
+ size_t nelves = count_elves(lines, nlines);
+ printf("#elves: %zu\n", nelves);
+
+ stack_u64 estack[nelves];
+ get_estack(estack, nelves, lines, nlines);
+ uint64_t sums[nelves];
+ comp_sums(sums, estack, nelves);
+
+ sort(sums, nelves);
+ uint64_t* top = &sums[nelves-3];
+ uint64_t tsum = top[0] + top[1] + top[2];
+ printf("sum: %llu\n", tsum);
+}
diff --git a/day10/Makefile b/day10/Makefile
@@ -0,0 +1,20 @@
+CC=clang
+UTILS=../utils/reading.o
+INCLUDES=-I../utils
+
+all: utils common.o uppga uppgb
+
+common.o: common.c common.h
+ $(CC) $(CFLAGS) -c common.c $(INCLUDES)
+
+uppga: $(UTILS) common.o uppga.c
+ $(CC) -Wall -o uppga uppga.c common.o $(UTILS) $(INCLUDES)
+
+uppgb: $(UTILS) common.o uppgb.c
+ $(CC) -Wall -o uppgb uppgb.c common.o $(UTILS) $(INCLUDES)
+
+utils:
+ make -C ../utils
+
+clean:
+ rm -rf common.o uppga uppgb
diff --git a/day10/common.c b/day10/common.c
@@ -0,0 +1,27 @@
+#include "common.h"
+
+#define MAX_CYCLES 240
+
+int* parse(char** lines, size_t nlines)
+{
+ int* r = malloc(MAX_CYCLES * sizeof(*r) + 2);
+
+ r[0] = 1;
+ int t;
+ size_t i, j, c = 0;
+ for(i = 0; i < nlines; i++) {
+ if(lines[i][0] == 'n') {
+ r[c+1] = r[c];
+ c++;
+ } else {
+ sscanf(lines[i], "addx %d\n", &t);
+ r[c+1] = r[c];
+ r[c+2] = r[c] + t;
+ c += 2;
+ }
+
+ if(c >= 240) break;
+ }
+
+ return r;
+}
diff --git a/day10/common.h b/day10/common.h
@@ -0,0 +1,11 @@
+#ifndef COMMON_H_
+#define COMMON_H_
+
+#include <stdio.h>
+#include <stdint.h>
+#include <assert.h>
+#include <reading.h>
+
+int* parse(char** lines, size_t nlines);
+
+#endif
diff --git a/day10/einput b/day10/einput
@@ -0,0 +1,146 @@
+addx 15
+addx -11
+addx 6
+addx -3
+addx 5
+addx -1
+addx -8
+addx 13
+addx 4
+noop
+addx -1
+addx 5
+addx -1
+addx 5
+addx -1
+addx 5
+addx -1
+addx 5
+addx -1
+addx -35
+addx 1
+addx 24
+addx -19
+addx 1
+addx 16
+addx -11
+noop
+noop
+addx 21
+addx -15
+noop
+noop
+addx -3
+addx 9
+addx 1
+addx -3
+addx 8
+addx 1
+addx 5
+noop
+noop
+noop
+noop
+noop
+addx -36
+noop
+addx 1
+addx 7
+noop
+noop
+noop
+addx 2
+addx 6
+noop
+noop
+noop
+noop
+noop
+addx 1
+noop
+noop
+addx 7
+addx 1
+noop
+addx -13
+addx 13
+addx 7
+noop
+addx 1
+addx -33
+noop
+noop
+noop
+addx 2
+noop
+noop
+noop
+addx 8
+noop
+addx -1
+addx 2
+addx 1
+noop
+addx 17
+addx -9
+addx 1
+addx 1
+addx -3
+addx 11
+noop
+noop
+addx 1
+noop
+addx 1
+noop
+noop
+addx -13
+addx -19
+addx 1
+addx 3
+addx 26
+addx -30
+addx 12
+addx -1
+addx 3
+addx 1
+noop
+noop
+noop
+addx -9
+addx 18
+addx 1
+addx 2
+noop
+noop
+addx 9
+noop
+noop
+noop
+addx -1
+addx 2
+addx -37
+addx 1
+addx 3
+noop
+addx 15
+addx -21
+addx 22
+addx -6
+addx 1
+noop
+addx 2
+addx 1
+noop
+addx -10
+noop
+noop
+addx 20
+addx 1
+addx 2
+addx 2
+addx -6
+addx -11
+noop
+noop
+noop
diff --git a/day10/input b/day10/input
@@ -0,0 +1,138 @@
+noop
+noop
+addx 5
+addx 29
+addx -28
+addx 5
+addx -1
+noop
+noop
+addx 5
+addx 12
+addx -6
+noop
+addx 4
+addx -1
+addx 1
+addx 5
+addx -31
+addx 32
+addx 4
+addx 1
+noop
+addx -38
+addx 5
+addx 2
+addx 3
+addx -2
+addx 2
+noop
+addx 3
+addx 2
+addx 5
+addx 2
+addx 3
+noop
+addx 2
+addx 3
+noop
+addx 2
+addx -32
+addx 33
+addx -20
+addx 27
+addx -39
+addx 1
+noop
+addx 5
+addx 3
+noop
+addx 2
+addx 5
+noop
+noop
+addx -2
+addx 5
+addx 2
+addx -16
+addx 21
+addx -1
+addx 1
+noop
+addx 3
+addx 5
+addx -22
+addx 26
+addx -39
+noop
+addx 5
+addx -2
+addx 2
+addx 5
+addx 2
+addx 23
+noop
+addx -18
+addx 1
+noop
+noop
+addx 2
+noop
+noop
+addx 7
+addx 3
+noop
+addx 2
+addx -27
+addx 28
+addx 5
+addx -11
+addx -27
+noop
+noop
+addx 3
+addx 2
+addx 5
+addx 2
+addx 27
+addx -26
+addx 2
+addx 5
+addx 2
+addx 4
+addx -3
+addx 2
+addx 5
+addx 2
+addx 3
+addx -2
+addx 2
+noop
+addx -33
+noop
+noop
+noop
+noop
+addx 31
+addx -26
+addx 6
+noop
+noop
+addx -1
+noop
+addx 3
+addx 5
+addx 3
+noop
+addx -1
+addx 5
+addx 1
+addx -12
+addx 17
+addx -1
+addx 5
+noop
+noop
+addx 1
+noop
+noop
diff --git a/day10/uppga.c b/day10/uppga.c
@@ -0,0 +1,17 @@
+#include "common.h"
+
+int main(int argc, char** argv)
+{
+ char** lines;
+ size_t nlines = readlines(&lines, "input");
+
+ int* r = parse(lines, nlines);
+
+ int strength = 0;
+ size_t i;
+
+ for(i = 20; i < 221; i += 40)
+ strength += i * r[i-1];
+
+ printf("%d\n", strength);
+}
diff --git a/day10/uppgb.c b/day10/uppgb.c
@@ -0,0 +1,22 @@
+#include "common.h"
+
+int main(int argc, char** argv)
+{
+ char** lines;
+ size_t nlines = readlines(&lines, "input");
+
+ int* r = parse(lines, nlines);
+
+ size_t i,j;
+ for(j = 0; j < 6; j++) {
+ for(i = 0; i < 40; i++) {
+ if(r[j*40+i] == i-1 || r[j*40+i] == i+1 || r[j*40+i] == i)
+ printf("#");
+ else
+ printf(".");
+ }
+ printf("\n");
+ }
+
+ free(r);
+}
diff --git a/day11/Makefile b/day11/Makefile
@@ -0,0 +1,20 @@
+CC=clang
+UTILS=../utils/reading.o
+INCLUDES=-I../utils
+
+all: utils common.o uppga uppgb
+
+common.o: common.c common.h
+ $(CC) $(CFLAGS) -c common.c $(INCLUDES)
+
+uppga: $(UTILS) common.o uppga.c
+ $(CC) -Wall -o uppga uppga.c common.o $(UTILS) $(INCLUDES)
+
+uppgb: $(UTILS) common.o uppgb.c
+ $(CC) -Wall -o uppgb uppgb.c common.o $(UTILS) $(INCLUDES)
+
+utils:
+ make -C ../utils
+
+clean:
+ rm -rf common.o uppga uppgb
diff --git a/day11/common.c b/day11/common.c
@@ -0,0 +1,122 @@
+#include "common.h"
+
+monkis parse_monkis(char** lines, size_t nlines, int mods)
+{
+ monkis r;
+ size_t i,j;
+ uint64_t t;
+
+ r.mod = malloc(nlines * sizeof(*r.mod));
+
+ r.n = 0;
+ r.nitems = 0;
+ for(i = 0; i < nlines; i++) {
+ if(lines[i][0] == 'M') r.n++;
+ else if(strlen(lines[i]) > 2) {
+ if(lines[i][2] == 'S') {
+ char* p = lines[i];
+ while((p = sread_next_u64(&t, p)) != NULL) r.nitems++;
+ } else if(lines[i][2] == 'T') {
+ sread_next_u64(&(r.mod[r.n-1]), lines[i]);
+ }
+ }
+ }
+
+ r.mod = realloc(r.mod, r.n * sizeof(*r.mod));
+
+ r.rmod = malloc(r.n * sizeof(*r.rmod));
+ memcpy(r.rmod, r.mod, r.n * sizeof(*r.rmod));
+ if(!mods) for(i = 0; i < r.n; i++) r.mod[i] = UINT64_MAX;
+
+ r.fnext = malloc(r.n * sizeof(*r.fnext));
+ r.tnext = malloc(r.n * sizeof(*r.tnext));
+ r.heads = malloc(r.n * sizeof(*r.heads));
+
+ r.inspections = calloc(r.n, sizeof(*r.inspections));
+
+ r.items = malloc(r.nitems * r.n * sizeof(*r.items));
+
+ size_t cm = 0, ci = 0;
+ for(i = 0; i < nlines; i++) {
+ if(strlen(lines[i]) > 2) {
+ if(lines[i][4] == 'I') {
+ sread_next_u64(&t, lines[i]);
+ if(lines[i][7] == 't') r.tnext[cm] = t;
+ else r.fnext[cm] = t;
+ } else if(lines[i][2] == 'S') {
+ SIMPLEQ_INIT(&r.heads[cm]);
+ char* p = lines[i];
+ while((p = sread_next_u64(&t, p)) != NULL) {
+ struct entry* new_entry = malloc(sizeof(*new_entry));
+ new_entry->index = ci;
+ SIMPLEQ_INSERT_TAIL(&r.heads[cm], new_entry, entries);
+ for(j = 0; j < r.n; j++) r.items[ci * r.n + j] = t % r.mod[j];
+ ci++;
+ }
+ }
+ } else {
+ cm++;
+ }
+ }
+ return r;
+}
+
+void mmonkey(monkis m, size_t i)
+{
+ uint64_t* tmp;
+ struct entry* np;
+ size_t j;
+
+ while(!SIMPLEQ_EMPTY(&m.heads[i])) {
+ m.inspections[i]++;
+ np = SIMPLEQ_FIRST(&m.heads[i]);
+ SIMPLEQ_REMOVE_HEAD(&m.heads[i], entries);
+ tmp = &(m.items[np->index * m.n]);
+ for(j = 0; j < m.n; j++) tmp[j] = (m.operate)(tmp[j], i) % m.mod[j];
+
+ size_t new_index = (tmp[i] % m.rmod[i]) == 0 ? m.tnext[i] : m.fnext[i];
+
+ SIMPLEQ_INSERT_TAIL(&m.heads[new_index], np, entries);
+ }
+}
+
+void mround(monkis m)
+{
+ size_t i;
+ for(i = 0; i < m.n; i++) mmonkey(m, i);
+}
+
+uint64_t get_result(monkis m)
+{
+ uint64_t tmax[2] = {0,0};
+
+ size_t i;
+ for(i = 0; i < m.n; i++) {
+ if(m.inspections[i] > tmax[0])
+ tmax[0] = m.inspections[i];
+ if(tmax[0] > tmax[1])
+ tmax[0] ^= tmax[1] ^= tmax[0] ^= tmax[1];
+ }
+
+ return tmax[0]*tmax[1];
+}
+
+void let_the_monkis_out(monkis m)
+{
+ free(m.mod);
+ free(m.tnext);
+ free(m.fnext);
+
+ free(m.items);
+
+ size_t i;
+ struct entry* t;
+ for(i = 0; i < m.n; i++) {
+ while(!SIMPLEQ_EMPTY(&m.heads[i])) {
+ t = SIMPLEQ_FIRST(&m.heads[i]);
+ SIMPLEQ_REMOVE_HEAD(&m.heads[i], entries);
+ free(t);
+ }
+ }
+ free(m.heads);
+}
diff --git a/day11/common.h b/day11/common.h
@@ -0,0 +1,39 @@
+#ifndef COMMON_H_
+#define COMMON_H_
+
+#include <stdio.h>
+#include <stdint.h>
+#include <assert.h>
+#include <reading.h>
+#include <sys/queue.h>
+
+struct entry {
+ size_t index;
+ SIMPLEQ_ENTRY(entry) entries;
+};
+
+typedef struct {
+ size_t n;
+ uint64_t* mod;
+ uint64_t* rmod;
+ size_t* fnext;
+ size_t* tnext;
+
+ uint64_t* inspections;
+
+ size_t nitems;
+ uint64_t* items;
+
+ SIMPLEQ_HEAD(listhead, entry)* heads;
+
+ uint64_t (*operate)(uint64_t, size_t);
+} monkis;
+
+void print_monkis(monkis m);
+monkis parse_monkis(char** lines, size_t nlines, int mods);
+void mmonkey(monkis m, size_t i);
+void mround(monkis m);
+uint64_t get_result(monkis m);
+void let_the_monkis_out(monkis m);
+
+#endif
diff --git a/day11/einput b/day11/einput
@@ -0,0 +1,27 @@
+Monkey 0:
+ Starting items: 79, 98
+ Operation: new = old * 19
+ Test: divisible by 23
+ If true: throw to monkey 2
+ If false: throw to monkey 3
+
+Monkey 1:
+ Starting items: 54, 65, 75, 74
+ Operation: new = old + 6
+ Test: divisible by 19
+ If true: throw to monkey 2
+ If false: throw to monkey 0
+
+Monkey 2:
+ Starting items: 79, 60, 97
+ Operation: new = old * old
+ Test: divisible by 13
+ If true: throw to monkey 1
+ If false: throw to monkey 3
+
+Monkey 3:
+ Starting items: 74
+ Operation: new = old + 3
+ Test: divisible by 17
+ If true: throw to monkey 0
+ If false: throw to monkey 1
diff --git a/day11/input b/day11/input
@@ -0,0 +1,55 @@
+Monkey 0:
+ Starting items: 54, 82, 90, 88, 86, 54
+ Operation: new = old * 7
+ Test: divisible by 11
+ If true: throw to monkey 2
+ If false: throw to monkey 6
+
+Monkey 1:
+ Starting items: 91, 65
+ Operation: new = old * 13
+ Test: divisible by 5
+ If true: throw to monkey 7
+ If false: throw to monkey 4
+
+Monkey 2:
+ Starting items: 62, 54, 57, 92, 83, 63, 63
+ Operation: new = old + 1
+ Test: divisible by 7
+ If true: throw to monkey 1
+ If false: throw to monkey 7
+
+Monkey 3:
+ Starting items: 67, 72, 68
+ Operation: new = old * old
+ Test: divisible by 2
+ If true: throw to monkey 0
+ If false: throw to monkey 6
+
+Monkey 4:
+ Starting items: 68, 89, 90, 86, 84, 57, 72, 84
+ Operation: new = old + 7
+ Test: divisible by 17
+ If true: throw to monkey 3
+ If false: throw to monkey 5
+
+Monkey 5:
+ Starting items: 79, 83, 64, 58
+ Operation: new = old + 6
+ Test: divisible by 13
+ If true: throw to monkey 3
+ If false: throw to monkey 0
+
+Monkey 6:
+ Starting items: 96, 72, 89, 70, 88
+ Operation: new = old + 4
+ Test: divisible by 3
+ If true: throw to monkey 1
+ If false: throw to monkey 2
+
+Monkey 7:
+ Starting items: 79
+ Operation: new = old + 8
+ Test: divisible by 19
+ If true: throw to monkey 4
+ If false: throw to monkey 5
diff --git a/day11/uppga.c b/day11/uppga.c
@@ -0,0 +1,39 @@
+#include "common.h"
+
+// I really don't want to parse this from input
+uint64_t operation(uint64_t x, size_t i)
+{
+ if(i == 0) {
+ return (x * 7)/3;
+ } else if(i == 1) {
+ return (x * 13)/3;
+ } else if(i == 2) {
+ return (x + 1)/3;
+ } else if(i == 3) {
+ return (x * x)/3;
+ } else if(i == 4) {
+ return (x + 7)/3;
+ } else if(i == 5) {
+ return (x + 6)/3;
+ } else if(i == 6) {
+ return (x + 4)/3;
+ }
+ return (x + 8)/3;
+}
+
+
+int main(int argc, char** argv)
+{
+ char** lines;
+ size_t nlines = readlines(&lines, "input");
+
+ monkis m = parse_monkis(lines, nlines, 0);
+ m.operate = operation;
+
+ size_t i;
+ for(i = 0; i < 20; i++) mround(m);
+
+ printf("%llu\n", get_result(m));
+
+ let_the_monkis_out(m);
+}
diff --git a/day11/uppgb.c b/day11/uppgb.c
@@ -0,0 +1,38 @@
+#include "common.h"
+
+// I really don't want to parse this from input
+uint64_t operation(uint64_t x, size_t i)
+{
+ if(i == 0) {
+ return x * 7;
+ } else if(i == 1) {
+ return x * 13;
+ } else if(i == 2) {
+ return x + 1;
+ } else if(i == 3) {
+ return x * x;
+ } else if(i == 4) {
+ return x + 7;
+ } else if(i == 5) {
+ return x + 6;
+ } else if(i == 6) {
+ return x + 4;
+ }
+ return x + 8;
+}
+
+int main(int argc, char** argv)
+{
+ char** lines;
+ size_t nlines = readlines(&lines, "input");
+
+ monkis m = parse_monkis(lines, nlines, 1);
+ m.operate = operation;
+
+ size_t i;
+ for(i = 0; i < 10000; i++) mround(m);
+
+ printf("%llu\n", get_result(m));
+
+ let_the_monkis_out(m);
+}
diff --git a/day12/Makefile b/day12/Makefile
@@ -0,0 +1,20 @@
+CC=clang
+UTILS=../utils/reading.o
+INCLUDES=-I../utils
+
+all: utils common.o uppga uppgb
+
+common.o: common.c common.h
+ $(CC) $(CFLAGS) -c common.c $(INCLUDES)
+
+uppga: $(UTILS) common.o uppga.c
+ $(CC) -Wall -o uppga uppga.c common.o $(UTILS) $(INCLUDES)
+
+uppgb: $(UTILS) common.o uppgb.c
+ $(CC) -Wall -o uppgb uppgb.c common.o $(UTILS) $(INCLUDES)
+
+utils:
+ make -C ../utils
+
+clean:
+ rm -rf common.o uppga uppgb
diff --git a/day12/common.c b/day12/common.c
@@ -0,0 +1,62 @@
+#include "common.h"
+
+uint8_t** parse(size_t* h, size_t* w, size_t* pos, char** lines, size_t nlines)
+{
+ size_t i,j;
+
+ *h = nlines;
+ *w = strlen(lines[0])-1;
+
+ uint8_t** grid = malloc(*h * sizeof(*grid));
+ for(i = 0; i < *h; i++)
+ grid[i] = malloc(*w * sizeof(**grid));
+
+ for(i = 0; i < nlines; i++) {
+ for(j = 0; j < *w; j++) {
+ if(lines[i][j] == 'S') {
+ pos[0] = i; pos[1] = j;
+ lines[i][j] = 'a';
+ } else if(lines[i][j] == 'E') {
+ pos[2] = i; pos[3] = j;
+ lines[i][j] = 'z';
+ }
+ grid[i][j] = (uint8_t) (lines[i][j] - 'a');
+ }
+ }
+
+ return grid;
+}
+
+
+void calculate_steps(uint64_t* stepsto, size_t ex, size_t ey, size_t h, size_t w, uint8_t** grid)
+{
+ size_t i;
+ SIMPLEQ_HEAD(listhead, entry) head = SIMPLEQ_HEAD_INITIALIZER(head);
+
+ struct entry *pos = malloc(sizeof(*pos));
+ pos->x = ex; pos->y = ey;
+ SIMPLEQ_INSERT_TAIL(&head, pos, entries);
+
+ while (!SIMPLEQ_EMPTY(&head)) {
+ pos = SIMPLEQ_FIRST(&head);
+ size_t x = pos->x, y = pos->y;
+ SIMPLEQ_REMOVE_HEAD(&head, entries);
+ int delta[4][2] = {{-1,0},{1,0},{0,-1},{0,1}};
+ for(i = 0; i < 4; i++) {
+ int cx = (int) x + delta[i][0];
+ int cy = (int) y + delta[i][1];
+ if(cx < 0 || cy < 0 || cx >= h || cy >= w) {
+ continue;
+ }
+ if(grid[cx][cy] + 1 >= grid[x][y]) {
+ if(stepsto[x * w + y] + 1 < stepsto[cx * w + cy]) {
+ stepsto[cx * w + cy] = stepsto[x * w + y] + 1;
+ struct entry *npos = malloc(sizeof(*npos));
+ npos->x = cx; npos->y = cy;
+ SIMPLEQ_INSERT_TAIL(&head, npos, entries);
+ }
+ }
+ }
+ free(pos);
+ }
+}
diff --git a/day12/common.h b/day12/common.h
@@ -0,0 +1,20 @@
+#ifndef COMMON_H_
+#define COMMON_H_
+
+#include <stdio.h>
+#include <stdint.h>
+#include <assert.h>
+#include <sys/queue.h>
+#include <reading.h>
+
+struct entry {
+ size_t x;
+ size_t y;
+
+ SIMPLEQ_ENTRY(entry) entries;
+};
+
+uint8_t** parse(size_t* h, size_t* w, size_t* pos, char** lines, size_t nlines);
+void calculate_steps(uint64_t* stepsto, size_t ex, size_t ey, size_t h, size_t w, uint8_t** grid);
+
+#endif
diff --git a/day12/einput b/day12/einput
@@ -0,0 +1,5 @@
+Sabqponm
+abcryxxl
+accszExk
+acctuvwj
+abdefghi
diff --git a/day12/input b/day12/input
@@ -0,0 +1,41 @@
+abccccccccaaaaccccaaacaccccaaaaaacccccccccccaaaccccccccccaaaaaaacccccccccccccccccccccccccccccacaaaccccccccccccccccccccccccccccccccccccccccaaaaa
+abccccccccaaaaccaaaaaaaacccaaaaaacccccccccccaaaacccccccccaaaaaaaaaacccccccccccccccaaccccccccaaaaaccaaaccaacccccccccccccccccccccccccccccccaaaaaa
+abcccccccccaacccaaaaaaaaccccaaaaacccccccccccaaaacccccccaaaaaaaaaaaaaccccccccccaaaaaaccccccccaaaaaaaaaaaaaaccccccccccccccccaaaccccccccccccaaaaaa
+abcccccccccccccccaaaaaccccccaacaaccccaacccccaaacccccccaaaaaaaaaaaaaaccccccccccaaaaaaacccccccccaaaaacaaaaaaccccccccccccccccaaccccccccccccccccaaa
+abccccccccccccccccaaaaaccccccccccaaccaacccccccccccccccaaaaacaaaacacacccccaacccaaaaaaaacccccccaaaaacaaaaaaaccccccccccccccccaaacccccccccccccccaaa
+abcccccccccccccccaaaaaaccccccccccaaaaaaccccccccccccccccaaaaaaaacaaaaacaaaaaccccaaaaaaacccccccaacaacaaaaaaaaccccccccaaaaccaakcccccccccccccccccaa
+abcccccccccccccccaaaccacccccccccccaaaaaaacccccccaaaccccccaaaaaacaaaaaccaaaaaccaaaaaaccccccccccccaacaaaaaaaacccccccccaaaakkkklllcccccccccccccccc
+abcccccaaaccccccccccccccccccccccccaaaaaaacccccccaaacacccaaaaaaaaaaaaacaaaaaaccaaaaaacccccccccccccccccaaaccccccccccccaaakkkkkllllcccccccaacccccc
+abccccaaaacccccccccccccccccccccccaaaaaacccccccaccaaaaaccaaaaaaaaaaaaacaaaaccccccccaaccccccccccccccccccaaccccccccccccckkkkkkpllllccccaaaaaaccccc
+abccccaaaacccccccccccccccccaaacccaaaaaacccccccaaaaaaaacccaaaaacaaaaaacccaaaccccccccccccccccccccccccccccccccccccccccckkkkpppppplllcccaaaaacccccc
+abcccccaaaccccccccccccccccaaaacccccccaaccccccccaaaaacccccaaaccccaaacccccccccccccccccccccccccaaccccccccccccccccccjjjkkkkpppppppplllcccaaaaaacccc
+abccccccccccccccccccccccccaaaaccccccccccccccccccaaaaacccccccccccccccccccccccccccccccccccccccaaaaaccccccccccccjjjjjjkkkrppppuppplllccccaaaaacccc
+abccccccccccccccaaaccccccccaaaccccccccccccccccccaacaaccccccccccccccccccccccaaaccccccccaacccaaaaaccccccccccccjjjjjjjjrrrpuuuuuppplllcccccaaacccc
+abcccccaaccaacccaaacacccccccccccccccccccccccccacaaaaccccccccccccccccccccccaaaaaaccccaaaacccaaaaaaccaccccccccjjjrrrrrrrrruuuuuppplllmcccddcccccc
+abcccccaaaaaacaaaaaaaaccccccccccccccccccccccccaacaaaccccccccccccccccccccccaaaaaaccccaaaaaacccaaaaccaaacaaacjjjrrrrrrrrruuuxuuupqqlmmmmddddccccc
+abcccccaaaaaccaaaaaaaaccccccccccccccccccccccccaaaaaccccaacccccccccccccccccaaaaaacccccaaaacccaacccccaaaaaaacjjjrrrrtuuuuuuxxyuvqqqqmmmmmddddcccc
+abaacccaaaaaaccaaaaaccccccccccccccccccaaaaccccaaaaaaccaaaccccccccccccccccccaaaaaccccaaaaaccccccccccaaaaaaccjjjrrrtttuuuuuxxyvvvqqqqqmmmmdddcccc
+abaaccaaaaaaaaccaaaaaccccccccccccccccaaaaaaaaaaaaaaaacaaacaaaccccccccccccccaacaacaacaacaaccccccccaaaaaaaaccijjqqrtttxxxxxxyyvvvvvqqqqmmmmdddccc
+abaaccaaaaaaaacaaaaaaccccccccccccccccaaaaaaaaaaaaaaaaaaaaaaaacccccccccccccccaaacaaaccccccccccaaccaaaaaaaaaciiiqqqttxxxxxxxyyvvvvvvvqqqmmmdddccc
+abaaaccccaaccccaaaccacccccccccccccccccaaaaaaccccaacaaaaaaaaaaccaaaccccccccccaaaaaaaccccccccccaaaaaaaaaaaaaaiiiqqqtttxxxxxxyyyyyyvvvqqqmmmdddccc
+SbaaaccccaacccccccccccccccccccccccccaaaaaaaaccccaacccaaaaaaccaaaaaaccccccccccaaaaaacccccccccccaaaaacaaacaaaaiiiqqqttxxxxEzzyyyyyvvvqqqmmmdddccc
+abaaaccccccccccccccccccccccccccccccaaaaaaaaaaccccccccaaaaaaccaaaaaaccccccccccaaaaaaaaccccccccaaaaaacaaaccaaaiiiqqqtttxxxyyyyyyvvvvqqqmmmdddcccc
+abaccccccaacccccccccccccccccccccccccaaaaaaaaaaaacccccaaaaaaacaaaaaacccccccccaaaaaaaaacccccccaaaaaaaacaaaaaaaiiiqqqtttxxyyyyyyvvvvqqqqnnmeddcccc
+abccccccaaaaccccccccccccaaaccccccccccccaaaaaaaaaaacccaaacaaacaaaaacccccccccaaaaaaaaaacccccccaaaaaaaaccaaaaaaaiiiqqtttxxyyyyyywvrrrrnnnneeeccccc
+abccccccaaaacccccaacccccaaaacccccccccccaaaccaaaaaacccacccccccaaaaacccccccccaaacaaacccccccccccccaacccccccaaaaaiiqqqttxxwywwyyywwrrrnnnneeeeccccc
+abccccccaaaaccaacaaaccccaaaaccccccaacccaacccaaaaaccccccccccccccccccccccccccccccaaacccccccccccccaaccccccaaaaaaiiqqqttwwwwwwwwywwrrrnnneeeecccccc
+abccccccccccccaaaaacccccaaaccccacaaacccccccccaaaaacccccccccccccccccccccccccccccaaacccccccccccccccccccccaaaaaaiiqqpsswwwwsswwwwwrrnnneeeeccccccc
+abcccccccccccccaaaaaacccccccccaaaaacaacccccccaacaacccccaaccccccccccccccccccccccccccccccccccccccccccccccaccaahhhpppssssssssswwwwrrnnneeeaccccccc
+abcccccccccccaaaaaaaacccccccccaaaaaaaacccccaaccccccaaacaaccccccccccccccccccccccccccccccccccccaaaccaccccccccchhhpppsssssssssswwrrrnnneeeaaaacccc
+abcccccccccccaaaaacaacccccccccccaaaaaccaaaaaaccccccaaaaaaccccccccccccccccccccccccccccaaccaaccaaaaaacccccccccchhpppppsspppossrrrrrnnneeeaaaacccc
+abccccccccccccacaaaccccccccccccaaaaacccaaaaaaaacccccaaaaaaaccaaaccccccccaaaacccccccccaaaaaacccaaaaacccccccccchhhpppppppppoosrrrroonffeaaaaacccc
+abccccccccccccccaaaccccccccccccaacaaaccaaaaaaaaccccaaaaaaaaacaaaccccccccaaaacccccccccaaaaaccaaaaaaacccccccccchhhhpppppppoooooooooonfffaaaaccccc
+abcccccccccccccccccccccccaaaccccccaaccccaaaaaaaccccaaaaaaaaaaaaaaaccccccaaaacccccccccaaaaaacaaaaaaaacccccaacchhhhhhhhgggggoooooooofffaaaaaacccc
+abcccccccccccccccccccccccaaaaacccaacccccaaaaaccccccaaaaaacaaaaaaaaccccccaaacccccccccaaaaaaaaaaaaaaaaccccaaacccchhhhhgggggggooooooffffaaaaaacccc
+abccaaacccccccccccccccccaaaaaaccaaaccccaaaaaacccccccccaaacccaaaaacccccccccccccccccccaaaaaaaaccaaacacccccaaacaaachhhggggggggggfffffffcaacccccccc
+abcaaaaccccccccccaacccccaaaaaaccaaacaaaccccaaccccccccccccccaaaaacccccccccccccccccccccccaacccccaaaccccaaaaaaaaaacccccccccaagggffffffcccccccccccc
+abcaaaaccccccccccaaccccccaaaaaaaaaaaaaaccccccccccccccccccccaaaaaaccccccccccccccccccccccaaccccccccccccaaaaaaaaaccccccccccaaacgfffffcccccccccccaa
+abccaaacccccccaaaaaaaacccaaaaaaaaaaaaaaccccccccaaaaaccaaaaaaaaaaaaaacaacccccccccaaaccacccccccccccccccccaaaaacccccccccccaaaaccccccccccccccccccaa
+abccccccccccccaaaaaaaacccccccccaaaaaaccccccccccaaaaaccaaaaaaaaaaaaaacaaaaaacccccaaaaaacccccccccccccccccaaaaaacccccccccccaacccccccccccccccacacaa
+abccccccccccccccaaaacccccccccccaaaaaacccccccccaaaaaacccaaaaaaaaaaaaacaaaaaacccccaaaaaacccccccccccccccccaaaaaaaccccccccccaacccccccccccccccaaaaaa
+abcccccccccccccaaaaaaccccccccccaaaaaaaccccccccaaaaaaccccccaaaaaacccaaaaaaaaccccaaaaaaaaccccccccccccccccaaacaaacccccccccccccccccccccccccccaaaaaa
diff --git a/day12/uppga.c b/day12/uppga.c
@@ -0,0 +1,19 @@
+#include "common.h"
+
+int main(int argc, char** argv)
+{
+ char** lines;
+ size_t nlines = readlines(&lines, "input");
+
+ size_t h,w;
+ size_t pos[4];
+ uint8_t** grid = parse(&h, &w, pos, lines, nlines);
+
+ uint64_t* stepsto = malloc(h * w * sizeof(*stepsto));
+ memset(stepsto, 0xff, h * w * sizeof(*stepsto));
+
+ stepsto[pos[2] * w + pos[3]] = 0;
+ calculate_steps(stepsto, pos[2], pos[3], h, w, grid);
+
+ printf("%llu\n", stepsto[pos[0] * w + pos[1]]);
+}
diff --git a/day12/uppgb.c b/day12/uppgb.c
@@ -0,0 +1,28 @@
+#include "common.h"
+
+int main(int argc, char** argv)
+{
+ char** lines;
+ size_t nlines = readlines(&lines, "input");
+
+ size_t h,w;
+ size_t pos[4];
+ uint8_t** grid = parse(&h, &w, pos, lines, nlines);
+
+ uint64_t* stepsto = malloc(h * w * sizeof(*stepsto));
+ memset(stepsto, 0xff, h * w * sizeof(*stepsto));
+
+ stepsto[pos[2] * w + pos[3]] = 0;
+ calculate_steps(stepsto, pos[2], pos[3], h, w, grid);
+
+ uint64_t minsteps = UINT64_MAX;
+ size_t i,j;
+ for(i = 0; i < h; i++) {
+ for(j = 0; j < w; j++) {
+ if(grid[i][j] == 0 && minsteps > stepsto[i * w + j])
+ minsteps = stepsto[i * w + j];
+ }
+ }
+
+ printf("%llu\n", minsteps);
+}
diff --git a/day13/Makefile b/day13/Makefile
@@ -0,0 +1,20 @@
+CC=clang
+UTILS=../utils/reading.o
+INCLUDES=-I../utils
+
+all: utils common.o uppga uppgb
+
+common.o: common.c common.h
+ $(CC) $(CFLAGS) -c common.c $(INCLUDES)
+
+uppga: $(UTILS) common.o uppga.c
+ $(CC) -Wall -o uppga uppga.c common.o $(UTILS) $(INCLUDES)
+
+uppgb: $(UTILS) common.o uppgb.c
+ $(CC) -Wall -o uppgb uppgb.c common.o $(UTILS) $(INCLUDES)
+
+utils:
+ make -C ../utils
+
+clean:
+ rm -rf common.o uppga uppgb
diff --git a/day13/common.c b/day13/common.c
@@ -0,0 +1,92 @@
+#include "common.h"
+
+int compare(const lori* a, const lori* b)
+{
+ if(a->head != NULL && b->head != NULL) {
+ size_t i = 0;
+ lori* af = SIMPLEQ_FIRST(a->head);
+ lori* bf = SIMPLEQ_FIRST(b->head);
+ while(af != NULL && bf != NULL) {
+ int comp = compare(af, bf);
+ if(comp != 0) return comp;
+ af = SIMPLEQ_NEXT(af, entries);
+ bf = SIMPLEQ_NEXT(bf, entries);
+ }
+ if(af != NULL) return 1;
+ else if(bf != NULL) return -1;
+ return 0;
+ } else if(a->head != NULL || b->head != NULL) {
+ int comp = 0;
+ if(a->head != NULL) {
+ lori* af = SIMPLEQ_FIRST(a->head);
+ if(af == NULL) return -1;
+ comp = compare(af, b);
+ if(comp != 0) return comp;
+ if(SIMPLEQ_NEXT(af, entries) == NULL) return 0;
+ return 1;
+ } else {
+ lori* bf = SIMPLEQ_FIRST(b->head);
+ if(bf == NULL) return 1;
+ comp = compare(a, bf);
+ if(comp != 0) return comp;
+ if(SIMPLEQ_NEXT(bf, entries) == NULL) return 0;
+ return -1;
+ }
+ return comp;
+ }
+ if(a->v < b->v) {
+ return -1;
+ } else if(b->v < a->v) {
+ return 1;
+ }
+ return 0;
+}
+
+void printlori(const lori* x)
+{
+ if(x->head != NULL) {
+ printf("[");
+ lori* np;
+ SIMPLEQ_FOREACH(np, x->head, entries) {
+ printlori(np);
+ }
+ printf("]");
+ } else {
+ printf("%llu,", x->v);
+ }
+}
+
+lori* parseline(char* line, char** next)
+{
+ if(line == NULL || line[0] == '\0') {
+ next = NULL;
+ return NULL;
+ }
+
+ lori* r = malloc(sizeof(*r));
+
+ if('0' <= line[0] && line[0] <= '9') {
+ r->head = NULL;
+ *next = sread_next_u64(&(r->v), line);
+ } else if(line[0] == ',') {
+ *next = line+1;
+ free(r);
+ return NULL;
+ } else {
+ r->v = UINT64_MAX;
+ r->head = malloc(sizeof(*r->head));
+ SIMPLEQ_INIT(r->head);
+
+ lori* e;
+ line++;
+ char* nn = &line[1];
+ while(line[0] != ']') {
+ e = parseline(line, &nn);
+ if(e != NULL) SIMPLEQ_INSERT_TAIL(r->head, e, entries);
+ line = nn;
+ }
+ *next = line+1;
+ }
+
+ return r;
+}
diff --git a/day13/common.h b/day13/common.h
@@ -0,0 +1,21 @@
+#ifndef COMMON_H_
+#define COMMON_H_
+
+#include <stdio.h>
+#include <stdint.h>
+#include <sys/queue.h>
+#include <assert.h>
+#include <reading.h>
+
+typedef struct entry {
+ uint64_t v;
+ SIMPLEQ_HEAD(listhead, entry) *head;
+
+ SIMPLEQ_ENTRY(entry) entries;
+} lori;
+
+void printlori(const lori* x);
+lori* parseline(char* line, char** next);
+int compare(const lori* a, const lori* b);
+
+#endif
diff --git a/day13/einput b/day13/einput
@@ -0,0 +1,23 @@
+[1,1,3,1,1]
+[1,1,5,1,1]
+
+[[1],[2,3,4]]
+[[1],4]
+
+[9]
+[[8,7,6]]
+
+[[4,4],4,4]
+[[4,4],4,4,4]
+
+[7,7,7,7]
+[7,7,7]
+
+[]
+[3]
+
+[[[]]]
+[[]]
+
+[1,[2,[3,[4,[5,6,7]]]],8,9]
+[1,[2,[3,[4,[5,6,0]]]],8,9]
diff --git a/day13/input b/day13/input
@@ -0,0 +1,449 @@
+[[[[3,10,1,1],[0],[4]],10,[[1,4,1],7,10],[[2,3],[4,10,6,6]],9],[[6,[3,1,4,0,0]],5,8,0],[10,10,7,[[],[0,8],[7,6,4]],[[0,7,2,1,2],7,2,[6,0],[7,6,4,6]]]]
+[[],[],[9,[8,[],1]],[1,5],[[],[]]]
+
+[[[[7],8,[6,6]],9,[0,1],[[7,2]],[]]]
+[[[]],[[[7,4,0,10,9],[3,2,10,6,0]],9,[[7,2,0],[5,7,8],[0,7,4,2],[0,1,3,7]],3,8],[]]
+
+[[],[[[0,3,2,6],7],8,5,5],[1],[[6,6,10,10],9,[[9,1],[6,0,2,10],[0,7,1,1,2]],[0,[],[8,6,5,6],[9,8,6],8]],[0,[],[[],[7,10,10]]]]
+[[2,[[9,2,7],2,[4,8,5],4],0,[[7,4,0,9],3]]]
+
+[[[[1,9,9,1,10],8,1,[],[6,7,9,10]],6,[0,1,9],10],[[9,5,[0,2],7,[8,2]],[1]],[2,6,[[10,6],9,7]],[[[6,7,5,1]],[],0],[]]
+[[[],[8,[6,7],[1,3,7,1,6],6,[]],3],[1,9]]
+
+[[3,3],[[3,8],4,[3,[9,0,6,9],2],5],[],[],[]]
+[[],[2,[1,[6,5,9,1],[6],6],[[7,8,7],[5,4],[9,4,3,0,6],[],[]]],[],[10,[[],7,0,2],4,9]]
+
+[[4],[[],[[4],9],[]]]
+[[[]],[]]
+
+[[[[0,3,4],[],[6,9,5],7]],[]]
+[[8,6,[5],8,2],[[[6,9,8,0],0,[10,0,6,8,5],[],[]],10,[[0,2,10,0],9,[8,1],[7,7,10]],[8],[[1,7,10,5],6]],[[0,[4,9,7,9]],10,[2,[],9]]]
+
+[[5,8,1,3,6],[[6,[1,1,8],5],6,[3,5,[3,3,4,6,5],3,1]],[[10,[7,1,8,3],8,[9,9,9],[4,2,8]],[6,4,[3,1,2,8,7],6],[6,[3],[0,0,9,2],[1],8],[4,[8,5,3,10],[8,7,3,5,7],1,6]],[[[5,2,7,6],6,2]]]
+[[[10],10,[]],[],[7,[[0,9,7,10,2]],[[7],1,6,10,[9]]]]
+
+[[],[0,[[1,9],3,[],3,[3]]],[9,[[3,9,8,4],10,[8,1,3]]],[[[],[4,4,8,6,8],5],[[2,2,9],[8,2,0]],[6,7],4],[[],10]]
+[[[],[[3,2,2,8,9],[4],7,0],0,[9,[2,3,0,9]],8],[[1,0],[7,[7,4,3,4],2,[1,1,1,3],[4,10]],10,5],[],[]]
+
+[[[[],[]],1],[[6,2,[9,8,1,2,0],[]],[]],[[1,[9,7,0,7,3],[4,1,9,6],[8,4,10],9],[7,[1,4,3,4]],0,1],[],[]]
+[[[9,8],[5,4,9,1],[[0],[2,10]],[8],[10,0]],[[[],9,1,[5,5,4,6]]]]
+
+[[[1],4,[4,[9,0,3],2],[],6],[],[],[],[9,2,3,1,7]]
+[[4,1,[2,[6]],10],[],[[9],6,[0],9],[[6,[5,1,9,10],9],5],[]]
+
+[[2,8,[[1],[5,8],[4]]],[2,2,[[4,10,4,3,4],[1],4,[]],7,[8]],[4,[]]]
+[[[]],[4,4],[0]]
+
+[[[6,1,[7,2,8,5,2]],6,[[3,5,1,6],[2,8,0,9],[7,9,5,6,3],[8],[10,1,7]]],[2,9,5],[[],[],6]]
+[[[8],[6,9,6,[3]]],[[[10,6,3],[7,3],[0,6],[]],6]]
+
+[[],[[[4,2,8,3,4],[1,10]],[[7,9,0,0],8]],[[5,2,[6,8,10],8],[7,[1,9,3],0,[]],4],[[0,9,[],[5,0,10],3],[7,7,[5,6,6,5,7]]],[5,6]]
+[[[5,[6,6,4],1],[0,3,5],[[9,0,7]]]]
+
+[[[4,[3,6,5,10,0],[8,4,6,8],2,4],1,[1,2,7,4],[[3,10],[5],[3]]],[[0,[5]],[[],[8],2,8],1,[10,10,0],[]],[[4],0],[[7],9],[10,[]]]
+[[[[],[5,2,8,4,10],2],0,[[6,7,9,7,5],[2,5,8,7],10,0],1,[1]],[7,[]]]
+
+[[[8,[8,4,5]],3,1]]
+[[[],9,1],[[[10,2,4],6,[10,6,0,5],4,[]],[0],[[2,8,5,5,7]],8]]
+
+[[[[6],[2,4,4],[6,8,0,7]],0,[7,1,8,[3,0,5]]],[[[],7,[5,3,9],[8,0]],8,9]]
+[[10,1,[[4,0,6,4],[2]]],[7,7,3,[],[0]],[7,0]]
+
+[[4,[],10]]
+[[[[],[9,5,3,9,4],6,10,[6]],6,1,[[1,1,9],1,7,[5,1]]],[9,[[9,9],[1,0,4,6,9],[]],[],9],[[9,[8,2,2,7,9]],9]]
+
+[4,10,4,2,10]
+[4,10,4,2]
+
+[[[[]],8,0],[[9,0,[9,10,6]],[],7]]
+[[6,5,[6],1,[[4,7,10,2,8],7,3,[8,3,5,10]]]]
+
+[[[0,[2,3],[],[1],[]],4,[[],[1,7,9],[6],[6,4,8,3]],[[9,3,7,9]],[[5,0,1,9,0],[6,2,9]]],[[0,[4,1]],5],[],[]]
+[[[5]],[1,[[9,2,8],[4,1,4,4]]]]
+
+[[],[7],[]]
+[[7,[[10],5,[3],4,2],9,4],[[[8,8],[3,2,3,10,0]],3,0,[2],9]]
+
+[[[6,0,[],[0,5]],[],8,1],[],[5,2],[3,[6,[0,9,4],8,6,[]],9],[1,5,1,6,[2,0,8]]]
+[[[0],9],[[[3,9,2],[0],[9,10,1,4,6]]]]
+
+[[3,[[4,4,10,5],5,[9,6,10,9],9],4,[]],[[[6,4],1,[]]],[[[],[10,4],1],[7,9,[2,6],7,8]]]
+[[5,2,[[0,0],0,2],7,8],[0,1],[[[1],[10,0]],[[],5],1,[[9,8,9,5],6,[5,10,2,3,5]],9],[7,5,3,[8,1,[7,7],2,4],4]]
+
+[[],[[[],7]]]
+[[[[8]],[[4,4,10,8],[7],[2,8,1]]],[],[],[9,8,[[7,8,2,5,1],[1,1]],6,3],[1,[[]],[[7,2],[6,3,5,0,2],7,2],[[9,3,10],[6,4,4],6,[10,4],0]]]
+
+[[4,7,8],[[1,[4,6,1,2],[],[],0],9,6,8,[4,1]]]
+[[9,2],[7,[[5,2,9],[9,4,4,2,10]],0]]
+
+[[4,[[5,9,0],[0,10,4,4,4],[9,2,4],2,3],[],[5],3],[[[7,1,9,2],[0,7,9,8]],[[],[8,2],0,8],[3,2],[[],[],3],6],[6,[[4],[7],[1],[2,9]],2],[[9],[]],[5,[0],[4,[]]]]
+[[[[10,0],10,7],1,[2]],[7,[6,8,2,[9,6,10,1],8]],[],[6],[[],[4,[1,2],7]]]
+
+[[],[7]]
+[[[[2],2,[4,3,9,9,7],6],[7,10,6,[9,1,4,3,10]],[8,[9,7],7,[3,10,3,9]],2]]
+
+[[[0],1],[6],[10],[],[6]]
+[[],[[[9,5,10,6,3],7,10],6],[0,7,0,8],[5,[[10,3],7]]]
+
+[[],[[[4,1,9,7,1],4,[2,4,4],[6,8,4,5,1],[4,8,4,3,3]],10,[],9],[6,[5],[[],[8,4,3,10],[5,3,0,8,4]]],[[[4,2,2],10,1,[6,0,8]],[[3,10],0,0,[7,3,3],[0,1,0,2,0]]],[]]
+[]
+
+[[[]],[[7,7,0,[4,0,7,4],[7]],[[6],8,[0,4,4,10]],[10,7,[9,9,10,0,0]]]]
+[[6,[],7],[[7,7,[7]],[7,4,0],6,[[0,6,9,4,2]],[[7,6,6,6,1],[9,8,10],[0],[7,10,3]]]]
+
+[[4],[[[8,4,9,4],6],2,[4,[6,2,9],6,[0]],[4,6,[]],[1]],[[5],[],[[6,2],9,0,6],9],[],[]]
+[[5,2,1],[[10,[2],2,[2,0,7,6,6],0]],[[[3,0,10,3],8,6,1,[]]],[3],[]]
+
+[[4,[6]],[4,7,[[0,7,4,10,1],[],[10,4,7,6,6],0,1],8],[0,7,[[]]]]
+[[[[6,1],5,10],[9],3,4,[[6,1,9,1,6],6]],[10,1,7,9,7],[[4,[3,9,10],2],[9,[8,2,0,7]],[[1,9],[10,3,5,2,5]],9],[],[1,2,4,2,[2,[6,4,2,4,8],10,4]]]
+
+[[[],3,[[2,2,7,4,7],1]],[6],[[1,[9]],[[3,6,10,2,0],[10,3,0,6,1],8,7],[[3,7,5,9],5,1]],[0]]
+[[[]],[],[],[1,1,6,[[8,0,5,9,10],6],8]]
+
+[[[1,[0,3],[4,8]]],[[3,7,[8],10,9],[],[7]]]
+[[[[3,7,6],[9,5,1],[3,3,7],[4,9]],2],[8,4,0,[0,2]],[8,[[7,2],9,[]],[[0],3,7,[4,6],[10,1]],8],[[]]]
+
+[[[2,4,5,[],2],[[10]],1],[],[]]
+[[1,[4],[10,[8,4,9,7,3],[]],[0,[],8]]]
+
+[[[],9,[[0,10,0,0,5],[3,4],5,10],[[3,5,9,7,9],[9],[9]],8]]
+[[10,[[3,1,8],[3,2],[6,0],2,5],6,[[2,7,4,0,7],[9,7,3,10,7],[9,4,4,7],6,10]]]
+
+[[[[7,2],6,0,[9,10,3,0,8],8],7,[[1,5],6,[5,7,6,2],[10,6]],[[1,8,0],8],[[],[3,9,10,3],[]]],[[[9,7],10,[6,9,0],[6,2,7,8,3],2],3,[[6,1,2,1],0,2],8,4],[8,[],[3,[5,7,2,1]],[2],0]]
+[[[8,[8,2,10],5,8],2,[[1,0,3,4],6,[10,10],5],[3]],[],[[10],9,8,0],[7,[],[[2]],1,7],[[2,[6,10,4,1],7,[2,3,8]]]]
+
+[[9,10]]
+[[3,8],[[[7,7,2],5,5],[8,6,[4,7,10,10,4],0],9,[3,7]],[[[],[6],[5]],[[2,0,3,8,6],[3,5,8],2,[7,8,0,6,9]],[[3,4,4,3]],7,[[8,5,5,5,3],[5,8,6],3,6]],[[[10,6,2,10],1],[[0,5,0,6],7,10,3,[]],5,1]]
+
+[[5,[[3,5]]],[7],[5,0],[[],4,8,4,7],[[10,1,0],[[0,9],1,0,4,[0,5,1]],[[],[5,6,9],1,[5],[]],[[4,4,5,6,9],[1,9,6],7,2,5],[8,3]]]
+[[],[2,2]]
+
+[[[[1,5,5],[9,2,6,9,0],[10],2],1,8,3,10],[[],7,[6,5,[9,10,7,4],7],[]],[3,4]]
+[[7,[[6,3,6,3,9],[5,7,6,5],[10,5],[2,4,7],3]],[],[]]
+
+[[[[10,6],[4,8,7,3,1],8,3],6,[9],[10,[6],3,0,8],[5]],[],[[4,[6,0,9,1,10],[2,1,5],[6]],1],[],[[4,[4,7,10,7,9]],[[5],[6,6,2,5]],[[6,2,1,8],2,[6],[2,9,10],[8,5,5]],[1,[1,1,6,5,4]]]]
+[[[[7,8,1,0,5]],[[10,9,7],[1,5,1,2],[6,5,8,10,10]],[[1,0,5,1],[10,3,4,4,2],8,6],4],[3,1,[2,[],[1,10],2,[1,7,4,4]],8,4],[7,5,[[1,8,6,7],8,[3]],9,[[1,8,9],[],[],[10,0],[8]]],[[[8,1],[3,1,5,0],[8],[],6],6,4,0],[[[6,9,10],[3,10,6,7,9],[],5,[4,8,3]]]]
+
+[[3,[5,5,[6]]]]
+[[5],[0],[6,7,6,[9,7,5]],[[[4,5,2,7,10]],[3,10],[[9,9,2,5],0,[8,5,9,5,9],0,[9]],2]]
+
+[[[[]],[[5,0,6,9]],7],[9,1,2,[3,6],[[],9,8,1,[7,6,10,2,6]]],[[7,[10,0,8],6,[5],[1]],10,[1],[9,[7,6,2,6,8]],[[4,8,4],[1,10,8,3,7],3,0,[]]]]
+[[[7,8,3,[]],9],[]]
+
+[5,7,4,4]
+[5,7,4,4,1]
+
+[[],[0],[],[1,1,[6,[]],1,[4,[6,10,9,2,2]]]]
+[[[9],5,5,[]]]
+
+[[[[3,7,10],2,2,[6,9,0,3],[1,9,3,9]],0,9,[[5,1,1],10,[8,10],[]]]]
+[[[4,[8],[0,2,8],[9,8,2]],[[6,2,3],0,10],5]]
+
+[[8,1,9],[[[],[]],7,[[1,2,3],6,2,4]],[8,[[6,1],4,2,6]],[[[1,0,6,3],7,4,[10,5,8,9,0],10],[1],[8,10,[8,4,6,6,6],1],9,9]]
+[[6,6,7],[[5,5,[1,0,4],[6,4,1]],[7,2,8]],[[[1,7,1,2],[2],[5,10,5]],9,[3,[5,3,7,7],[10,7,2,7],[6]],8,3]]
+
+[[[4,1,2],[2,[0],1,[4,4,6],[]],5,1],[],[2,[[0,9,2,6],8,[0,1,0,3]],3],[],[[10,[4],3,[5,0,3,9],[4]],[],1,[[8,5,1,2]]]]
+[[[[1,6,2,4,8],6,1,9,[2,2]],[9],0,8]]
+
+[[[2,[9,10,10],[9,0,7,2],[7],1],6]]
+[[[[],10,8],1],[7,[[9,2],8,1],[[5,4,0,0,2],3]],[7,9]]
+
+[[[[4,1,10],9,[9,8,9],[5,2,0,5],[5,5,10]],[],0,[3,9,[5,4,7]]],[[[0,10,8,6],[],[1,4]],2,6,4],[7,[[1,8,5,10,6],5,[5,10,4,0,0]],[3,[]],[0,[2],6]],[0,0,[],[7,9,1]],[[],[9,2],[[]],[9,0,[1,9,4],8,[9,0,5,5,9]],[2,7,[7,0,1,8,1]]]]
+[[[],[1,3,6,1,4],[[5,10],2],0],[]]
+
+[[],[[[0,7,9,9],[9,1,3],[3,3,8,10,3],[9,8],7],4],[[],4,8],[[],[[1],[0,3],[],8,[10,0,5,8,10]],[[3,1,2,2,3],[7,4,10,4],[]],[[3,3,0],[4,7,1,5],0,[8,2,3,2,5]],4]]
+[[[]],[[10,[9],[6,8,8,2,6],[9,3],6]]]
+
+[[[10,9,[10],2]],[10,1,[10,4,2]],[2,9,0,[[2,7,0,7,8],[5],2,6,[1,7,6]]],[9,[7,[],[]],9,[[8,8],6]],[[10,4,10],[[9,3]],[[4,1,6,10]],4,[2]]]
+[[2,6,0,[4,3],10]]
+
+[[],[[[7,1,3,9,2],[8,10,4],2]],[]]
+[[6,6,[6,[],[10,1,1],[7],[]],[8]],[[5,6,1,[6],5],7],[[[1,3,3,1,9],0]]]
+
+[[],[9,9,[2,[1,9,1,3,0]],[2],1]]
+[[[[6,4,8,9],1,8,4],10],[[[],1,2,4],[9,[7,8]],6,9,[[4,2,1,8,5]]]]
+
+[[[[7,1,2,2]],8,[10],9]]
+[[9,[7,[6,3,6,10],5,[0]],[[],8],10],[9,[]],[4,[9,[10]],7],[9,7,[]]]
+
+[[8,[[5,3,5,7,3],[6,5],0],[[2,3],[7,2,7],[]]],[[8,[5,0],[5],[1]]],[[6,[],[]],[],3,[5,6,10,1,[]],[3,8,[5,1],5]],[],[[],4]]
+[[4,7,[7,8],[7]],[6,[5],3,[5,0,5,[7,0,5,4,4],0]],[[2,[9,9],3]],[9,[[4,7],10,[0,5]],[1],4,[9,3,[5,5,9],[1,1],[8,10,10,10,5]]]]
+
+[[6,[0,9,3,1,8],[[2,10,7,5],2],[[9,8,9,6],1,0]],[[[1,3,10,4],2,5,0,[7]],[7,6],0,[],[[8,7,4],5,3,[]]],[6],[3,[[10,9,10,7],[7,10],1,[3],2]],[7,2,9]]
+[[[1,9],[[5,3,0,8,3],4,0],4],[4,[[9,4,8,3,7],7,10,1,[9,9,0,6,9]],[[9,4,3,7],[],9,[4,3,8,4,8]],[]],[[[],[10,6],[8,10],[],[]],[[],6,[7,0,9,0,1]],[[2,5,4],2,[4]],3],[[[10,4,0],6],[1,[0,4,2,6],9,4,5],8,[[7,9,5,0],[],[],[7],[9]]]]
+
+[[],[5,9,5,8,2],[6],[[8,[1,8,2],[6,3],0],[2,[10,3,2,10,0]],[[9,3,7],[3,3,6]],8,[1,[3,2],9,[3,0,1,1]]],[2,[[2,3,5,0],8]]]
+[[[[1,8,4,10]],4]]
+
+[[2,[9,8,[6]]],[[[5,6],[9,9,0,2],[0,7,10,9,8],2,[2,7,2]]],[[[],4,[3,2,8],5]],[8]]
+[[10,9]]
+
+[[],[[10,[],7]]]
+[[[5,1],[4,[2,7,9,10],[3],0],0],[[[3],[],[4,9,7],[10,3,0]],[[1],2,3,5,[0,5,8,3]],4,[9,3]]]
+
+[[5],[4,0],[[[1,1,2,9,5],[4],[7]],[[9,1,7,6]],0,[]]]
+[[5,[10],0,[7,[2,10,8],[10,4,5,0,8]]],[[[8,8,4,10],[0,0,0,8,6],[]],8,6,[[5,0,0,1,1],6,[10,7]]]]
+
+[[[0,5,1,[]],[],6],[[7,6,[1,8,2,7,10]],[4],5],[7,6,4],[1,9,[],[],[[],9,3,0]]]
+[[4,4,[]]]
+
+[[6,[6,[1,8],[8,10,0,8,5]],[[7],7]],[[],0,[[8,9,8],1,3,[]]]]
+[[[[6,2,6,4,5],3,[0],[9]],4],[],[5,1,[[]],[3,[10,1,10,5,10]]]]
+
+[[7],[2,[7,3,[10]]],[]]
+[[[8,[4,4,2,7,5],6],7,[5,6,8,[2,3],6]],[[[5,10],[8,9,2]],7,[1,[3,5,2],[6,9]],9],[],[[[8,3,3,2,8],[]],2,7],[3,[[2,1,5,3],[2],0],[[6,6,6,2,0],8,[9,9,8,5,6],[3,9,6]],[8,4,5],[1,[7,4],[2,3,0,2,4]]]]
+
+[[[[10]],[[]],7,[[3,0],9,2]]]
+[[[[1,7,6,6,3],3,[6,7,7],3],[],5]]
+
+[[5,[[0],6,[7,8,7,5],[4,8,7,7],10],[0,9,[4,9,9,6,3],[6],4],[[8,9],3,[]]],[[]],[0,[[10,10,5,8,5],2,7,0,[3]],[2,[4,6,5,1,6],[7,10,10,4],7]]]
+[[5,0],[[[6,3,5],[3],[8,1,5],5,9],[6],[2,0],2,[10]],[]]
+
+[[[],10]]
+[[[3,[7,9,1,4],[5,0,7],[1]]],[4,[[],6],5],[[6,[0,3],[3,2,2,5],[4,7,9]]],[10,[[8,4],2,4]],[]]
+
+[[[[9],[10,9,3,8,4]],10,3,[[7],3,[10,1,10]],10]]
+[[[[8,10,1],[4]],[],[9,[2,3,3,1],[8,9,1]],[9,1,[3],[],8]],[]]
+
+[[9,0,5]]
+[[],[[6]],[4,[5,[2,3],[10,3,1,2],[4,4,9],1],8,[3,[4,10,10],[1,6,1,0],6,4],7],[3,9],[9,[[0,3,10,10]],[5,2],[]]]
+
+[[],[],[8],[2,3,4,3]]
+[[[[9,10,0,10]],1,[[],[],[],[1,4,7,0],4],8,[]],[4,0,[[5,0,2],2,[5,3,6,5],9,5],[1,0],8],[[2,1,[6,3,5,10,1],2]]]
+
+[[[5,7,2,10],[1,[9,8,10],[0,7,2,10,5]],6]]
+[[[],9],[2,[10],[3]],[[[10,7,3,8],2],[[10,1,2],0]],[9,[[6],[1,7,9]],4,[3],[]],[1,6]]
+
+[[2,2,8,[2]]]
+[[[4,[2,4,3,6,2],[6,7],0],10,9,[[6,2,4,4,10],2]],[[9,4,[9,1,1,8,5]]]]
+
+[[],[[0,9,5],[1,[6],2,[],0]],[3,[9,9,[]],5],[[[8,2,10,3],8],5,[6,0,[4,1,4,5,9],0,0],0]]
+[[1],[[5,4,9,8,[1,1,6]]],[1,1,[],[],7]]
+
+[[[0,0,[7,2,10]]],[9,1,[],4,[[9,10,1],4,9,[1,0,6,4,0]]],[4,[9],[9,[7,7,6,8,9],2,10],7,[[2]]],[[1,[8,0,3,4,2],[8,9,4,4],[4,3,0]],[4,7,7]]]
+[[],[],[1,[8,[10,0,2,10],[],10],[2,[]]],[5,8,[[7],[4,6,5,9],[6],6],8,1]]
+
+[[[[]],9,10,1]]
+[[7,5,[6,1,[9,10,2,5,9],[],8]]]
+
+[[[2,2,7,[2,4,7,10],[6,6,6,8,4]],[10,3,10,[10],8],[[2],[],3,2,3],3],[2,1],[],[7,6,0,[[8],[5,3,5,8,7],[2,6,9,2],9]],[]]
+[[8,0],[4,6,[10,2,0,3],8],[]]
+
+[[4,3,8],[],[[],[]],[0,5,[1,[3,1,6],9],[[4,1]],10]]
+[[[[7,2,8,8,3],7]],[[[0,8,4],[0,8],[5,8,0,3],7],3]]
+
+[[[[10,6],[8,3]],3,[[6,8,5,4]],7],[[[10,5,8],[10,1,0],[],[],10],[[]],[10,[4],8],4],[[[4,1]],[6,[7,10],[],[1,0,9,4,1]],5,7],[],[[9,6,[],[4],1],9]]
+[[[[],[2,6,10,5]],8,[]],[9],[7,5,[5,[9,1,7],4]],[]]
+
+[[[1],[0,[8,3,9,2,2]],1,1]]
+[[],[[7,5,[9,9,3,1],9],[8,[],5],7]]
+
+[[8,5,8,[[9,7,7],6,0,3,[2,7,8,0,2]],1],[]]
+[[8,[],[[3,9,3,1]],[[],[]]],[[5],[8],[[3],[1,4,3,2,8],[8,0,1],[3],[0]],[],[[7,2],[7,1,0,1],0,[5,9,2,6],[6]]],[[[],[10,4,7,0]],[],[[7,8],7,4,3,3],[3,4,8],[10]],[0,7]]
+
+[[[[],[5,6,5],[]],[5,7,5,[10]],[[4,3,10],7]],[[]],[[7,[3,4,2,5],3,[6]],10,3],[3,0,7,5]]
+[[[[3,6],[7]],[[4,10]],[[8,4,9,7,2]],6],[[[7,2,1]],[[8]],[1]],[]]
+
+[[],[4,4,[[9,3,2,3]]],[5]]
+[[8,8,[6,1,[6,5]]],[10,[[1,10,10],[9,3,3,4]],6,[[2,7,2,1,8],7,5]]]
+
+[[6],[10],[1,5,2],[],[0,10,3,[10],[[2,6],[8],7]]]
+[[8,[]],[5],[2,7,[5,7,1,6,[0]],[[],9,[0],7],[[1,4,1,1],[7]]],[]]
+
+[[7],[3,8,[1,[3,4,4,1,3],9,[6,6,0]]],[0],[[]],[2,[6],[[0,3],[],6,[4,7,1,10],[6,7]],[[1],4,1],[[3,10],[4,5,3],[],10,[0,10,8,0]]]]
+[[5],[[9],[[1,9,4,5],0,9,[0,4,4,3,2]],4,[],6],[[[7]],[[4,0],10,5,9]],[[[8,6],[5,3],1],5,4,[[0,0,7,8,0],[],9,3,0]],[9]]
+
+[[],[[[],5],[[],10,[10,3,1,7],4],[5,10,6,[6,4,2]],[[6,8,6,8],1,6,5,[9,5]],[2]],[3,6,[[5,3,5],6]]]
+[[[[2,2,2,5],6,9,[6,3,7,1,7]],[],[1,[]],[],[[9],[10,5]]],[1,[[0,2,3],1],7,[6],7],[]]
+
+[[],[[[8,3,7,8,3],5,[4,9],[1,4,9],[6,9]],7,[]]]
+[[[1],9]]
+
+[[],[3,2,[[3],[7,1,6,5],9,0,[4,1,2,6,8]],2,[1,4,2,1]],[[[10],4,[1,5]],[]],[9]]
+[[0,[[],4,[],[7,9,1,3]],[[4,8,8,6],6,[9,0,9,7],[7,8,5,1]],6,5],[],[[5,3,4],0,[10,5,5],10],[[[0,9]],[6,[3,8,5,6,5],6]]]
+
+[[6,[],[8,8,9,1,8],[[9],9,[9,6,8,4],[8],[3,2]],[[4],1]],[10]]
+[[2,3,[10,2,1,10,4],5,3]]
+
+[[[],7,0,[0],[[2,8,7,10],0]]]
+[[[[9,10,8,7],0,[7,9],[7]],8,8,1,[[]]]]
+
+[[],[6,[[7,1,4,8],9,10],[10,3,[3,10],[]],[[0],2],8],[],[[4],[],[],[]],[3,[]]]
+[[0,[2,6],[]]]
+
+[[2,0,[10,4,10],2],[[],0,[[0],[9,9],[10,2,4]],[3,10,1,3,[10]],[[1],[0],4]]]
+[[[4,[0,4],7,10],[[],10,3,[4,10]],9,[[1,4,1,8,7],10,[4,9,2],3]],[],[],[[6,[3,6,0],[1,5],[8,8,4,4,1]],[],[4,[]],3,[10,[5,7,4],6,5]],[[[3,5],[5,3],[7]],[[7,10,1,10],9,3]]]
+
+[[5,9]]
+[[4,[[2],9],1],[[[1,8,9,2],5,[4,5,9,2,7],[4,0,9,7,4]]],[10,7,[],[[3,3,10,8],[4,4,3,4,2],2,5]],[],[[4,[10,2],0,4,[9]],[[]],[[3,7,5,1]],[[2,2,10],2,[0,2,0,7],[2,6,0,5]],[[2,2,1,4],[5,1],[4,10,3],10,8]]]
+
+[[5],[[9,[10,5,3,2,2],5,1],2,5]]
+[[7,2],[2,10,6]]
+
+[[],[[],2]]
+[[9]]
+
+[[[]],[0,[[9,4],8],[9,1,[1,0,8],8,8],8],[4],[[6,[2,4,5,9,2],[8,5]]],[[[4,9,6],[7,9,1,2,0],[4,5,4],1,[5,0]]]]
+[[2,[10,[1,9,5,8],[10,1,5,5],3]],[],[4,[],[[3,10,0,2]]],[0,3,6],[[8,0,[2,2],3,5],7,10,9]]
+
+[[[[5],9,6],8,2,0],[[10],[],6,[4,[7,6]]],[[4,[3,7],[0,3,6,4,4],10],3,5,[6,1,[8,5],4,3]],[[7,3,4,[3,5],[9,8]],5,[],3],[[6,10,[0,3,9]],[[3],0],0]]
+[[3,[6,5,1,[3]],3,9],[7,[9],[0,[0,9,1,10,0]],[],[[2,7]]],[],[]]
+
+[[3,4,[[5,2,9,9],0,6,1,[]],[2,2,[7,1],0,4]]]
+[[],[[[4],[5,8],[]],[5,8,1,[6,1]],10,[6,[],10,3],[6,[4],2,4,2]],[[3],[9,[3],5,[5,7,4]],[9,5,[9,1],9,[5,4,3,7,4]],[0],8],[1],[9,[4,[3,9,7,0]]]]
+
+[[6,1,[],1,[2]],[[[10,9,2,0,0],5],[5,7],2,10,0]]
+[[5,9],[],[[5,7,5,[0,1,5],[6,1,10]],10,[5,1,[],[5,5],[]]],[],[[8,5],2,0,10,8]]
+
+[[[],3,[],[5,[4,6,4]]],[[[3,8,3]]]]
+[[2,[[2,2,1,4],10,[10,7,10,8],[4,0,6,10],7]]]
+
+[[[[1],[7,2,1],[5]]],[6,8,0,7,1],[[[]],6,10],[],[4]]
+[[[[0,7,6,0],3],10],[[]],[1,8,3,[8]],[4,[[],[0],7,9],[],[0,[],6,2]],[]]
+
+[[8,4],[[5,8,2],[10],7,[3,[0],5,0],3],[[[3],[7,3,6,3]],[[0,5],7,1,[2,4,9,5],[3,7,3]]],[0,[[7,4],[7,8],[7]],7],[4,[[3],10,[3,3,1,8],0],5,3]]
+[[[[7,2],[9,9],5],[[0,1,5],8,[9]],[7,[3,10,6,9],5,[10,7,5],10],[[1],[8,4,0,3,4],[3,1,9,6],[],2],1],[8,[9,10,8,[]],8,4,[]],[3,[3,[2,0,9,3],1,[],[3,2]],[[6,3,5,1],[10,5,6,3],5,1],[[],[0,10,5,8],6,[7],[3,3,1]]],[4,2]]
+
+[[[[1,7,2],[8,10,9,10]]],[8,8]]
+[[7,[[2],[6,9,1,4,1],5]]]
+
+[[4,7,[[5,3],3,0,[9,9,5]]],[[8],4,[[6,2,2,6],6,[4,1,0],5,6],[1,10],[]],[[[1,0,8,8]],[[7,6,10,6]],10,5],[]]
+[[[[1,4,9,0],6]],[[4,7],[],10]]
+
+[[9,5,4],[9],[4,[4,[7,6],0],10,7],[[3,1,7],8,0],[]]
+[[[[6,5,2],[6,10,2,0],3,2,[4,2,7,10,2]]],[],[[[4,5],3,[10,7,2,3,10]],5,4,5,10],[]]
+
+[[[[2,5,8,3],9,8],0,[8,[5,8,10],[5,1,4,8,3]]]]
+[[[],5,1,[9,9],[[9,5],[10,5],[1]]],[2,[9,5,1,8],[[9,7,9,0]],0],[[[7,4,9,7,2],[5,5,8,7],3,[6],9],[7,3,[5,3],8],5],[[],1,10,[2,4,[],6],10]]
+
+[[6,1,3],[[4,[],[9,1],0,[10,0,3,3]]],[6,8,3,[]],[[[]],8]]
+[[[[0],[8,8,7,7],10,7,8],5,[3,[4],[8,3,10,7,7],7,[10,4,3,3,3]],7],[[10,[2,5,0,8,0],[],8],1,0,[[],[7,5,8,10],7,6]],[5,6],[[],[],[[6,3,9,4,3],10,5,9,[7,1,3]],[[1,3,7],[5,9,4],[5,8,8],[8]]]]
+
+[[[[8,8,0,3],[3,1],9,[6,4,9,0]],[[7,8,8,1,3],10,[10,2],10,4],10,[[6,7],[0,8,5,3],9]]]
+[[[1,3],[3,[6],[1,10,10]],0],[[],[[9],5],[[],[3,5],[]],8],[1,[7],[],8,1],[],[[[]],7,[],8]]
+
+[[[],0,[10,9,8,8],[4,[4,7,4,7]],[5]],[2,9,[],0],[[0,4,6,[2,3],1],6],[1,1,[[6],0,[]],2,3],[2]]
+[[7]]
+
+[[[8,0,1,7],10,0],[[[],10],10,0],[10,[0,[],0],[4],[10]],[[[],9,[5,10,0,1,2],8],0],[10,2,7,[1,0,[3,3,6],[0],5]]]
+[[],[1],[[0,[1,9,1,9,10],5,[]],[3],1],[[4,[1,6,9],[5,3,10,6],[1,6,3,10,4],1],[[7],9]],[9,[[5,10],0,6,10],[]]]
+
+[[],[7,3,4],[[[8,10,8,1],5,6,[]],1,5,0],[[[2,7,2],8],[[1,6],[10],9,[8,6,3]],[5,[4,7,9,0,2],[]],[],[[8,5,10],[1],[],5,[3,7]]]]
+[[[[7,3],[7,6,3,5]],[],6,[3,[3,6,3,6],[2,9,1,0],7,[7,8,10]],[4,6,4,[4,1,3,6,4]]],[2,10],[],[]]
+
+[[],[[3],8,1,7],[[10,[2],3],8,4,[0,4,[],7,[2,3,5,1,7]],[[4,7,10],0,[6,10,6,7,3]]]]
+[[],[[9],7,[],[7,9,[5,8,8,10],2,[9,3,3,9]],1]]
+
+[[],[10,4]]
+[[[6,[],7]],[3,[1,[0]],[[1,0,0,0,10],[5,5,8,1],0,[1,4]],2,0]]
+
+[[7,7,[8,[0]],[]],[3,[[3],[],[0,10,9,10,0]],4,8],[[[1,3]]]]
+[[[[4,5]],8,10,3,10]]
+
+[[5,[0,4,7]],[8,[[10,1,7],7,[9,6],[0,8],[]]]]
+[[7,[[4],3],4,[[3,5,9],[2]]],[],[[[7,7,9],[4,1,9]],[[2,8,7,2,9],6],[[5,5,1,7,1]],[[5,2,1],3,[],[6,0,9,0]]],[]]
+
+[[[[7,3,4],5,4,[5,0,2,6,2],5],[1,0,[8,2,5,10]],10]]
+[[4,[1,0]],[4,4],[7,[[9,3],[6,0]],1,[[0,10,6,4],[1]]]]
+
+[[2],[[[0,5,9],9],[]]]
+[[],[[[5,6,10,3],[0,8,4,3],[8,3,2,5]],1,[7,[8,1,4,9,9],[3,9,0],[2,4],[5,3,0]],[10]],[9,[[],5],7,2,[5,9,6,9]]]
+
+[[[[9],5],[[10,9]],[5,[6,6,6,5,10],[8,10,3,0]],[[0],[10,7,0,9],[3],7],[1,2]],[[[6,6],6,[7]],3,8,[0,1,1],5]]
+[[[],[[10,1]],[]],[7,[2,9,0,[]],[0,[2,1,7,1,4],0,[0],4],[10,[1,9,2,6,3],9,[1,10,6,7],1]],[[8,8,3,6]]]
+
+[[[7,4,7,3],2,8,6]]
+[[[[5,7]],7,10],[]]
+
+[[8,[1,[0,5],[2,10,2],[4,9,5],7]],[[],[[4,9],4,4,5],6,10],[]]
+[[],[5,9]]
+
+[[[7],[2,[2,1,7,5,8]],[0,1,5,6,[2,6,8,9,1]],[[],6]],[[[],4,3,[10,1,5,5,6]],1,10,8,[]]]
+[[6],[[[]],7],[[7,1,0],0,2],[8,[[3,7]],3,2]]
+
+[[],[[],8,6],[2]]
+[[1,7,6],[],[[3,[9]],[5],[[8,1,4]],10],[[[7],[7,5,5,8],[],6],0,4,4,[]]]
+
+[[[[2],9,1,8],[5]],[],[10,[5,[7,10,2,6],10,5],5,[[2,10,7,5],[0,6],9,0]],[[]],[9]]
+[[[6,[0,10],[0,10,3,9,2]],10,[[10,9,0,8],[5],[7,6,10,4,5],7,7]],[[9,[]],8,[3,6,[7,0,5]],9],[],[[[9,8,5,10],[10,0,0,5],8,[7,1],[6,5,5,10]],6,[8,[2],0,3]]]
+
+[[[[1,8,8],4,[6],10,4],[[8]],[6,[6,9,6]]],[],[6],[]]
+[[[10],6,5,[10,[],5],4],[],[],[3,[[]],[[5,7],[],6,7,[]]],[[],2,[2,8,[8,4,1,10,3],[6],6],10,9]]
+
+[[7,1,[0,1,[5,8,1,2],[0,2,3,0],[6,5]],[5,1,2,[1,7,3,9,9],7]],[9,[[7,3,4,8,8],[6,6,2,3],[6,10,2,9],[5,1,10,1,0]],[9,[4],[6],7,[]],[[]]]]
+[[],[6,1,2,[2,[4,1]]],[0,9,[2,1,0],[[],1,[4,10,5,7],2]],[9,[[4,3,4,5,7]],[5],[[],8,[6,2,4,0]]]]
+
+[[[[5,5,3,3,7],[6,7,4]],[[],9,[2,2,4,9,10],9,[7,5,7,3]],[5,8,5,10,1],2],[[1,2,4,5],[10,5,[1,9,7,4]],[],7]]
+[[3,6]]
+
+[[[[7,10],[],9,6,0],[1,[1,8],[3]]]]
+[[[9,[],4,10],9,9,[],7],[2,[[],2,3,[4,9,2,3]]],[7]]
+
+[[],[5,[3,[10,9,6,2,9],[4],[7,6,8,5]],8,6,5],[],[[[10,0,2,10],5,[7,6,8,7],[6,10,9]],[[8,2],[6,0,2],8,3,[6,0,6,1]],8,10],[8,[]]]
+[[0,[[8,10,1],[0,9,10,1,0]],7,[6,5,[9,4,5]]]]
+
+[[[9,4,[3,9,2,4],[10,5,7,5],[5,8,10,8]],[[0],2,[1],[1,7,7,2],[8,1,5]],4],[6,[[],[10,5,6,8]],5,[[],[2,6,2,7]]],[10,[4,10],[0,7,[6,3,10,9]]],[3,[[5,7,6,5],[2,10,10,0]]],[2,2,[[7,4,8],5,10],[6,4,6,5]]]
+[[[3,4,[],1],[],6,1],[[[8,7,9]],[[5,3,3,1],[10,2,5]],10,[[8,0,1],[6,1],[10,2,6],[],[6,5]]],[7,[9,6,[10,5,5,8,4],6,0],4,[[7],8,[10,7,2,10],8,1],3],[[8],[8,[9,3]]]]
+
+[[10,4],[4,4],[[]],[[[],1],7]]
+[[6,[],[6,[6,10,3,2,3]],[1,2,4],[5,[0,6],[3]]]]
+
+[[[5,0,10,3],[1,5,4,[],[]],4],[]]
+[[10,0,[[],[10,8,6,8,8]]],[],[[1,[]],6]]
+
+[[],[[8,0,8,[]],[10],[[8,7],[],[4],[7,9]],8]]
+[[[7],6,[6,[7,8,8,3],[1,2],[],[1,7,4,1]]],[10,1,[7,8]],[8,[]],[[[7],[2,1],[7,5,8],6,[]],2,8,[],[[8,8],0,[1]]],[8,[[],8],[4,[]],5,[]]]
+
+[[4,10,7,10]]
+[[[],2,6],[[],9]]
+
+[[9,8,9,[1,[2,3,7],[8,0,6],3,5]],[9,[5],2,[1,[9,1,5],[],1,7],9]]
+[[4],[1,4,4],[[[2,4,4,1,4],[],6],[1,[10],2,[10]],9,[],[7,5,8,1,[9,6,2,1,9]]]]
+
+[[[6,8,10,[10,0]],4,[7,7,1,4],2]]
+[[[3],5,2,[7,5,1]],[[[2,7,8],[0,8,1,8,7],[6,4,0,0],9]],[]]
+
+[[2,[[3,3,3,7]]],[[6,[6]],7,[[3,0,4,9],7,[3],3,9]],[[[8,9,5,5,0]]],[1,[[10,0,6,3],10]],[[[7,10],6],[5,2,0],[]]]
+[[6],[],[[5,9],6,5,8],[[1]],[9,[9,4,10],[9,[0,10,3],6],0]]
+
+[[[[9,8,3,10],[6,1],10,[5,2,1,4,1]]],[0,7],[0,[],[[9,4,4,5],[0,3,3,9,2]]],[8,9,8,4],[[8,3,[4,10,10],9],0,10,[[4,9,2,7,10],[],3,[2,0,3,1,0]]]]
+[[6,[8,[1]]],[6,2,[],8,[]],[[[1,2,6,6,8],[],[1,0,7,8]],[4,1,[1,7,3,9]]],[[[7,9,2,8,0],10,[3,7,8,10],[10,5,9,0,7],[7]],10,[6,2,1,6]]]
+
+[[],[0,[[10,8,9]]],[[[8],2],0,5,[[7,8,10,9],3,[0,4,2,9,6]]]]
+[[]]
+
+[[9,6,[3,[6],7],1,[8,[6],8,1]],[7,[0,[5,3,0],[0,10,4],[8,0,10]],0,[2,[5,8,4,1,0],10,7],4],[[[6,5,3],7,2,3,10]]]
+[[[[]],[[9,2,9],10,[7,5],[2,4,1]],[7,6,[5,7,4],[]],9]]
+
+[[8],[4,10,9,7,[6,[],7]],[0,10,[[]],[],4]]
+[[10,3],[9,[],[[9],[5],4,6,[4,10,2,7]],2],[],[[[8,0,7,7],[]],[[6,5,8,8,8],[4,5],3,[4,2,5],[9,4,0,6,9]],6,1,7],[]]
+
+[[10,[[2]]],[0,[[9,5,2,3,7],[2],6,[1,10],0],[10,[],[2,2],2,6],[]],[1,8,[8,7]],[10,[[3,10],[]],[[6,1,2,7],[8,0]]],[7,6,3,[[1],[4,4],2,[1]],1]]
+[[[[2],1,[8,7,8,8]],6,1],[[7,1],3],[[10,[8,2,4,8,4],[10,3]],7,4,[10]]]
+
+[[9,7,7,10,2]]
+[[[[8,1,3],[5],[9]],[[6,9,5],0,8,[0,5,2,6,0],[9,9,3,9,6]]],[],[[[],[3],0,[9,1,7]],9,5],[9,[9,6,4],[6,0,3,2,[]],[[3,2,0,9],9,9]]]
+
+[[[9,[7,2,6,9]],[]],[3,2,[0,[10,7,8,10],[2,6],[],1],[[9,4,0],[10,7,7],[1,9,2]]],[]]
+[[6,[6,9,[],[5],[6]]],[[[1,7],7,6],4]]
+
+[[],[3,4,[[4,10],[10,1]],4,7],[7,[[9,0,7,0,1],[3,6,6],3,[]]],[]]
+[[6,6,[[1,9,7],[6,8,3],0,[2,3,7,0],[6,4,3,0,10]]],[[[1],6],3,6,7],[]]
+
+[[],[[[10],5],[[9,9,7,7],[7]],5,6],[1,[[9],[10,10],10],3],[2,10,[8,5,[4,4,6,8,3],[5,0,5,6,8],5],7]]
+[[[[4,9],[0,6,3,2]],[]]]
+
+[[[8],6,6],[2]]
+[[[[4]],[9,8,[6,8],[5]],2,3,10],[],[[[1,3,2,1],[0,5],4,[7,2,3,3],[]],3,7],[[[10,7,9],4,7,3],2,2,[6,10,[0,9,2,7]],3],[[[10,5,7]],[4,[5,4]],5]]
+
+[[5,5,0,9,[]],[[9,[10,1],[0,6],2],8,10,[[2]]],[]]
+[[8,[9],[3,[1,5,6],9]],[[[],[],[0,10,8],[1,6,5,1,4]]],[10]]
+
+[[6,[],5],[[3]],[],[3],[[],0,[3,[2,9,4],2],[2],[10]]]
+[[10,10,[[9,9,10,9,10],10,[1,9,0],[4,1],[1,10]],[],[2,9,9]],[4,0]]
+
+[[1],[10,[[9,5,2,3,4],[],[6,1,0]],[8,[6,0,3,8]],[[10,1],1,[10,6,2],7,6],[7,9,[7,4],8,2]],[[10,2,[2,1,4,10,1],3],[3,1,[0,3,0,9,4],6,[6,4,9,9,1]],7,[6],1],[4,9,6,3,[[5,3,5,5,1],[5,3,9],[5],5,1]]]
+[[[],6,3,6,9],[9,3,[]],[[[5,10,5,6]],[8,[3,2,7],[],[1,2,9,4,4]]]]
+
+[[[[10,9],[4,4,5,7]]],[[[0,3,3,10,2],[9,0,3,5,1],[5,6]],6,2,3]]
+[[[2,[9,0,9],[3,7,6,8]],[[0],2]],[[[7,9,3]],4,10,8],[7,9]]
diff --git a/day13/uppga.c b/day13/uppga.c
@@ -0,0 +1,25 @@
+#include "common.h"
+
+int main(int argc, char** argv)
+{
+ char** lines;
+ size_t nlines = readlines(&lines, "input");
+
+ size_t i;
+ char* next = lines[0];
+ lori* loris[nlines];
+ size_t c = 0;
+ for(i = 0; i < nlines; i++) {
+ if(strlen(lines[i]) > 1) {
+ loris[c] = parseline(lines[i], &next);
+ c++;
+ }
+ }
+
+ uint64_t sum = 0;
+ for(i = 0; i < c; i+=2)
+ if(compare(loris[i], loris[i+1]) < 0)
+ sum += i/2 + 1;
+
+ printf("%llu\n", sum);
+}
diff --git a/day13/uppgb.c b/day13/uppgb.c
@@ -0,0 +1,42 @@
+#include "common.h"
+
+int cmp(const void* a, const void* b)
+{
+ lori* al = *((lori**) a);
+ lori* bl = *((lori**) b);
+ int c = compare(al, bl);
+ return c;
+}
+
+int main(int argc, char** argv)
+{
+ char** lines;
+ size_t nlines = readlines(&lines, "input");
+
+ lori* loris[nlines + 2];
+ lori* sig[2];
+
+ char* next = lines[0];
+ loris[0] = parseline("[[2]]", &next);
+ loris[1] = parseline("[[6]]", &next);
+ sig[0] = parseline("[[2]]", &next);
+ sig[1] = parseline("[[6]]", &next);
+
+ size_t i;
+ size_t c = 2;
+ for(i = 0; i < nlines; i++) {
+ if(strlen(lines[i]) > 1) {
+ loris[c] = parseline(lines[i], &next);
+ c++;
+ }
+ }
+
+ uint64_t sigidx[2] = {UINT64_MAX};
+ qsort(loris, c, sizeof(*loris), cmp);
+
+ for(i = 0; i < c; i++) {
+ if(compare(loris[i], sig[0]) == 0) sigidx[0] = i;
+ else if(compare(loris[i], sig[1]) == 0) sigidx[1] = i;
+ }
+ printf("%llu\n", (sigidx[0]+1) * (sigidx[1]+1));
+}
diff --git a/day14/Makefile b/day14/Makefile
@@ -0,0 +1,20 @@
+CC=clang
+UTILS=../utils/reading.o ../utils/stack_u64.o
+INCLUDES=-I../utils
+
+all: utils common.o uppga uppgb
+
+common.o: common.c common.h
+ $(CC) $(CFLAGS) -c common.c $(INCLUDES)
+
+uppga: $(UTILS) common.o uppga.c
+ $(CC) -Wall -o uppga uppga.c common.o $(UTILS) $(INCLUDES)
+
+uppgb: $(UTILS) common.o uppgb.c
+ $(CC) -Wall -o uppgb uppgb.c common.o $(UTILS) $(INCLUDES)
+
+utils:
+ make -C ../utils
+
+clean:
+ rm -rf common.o uppga uppgb
diff --git a/day14/common.c b/day14/common.c
@@ -0,0 +1,121 @@
+#include "common.h"
+
+void printgd(gd* g)
+{
+ size_t i,j;
+ for(j = 0; j < g->maxy; j++) {
+ for(i = 494; i < 504; i++) {
+ uint8_t v = g->grid[i * g->h + j];
+ if(v == 0) printf(".");
+ else if(v == 1) printf("#");
+ else printf("o");
+ }
+ printf("\n");
+ }
+}
+
+int sandfall(gd* g)
+{
+ size_t x = 500, y = 0;
+
+ while(y < g->maxy) {
+ assert(x > 0);
+ if(g->grid[x * g->h + (y+1)] == 0) {
+ y++;
+ } else if(g->grid[(x-1) * g->h + (y + 1)] == 0) {
+ x--;
+ y++;
+ } else if(g->grid[(x+1) * g->h + (y + 1)] == 0) {
+ x++;
+ y++;
+ } else {
+ g->grid[x * g->h + y] = 2;
+ if(x == 500 && y == 0) return 3;
+ return 0;
+ }
+ }
+ return 1;
+}
+
+gd* parse(char** lines, size_t nlines, int floor)
+{
+ stack_u64 xs[nlines+1], ys[nlines+1];
+ char* p;
+ size_t i,j;
+
+ uint64_t minx = UINT64_MAX, maxx = 0, miny = UINT64_MAX, maxy = 0;
+
+ for(i = 0; i < nlines; i++) {
+ stack_u64_init(&xs[i]);
+ stack_u64_init(&ys[i]);
+ uint64_t t;
+ size_t c = 0;
+ p = lines[i];
+ while((p = sread_next_u64(&t, p)) != NULL) {
+ if(c % 2 == 0) {
+ stack_u64_push(&xs[i], t);
+ if(t < minx) minx = t;
+ if(t > maxx) maxx = t;
+ } else {
+ stack_u64_push(&ys[i], t);
+ if(t < miny) miny = t;
+ if(t > maxy) maxy = t;
+ }
+ c++;
+ }
+ }
+
+ if(floor) {
+ maxy += 2;
+ maxx += maxy+1; // at most diagonal
+ stack_u64_init(&xs[nlines]);
+ stack_u64_init(&ys[nlines]);
+ stack_u64_push(&xs[nlines], 0);
+ stack_u64_push(&ys[nlines], maxy);
+ stack_u64_push(&xs[nlines], maxx);
+ stack_u64_push(&ys[nlines], maxy);
+ nlines++;
+ }
+
+ assert(minx > 0); // otherwise we would have to shift
+ assert(miny > 0);
+
+ uint8_t* grid = calloc((maxx+1) * (maxy+1), sizeof(*grid));
+
+ for(i = 0; i < nlines; i++) {
+ assert(xs[i].nmemb == ys[i].nmemb);
+ for(j = 0; j < xs[i].nmemb-1; j++) {
+ assert(xs[i].data[j] == xs[i].data[j+1] || ys[i].data[j] == ys[i].data[j+1]);
+ if(xs[i].data[j] == xs[i].data[j+1]) {
+ uint64_t x = xs[i].data[j];
+ uint64_t yfrom = ys[i].data[j] < ys[i].data[j+1] ? ys[i].data[j] : ys[i].data[j+1];
+ uint64_t yto = ys[i].data[j] < ys[i].data[j+1] ? ys[i].data[j+1] : ys[i].data[j];
+ while(yfrom != yto) {
+ grid[x * (maxy+1) + yfrom] = 1;
+ yfrom++;
+ }
+ grid[x * (maxy+1) + yfrom] = 1;
+ } else {
+ uint64_t y = ys[i].data[j];
+ uint64_t xfrom = xs[i].data[j] < xs[i].data[j+1] ? xs[i].data[j] : xs[i].data[j+1];
+ uint64_t xto = xs[i].data[j] < xs[i].data[j+1] ? xs[i].data[j+1] : xs[i].data[j];
+ while(xfrom != xto) {
+ grid[xfrom * (maxy+1) + y] = 1;
+ xfrom++;
+ }
+ grid[xfrom * (maxy+1) + y] = 1;
+ }
+ }
+ }
+
+ gd* r = malloc(sizeof(*r));
+ r->h = (size_t) maxy+1;
+ r->w = (size_t) maxx+1;
+ r->minx = minx;
+ r->miny = miny;
+ r->maxx = maxx;
+ r->maxy = maxy;
+ r->grid = grid;
+
+ return r;
+}
diff --git a/day14/common.h b/day14/common.h
@@ -0,0 +1,26 @@
+#ifndef COMMON_H_
+#define COMMON_H_
+
+#include <stdio.h>
+#include <stdint.h>
+#include <assert.h>
+#include <reading.h>
+#include <stack_u64.h>
+
+typedef struct {
+ size_t h;
+ size_t w;
+
+ uint64_t minx;
+ uint64_t miny;
+ uint64_t maxx;
+ uint64_t maxy;
+
+ uint8_t* grid;
+} gd;
+
+gd* parse(char** lines, size_t nlines, int floor);
+int sandfall(gd* g);
+void printgd(gd* g);
+
+#endif
diff --git a/day14/einput b/day14/einput
@@ -0,0 +1,2 @@
+498,4 -> 498,6 -> 496,6
+503,4 -> 502,4 -> 502,9 -> 494,9
diff --git a/day14/input b/day14/input
@@ -0,0 +1,137 @@
+497,60 -> 497,59 -> 497,60 -> 499,60 -> 499,55 -> 499,60 -> 501,60 -> 501,54 -> 501,60 -> 503,60 -> 503,53 -> 503,60 -> 505,60 -> 505,53 -> 505,60 -> 507,60 -> 507,52 -> 507,60 -> 509,60 -> 509,53 -> 509,60 -> 511,60 -> 511,58 -> 511,60
+497,60 -> 497,59 -> 497,60 -> 499,60 -> 499,55 -> 499,60 -> 501,60 -> 501,54 -> 501,60 -> 503,60 -> 503,53 -> 503,60 -> 505,60 -> 505,53 -> 505,60 -> 507,60 -> 507,52 -> 507,60 -> 509,60 -> 509,53 -> 509,60 -> 511,60 -> 511,58 -> 511,60
+497,76 -> 497,80 -> 494,80 -> 494,86 -> 508,86 -> 508,80 -> 503,80 -> 503,76
+498,13 -> 502,13
+525,120 -> 525,122 -> 522,122 -> 522,130 -> 535,130 -> 535,122 -> 531,122 -> 531,120
+504,21 -> 508,21
+492,17 -> 496,17
+534,137 -> 538,137
+497,60 -> 497,59 -> 497,60 -> 499,60 -> 499,55 -> 499,60 -> 501,60 -> 501,54 -> 501,60 -> 503,60 -> 503,53 -> 503,60 -> 505,60 -> 505,53 -> 505,60 -> 507,60 -> 507,52 -> 507,60 -> 509,60 -> 509,53 -> 509,60 -> 511,60 -> 511,58 -> 511,60
+479,34 -> 479,32 -> 479,34 -> 481,34 -> 481,30 -> 481,34 -> 483,34 -> 483,26 -> 483,34 -> 485,34 -> 485,25 -> 485,34 -> 487,34 -> 487,26 -> 487,34 -> 489,34 -> 489,32 -> 489,34
+469,37 -> 469,38 -> 487,38 -> 487,37
+548,160 -> 548,161 -> 561,161 -> 561,160
+497,60 -> 497,59 -> 497,60 -> 499,60 -> 499,55 -> 499,60 -> 501,60 -> 501,54 -> 501,60 -> 503,60 -> 503,53 -> 503,60 -> 505,60 -> 505,53 -> 505,60 -> 507,60 -> 507,52 -> 507,60 -> 509,60 -> 509,53 -> 509,60 -> 511,60 -> 511,58 -> 511,60
+497,76 -> 497,80 -> 494,80 -> 494,86 -> 508,86 -> 508,80 -> 503,80 -> 503,76
+497,60 -> 497,59 -> 497,60 -> 499,60 -> 499,55 -> 499,60 -> 501,60 -> 501,54 -> 501,60 -> 503,60 -> 503,53 -> 503,60 -> 505,60 -> 505,53 -> 505,60 -> 507,60 -> 507,52 -> 507,60 -> 509,60 -> 509,53 -> 509,60 -> 511,60 -> 511,58 -> 511,60
+479,34 -> 479,32 -> 479,34 -> 481,34 -> 481,30 -> 481,34 -> 483,34 -> 483,26 -> 483,34 -> 485,34 -> 485,25 -> 485,34 -> 487,34 -> 487,26 -> 487,34 -> 489,34 -> 489,32 -> 489,34
+525,120 -> 525,122 -> 522,122 -> 522,130 -> 535,130 -> 535,122 -> 531,122 -> 531,120
+497,60 -> 497,59 -> 497,60 -> 499,60 -> 499,55 -> 499,60 -> 501,60 -> 501,54 -> 501,60 -> 503,60 -> 503,53 -> 503,60 -> 505,60 -> 505,53 -> 505,60 -> 507,60 -> 507,52 -> 507,60 -> 509,60 -> 509,53 -> 509,60 -> 511,60 -> 511,58 -> 511,60
+514,110 -> 514,103 -> 514,110 -> 516,110 -> 516,101 -> 516,110 -> 518,110 -> 518,105 -> 518,110
+479,34 -> 479,32 -> 479,34 -> 481,34 -> 481,30 -> 481,34 -> 483,34 -> 483,26 -> 483,34 -> 485,34 -> 485,25 -> 485,34 -> 487,34 -> 487,26 -> 487,34 -> 489,34 -> 489,32 -> 489,34
+469,37 -> 469,38 -> 487,38 -> 487,37
+537,139 -> 537,140 -> 548,140 -> 548,139
+523,117 -> 527,117
+501,15 -> 505,15
+514,110 -> 514,103 -> 514,110 -> 516,110 -> 516,101 -> 516,110 -> 518,110 -> 518,105 -> 518,110
+497,76 -> 497,80 -> 494,80 -> 494,86 -> 508,86 -> 508,80 -> 503,80 -> 503,76
+514,110 -> 514,103 -> 514,110 -> 516,110 -> 516,101 -> 516,110 -> 518,110 -> 518,105 -> 518,110
+545,146 -> 545,150 -> 537,150 -> 537,156 -> 551,156 -> 551,150 -> 548,150 -> 548,146
+479,34 -> 479,32 -> 479,34 -> 481,34 -> 481,30 -> 481,34 -> 483,34 -> 483,26 -> 483,34 -> 485,34 -> 485,25 -> 485,34 -> 487,34 -> 487,26 -> 487,34 -> 489,34 -> 489,32 -> 489,34
+492,21 -> 496,21
+548,160 -> 548,161 -> 561,161 -> 561,160
+491,73 -> 491,63 -> 491,73 -> 493,73 -> 493,65 -> 493,73 -> 495,73 -> 495,68 -> 495,73 -> 497,73 -> 497,67 -> 497,73 -> 499,73 -> 499,68 -> 499,73
+497,60 -> 497,59 -> 497,60 -> 499,60 -> 499,55 -> 499,60 -> 501,60 -> 501,54 -> 501,60 -> 503,60 -> 503,53 -> 503,60 -> 505,60 -> 505,53 -> 505,60 -> 507,60 -> 507,52 -> 507,60 -> 509,60 -> 509,53 -> 509,60 -> 511,60 -> 511,58 -> 511,60
+497,60 -> 497,59 -> 497,60 -> 499,60 -> 499,55 -> 499,60 -> 501,60 -> 501,54 -> 501,60 -> 503,60 -> 503,53 -> 503,60 -> 505,60 -> 505,53 -> 505,60 -> 507,60 -> 507,52 -> 507,60 -> 509,60 -> 509,53 -> 509,60 -> 511,60 -> 511,58 -> 511,60
+525,120 -> 525,122 -> 522,122 -> 522,130 -> 535,130 -> 535,122 -> 531,122 -> 531,120
+469,37 -> 469,38 -> 487,38 -> 487,37
+497,60 -> 497,59 -> 497,60 -> 499,60 -> 499,55 -> 499,60 -> 501,60 -> 501,54 -> 501,60 -> 503,60 -> 503,53 -> 503,60 -> 505,60 -> 505,53 -> 505,60 -> 507,60 -> 507,52 -> 507,60 -> 509,60 -> 509,53 -> 509,60 -> 511,60 -> 511,58 -> 511,60
+525,120 -> 525,122 -> 522,122 -> 522,130 -> 535,130 -> 535,122 -> 531,122 -> 531,120
+481,45 -> 486,45
+495,15 -> 499,15
+525,120 -> 525,122 -> 522,122 -> 522,130 -> 535,130 -> 535,122 -> 531,122 -> 531,120
+491,73 -> 491,63 -> 491,73 -> 493,73 -> 493,65 -> 493,73 -> 495,73 -> 495,68 -> 495,73 -> 497,73 -> 497,67 -> 497,73 -> 499,73 -> 499,68 -> 499,73
+491,73 -> 491,63 -> 491,73 -> 493,73 -> 493,65 -> 493,73 -> 495,73 -> 495,68 -> 495,73 -> 497,73 -> 497,67 -> 497,73 -> 499,73 -> 499,68 -> 499,73
+497,60 -> 497,59 -> 497,60 -> 499,60 -> 499,55 -> 499,60 -> 501,60 -> 501,54 -> 501,60 -> 503,60 -> 503,53 -> 503,60 -> 505,60 -> 505,53 -> 505,60 -> 507,60 -> 507,52 -> 507,60 -> 509,60 -> 509,53 -> 509,60 -> 511,60 -> 511,58 -> 511,60
+514,110 -> 514,103 -> 514,110 -> 516,110 -> 516,101 -> 516,110 -> 518,110 -> 518,105 -> 518,110
+547,143 -> 552,143
+497,60 -> 497,59 -> 497,60 -> 499,60 -> 499,55 -> 499,60 -> 501,60 -> 501,54 -> 501,60 -> 503,60 -> 503,53 -> 503,60 -> 505,60 -> 505,53 -> 505,60 -> 507,60 -> 507,52 -> 507,60 -> 509,60 -> 509,53 -> 509,60 -> 511,60 -> 511,58 -> 511,60
+479,34 -> 479,32 -> 479,34 -> 481,34 -> 481,30 -> 481,34 -> 483,34 -> 483,26 -> 483,34 -> 485,34 -> 485,25 -> 485,34 -> 487,34 -> 487,26 -> 487,34 -> 489,34 -> 489,32 -> 489,34
+497,60 -> 497,59 -> 497,60 -> 499,60 -> 499,55 -> 499,60 -> 501,60 -> 501,54 -> 501,60 -> 503,60 -> 503,53 -> 503,60 -> 505,60 -> 505,53 -> 505,60 -> 507,60 -> 507,52 -> 507,60 -> 509,60 -> 509,53 -> 509,60 -> 511,60 -> 511,58 -> 511,60
+479,34 -> 479,32 -> 479,34 -> 481,34 -> 481,30 -> 481,34 -> 483,34 -> 483,26 -> 483,34 -> 485,34 -> 485,25 -> 485,34 -> 487,34 -> 487,26 -> 487,34 -> 489,34 -> 489,32 -> 489,34
+545,146 -> 545,150 -> 537,150 -> 537,156 -> 551,156 -> 551,150 -> 548,150 -> 548,146
+511,117 -> 515,117
+479,34 -> 479,32 -> 479,34 -> 481,34 -> 481,30 -> 481,34 -> 483,34 -> 483,26 -> 483,34 -> 485,34 -> 485,25 -> 485,34 -> 487,34 -> 487,26 -> 487,34 -> 489,34 -> 489,32 -> 489,34
+484,43 -> 489,43
+491,73 -> 491,63 -> 491,73 -> 493,73 -> 493,65 -> 493,73 -> 495,73 -> 495,68 -> 495,73 -> 497,73 -> 497,67 -> 497,73 -> 499,73 -> 499,68 -> 499,73
+497,60 -> 497,59 -> 497,60 -> 499,60 -> 499,55 -> 499,60 -> 501,60 -> 501,54 -> 501,60 -> 503,60 -> 503,53 -> 503,60 -> 505,60 -> 505,53 -> 505,60 -> 507,60 -> 507,52 -> 507,60 -> 509,60 -> 509,53 -> 509,60 -> 511,60 -> 511,58 -> 511,60
+491,73 -> 491,63 -> 491,73 -> 493,73 -> 493,65 -> 493,73 -> 495,73 -> 495,68 -> 495,73 -> 497,73 -> 497,67 -> 497,73 -> 499,73 -> 499,68 -> 499,73
+498,17 -> 502,17
+489,19 -> 493,19
+479,34 -> 479,32 -> 479,34 -> 481,34 -> 481,30 -> 481,34 -> 483,34 -> 483,26 -> 483,34 -> 485,34 -> 485,25 -> 485,34 -> 487,34 -> 487,26 -> 487,34 -> 489,34 -> 489,32 -> 489,34
+497,60 -> 497,59 -> 497,60 -> 499,60 -> 499,55 -> 499,60 -> 501,60 -> 501,54 -> 501,60 -> 503,60 -> 503,53 -> 503,60 -> 505,60 -> 505,53 -> 505,60 -> 507,60 -> 507,52 -> 507,60 -> 509,60 -> 509,53 -> 509,60 -> 511,60 -> 511,58 -> 511,60
+497,76 -> 497,80 -> 494,80 -> 494,86 -> 508,86 -> 508,80 -> 503,80 -> 503,76
+525,120 -> 525,122 -> 522,122 -> 522,130 -> 535,130 -> 535,122 -> 531,122 -> 531,120
+545,146 -> 545,150 -> 537,150 -> 537,156 -> 551,156 -> 551,150 -> 548,150 -> 548,146
+479,34 -> 479,32 -> 479,34 -> 481,34 -> 481,30 -> 481,34 -> 483,34 -> 483,26 -> 483,34 -> 485,34 -> 485,25 -> 485,34 -> 487,34 -> 487,26 -> 487,34 -> 489,34 -> 489,32 -> 489,34
+491,73 -> 491,63 -> 491,73 -> 493,73 -> 493,65 -> 493,73 -> 495,73 -> 495,68 -> 495,73 -> 497,73 -> 497,67 -> 497,73 -> 499,73 -> 499,68 -> 499,73
+497,60 -> 497,59 -> 497,60 -> 499,60 -> 499,55 -> 499,60 -> 501,60 -> 501,54 -> 501,60 -> 503,60 -> 503,53 -> 503,60 -> 505,60 -> 505,53 -> 505,60 -> 507,60 -> 507,52 -> 507,60 -> 509,60 -> 509,53 -> 509,60 -> 511,60 -> 511,58 -> 511,60
+491,73 -> 491,63 -> 491,73 -> 493,73 -> 493,65 -> 493,73 -> 495,73 -> 495,68 -> 495,73 -> 497,73 -> 497,67 -> 497,73 -> 499,73 -> 499,68 -> 499,73
+479,34 -> 479,32 -> 479,34 -> 481,34 -> 481,30 -> 481,34 -> 483,34 -> 483,26 -> 483,34 -> 485,34 -> 485,25 -> 485,34 -> 487,34 -> 487,26 -> 487,34 -> 489,34 -> 489,32 -> 489,34
+537,139 -> 537,140 -> 548,140 -> 548,139
+537,139 -> 537,140 -> 548,140 -> 548,139
+497,60 -> 497,59 -> 497,60 -> 499,60 -> 499,55 -> 499,60 -> 501,60 -> 501,54 -> 501,60 -> 503,60 -> 503,53 -> 503,60 -> 505,60 -> 505,53 -> 505,60 -> 507,60 -> 507,52 -> 507,60 -> 509,60 -> 509,53 -> 509,60 -> 511,60 -> 511,58 -> 511,60
+479,34 -> 479,32 -> 479,34 -> 481,34 -> 481,30 -> 481,34 -> 483,34 -> 483,26 -> 483,34 -> 485,34 -> 485,25 -> 485,34 -> 487,34 -> 487,26 -> 487,34 -> 489,34 -> 489,32 -> 489,34
+497,76 -> 497,80 -> 494,80 -> 494,86 -> 508,86 -> 508,80 -> 503,80 -> 503,76
+498,21 -> 502,21
+514,110 -> 514,103 -> 514,110 -> 516,110 -> 516,101 -> 516,110 -> 518,110 -> 518,105 -> 518,110
+545,146 -> 545,150 -> 537,150 -> 537,156 -> 551,156 -> 551,150 -> 548,150 -> 548,146
+517,113 -> 521,113
+534,133 -> 538,133
+545,146 -> 545,150 -> 537,150 -> 537,156 -> 551,156 -> 551,150 -> 548,150 -> 548,146
+491,73 -> 491,63 -> 491,73 -> 493,73 -> 493,65 -> 493,73 -> 495,73 -> 495,68 -> 495,73 -> 497,73 -> 497,67 -> 497,73 -> 499,73 -> 499,68 -> 499,73
+479,34 -> 479,32 -> 479,34 -> 481,34 -> 481,30 -> 481,34 -> 483,34 -> 483,26 -> 483,34 -> 485,34 -> 485,25 -> 485,34 -> 487,34 -> 487,26 -> 487,34 -> 489,34 -> 489,32 -> 489,34
+507,19 -> 511,19
+497,60 -> 497,59 -> 497,60 -> 499,60 -> 499,55 -> 499,60 -> 501,60 -> 501,54 -> 501,60 -> 503,60 -> 503,53 -> 503,60 -> 505,60 -> 505,53 -> 505,60 -> 507,60 -> 507,52 -> 507,60 -> 509,60 -> 509,53 -> 509,60 -> 511,60 -> 511,58 -> 511,60
+517,117 -> 521,117
+504,17 -> 508,17
+514,110 -> 514,103 -> 514,110 -> 516,110 -> 516,101 -> 516,110 -> 518,110 -> 518,105 -> 518,110
+487,41 -> 492,41
+507,89 -> 507,93 -> 499,93 -> 499,97 -> 516,97 -> 516,93 -> 510,93 -> 510,89
+479,34 -> 479,32 -> 479,34 -> 481,34 -> 481,30 -> 481,34 -> 483,34 -> 483,26 -> 483,34 -> 485,34 -> 485,25 -> 485,34 -> 487,34 -> 487,26 -> 487,34 -> 489,34 -> 489,32 -> 489,34
+497,60 -> 497,59 -> 497,60 -> 499,60 -> 499,55 -> 499,60 -> 501,60 -> 501,54 -> 501,60 -> 503,60 -> 503,53 -> 503,60 -> 505,60 -> 505,53 -> 505,60 -> 507,60 -> 507,52 -> 507,60 -> 509,60 -> 509,53 -> 509,60 -> 511,60 -> 511,58 -> 511,60
+507,89 -> 507,93 -> 499,93 -> 499,97 -> 516,97 -> 516,93 -> 510,93 -> 510,89
+478,47 -> 483,47
+491,73 -> 491,63 -> 491,73 -> 493,73 -> 493,65 -> 493,73 -> 495,73 -> 495,68 -> 495,73 -> 497,73 -> 497,67 -> 497,73 -> 499,73 -> 499,68 -> 499,73
+491,73 -> 491,63 -> 491,73 -> 493,73 -> 493,65 -> 493,73 -> 495,73 -> 495,68 -> 495,73 -> 497,73 -> 497,67 -> 497,73 -> 499,73 -> 499,68 -> 499,73
+497,60 -> 497,59 -> 497,60 -> 499,60 -> 499,55 -> 499,60 -> 501,60 -> 501,54 -> 501,60 -> 503,60 -> 503,53 -> 503,60 -> 505,60 -> 505,53 -> 505,60 -> 507,60 -> 507,52 -> 507,60 -> 509,60 -> 509,53 -> 509,60 -> 511,60 -> 511,58 -> 511,60
+492,47 -> 497,47
+545,146 -> 545,150 -> 537,150 -> 537,156 -> 551,156 -> 551,150 -> 548,150 -> 548,146
+488,45 -> 493,45
+525,120 -> 525,122 -> 522,122 -> 522,130 -> 535,130 -> 535,122 -> 531,122 -> 531,120
+491,43 -> 496,43
+514,110 -> 514,103 -> 514,110 -> 516,110 -> 516,101 -> 516,110 -> 518,110 -> 518,105 -> 518,110
+507,89 -> 507,93 -> 499,93 -> 499,97 -> 516,97 -> 516,93 -> 510,93 -> 510,89
+486,21 -> 490,21
+497,60 -> 497,59 -> 497,60 -> 499,60 -> 499,55 -> 499,60 -> 501,60 -> 501,54 -> 501,60 -> 503,60 -> 503,53 -> 503,60 -> 505,60 -> 505,53 -> 505,60 -> 507,60 -> 507,52 -> 507,60 -> 509,60 -> 509,53 -> 509,60 -> 511,60 -> 511,58 -> 511,60
+537,135 -> 541,135
+479,34 -> 479,32 -> 479,34 -> 481,34 -> 481,30 -> 481,34 -> 483,34 -> 483,26 -> 483,34 -> 485,34 -> 485,25 -> 485,34 -> 487,34 -> 487,26 -> 487,34 -> 489,34 -> 489,32 -> 489,34
+491,73 -> 491,63 -> 491,73 -> 493,73 -> 493,65 -> 493,73 -> 495,73 -> 495,68 -> 495,73 -> 497,73 -> 497,67 -> 497,73 -> 499,73 -> 499,68 -> 499,73
+491,73 -> 491,63 -> 491,73 -> 493,73 -> 493,65 -> 493,73 -> 495,73 -> 495,68 -> 495,73 -> 497,73 -> 497,67 -> 497,73 -> 499,73 -> 499,68 -> 499,73
+531,135 -> 535,135
+497,76 -> 497,80 -> 494,80 -> 494,86 -> 508,86 -> 508,80 -> 503,80 -> 503,76
+507,89 -> 507,93 -> 499,93 -> 499,97 -> 516,97 -> 516,93 -> 510,93 -> 510,89
+499,47 -> 504,47
+507,89 -> 507,93 -> 499,93 -> 499,97 -> 516,97 -> 516,93 -> 510,93 -> 510,89
+514,110 -> 514,103 -> 514,110 -> 516,110 -> 516,101 -> 516,110 -> 518,110 -> 518,105 -> 518,110
+479,34 -> 479,32 -> 479,34 -> 481,34 -> 481,30 -> 481,34 -> 483,34 -> 483,26 -> 483,34 -> 485,34 -> 485,25 -> 485,34 -> 487,34 -> 487,26 -> 487,34 -> 489,34 -> 489,32 -> 489,34
+479,34 -> 479,32 -> 479,34 -> 481,34 -> 481,30 -> 481,34 -> 483,34 -> 483,26 -> 483,34 -> 485,34 -> 485,25 -> 485,34 -> 487,34 -> 487,26 -> 487,34 -> 489,34 -> 489,32 -> 489,34
+497,76 -> 497,80 -> 494,80 -> 494,86 -> 508,86 -> 508,80 -> 503,80 -> 503,76
+501,19 -> 505,19
+495,45 -> 500,45
+540,137 -> 544,137
+520,115 -> 524,115
+510,21 -> 514,21
+485,47 -> 490,47
+491,73 -> 491,63 -> 491,73 -> 493,73 -> 493,65 -> 493,73 -> 495,73 -> 495,68 -> 495,73 -> 497,73 -> 497,67 -> 497,73 -> 499,73 -> 499,68 -> 499,73
+507,89 -> 507,93 -> 499,93 -> 499,97 -> 516,97 -> 516,93 -> 510,93 -> 510,89
+491,73 -> 491,63 -> 491,73 -> 493,73 -> 493,65 -> 493,73 -> 495,73 -> 495,68 -> 495,73 -> 497,73 -> 497,67 -> 497,73 -> 499,73 -> 499,68 -> 499,73
+548,160 -> 548,161 -> 561,161 -> 561,160
+497,60 -> 497,59 -> 497,60 -> 499,60 -> 499,55 -> 499,60 -> 501,60 -> 501,54 -> 501,60 -> 503,60 -> 503,53 -> 503,60 -> 505,60 -> 505,53 -> 505,60 -> 507,60 -> 507,52 -> 507,60 -> 509,60 -> 509,53 -> 509,60 -> 511,60 -> 511,58 -> 511,60
+495,19 -> 499,19
+514,115 -> 518,115
+507,89 -> 507,93 -> 499,93 -> 499,97 -> 516,97 -> 516,93 -> 510,93 -> 510,89
+497,60 -> 497,59 -> 497,60 -> 499,60 -> 499,55 -> 499,60 -> 501,60 -> 501,54 -> 501,60 -> 503,60 -> 503,53 -> 503,60 -> 505,60 -> 505,53 -> 505,60 -> 507,60 -> 507,52 -> 507,60 -> 509,60 -> 509,53 -> 509,60 -> 511,60 -> 511,58 -> 511,60
+479,34 -> 479,32 -> 479,34 -> 481,34 -> 481,30 -> 481,34 -> 483,34 -> 483,26 -> 483,34 -> 485,34 -> 485,25 -> 485,34 -> 487,34 -> 487,26 -> 487,34 -> 489,34 -> 489,32 -> 489,34
+497,60 -> 497,59 -> 497,60 -> 499,60 -> 499,55 -> 499,60 -> 501,60 -> 501,54 -> 501,60 -> 503,60 -> 503,53 -> 503,60 -> 505,60 -> 505,53 -> 505,60 -> 507,60 -> 507,52 -> 507,60 -> 509,60 -> 509,53 -> 509,60 -> 511,60 -> 511,58 -> 511,60
+528,137 -> 532,137
+545,146 -> 545,150 -> 537,150 -> 537,156 -> 551,156 -> 551,150 -> 548,150 -> 548,146
diff --git a/day14/uppga.c b/day14/uppga.c
@@ -0,0 +1,15 @@
+#include "common.h"
+
+int main(int argc, char** argv)
+{
+ char** lines;
+ size_t nlines = readlines(&lines, "input");
+
+ gd* g = parse(lines, nlines, 0);
+
+ int r;
+ size_t c = 0;
+ while((r = sandfall(g)) == 0) c++;
+
+ printf("%zu\n", c);
+}
diff --git a/day14/uppgb.c b/day14/uppgb.c
@@ -0,0 +1,16 @@
+#include "common.h"
+
+int main(int argc, char** argv)
+{
+ char** lines;
+ size_t nlines = readlines(&lines, "input");
+
+ gd* g = parse(lines, nlines, 1);
+ int r;
+ size_t c = 0;
+ while((r = sandfall(g)) == 0) c++;
+
+ assert(r == 3); // reached proper end
+
+ printf("%zu\n", c+1);
+}
diff --git a/day15/Makefile b/day15/Makefile
@@ -0,0 +1,20 @@
+CC=clang
+UTILS=../utils/reading.o
+INCLUDES=-I../utils
+
+all: utils common.o uppga uppgb
+
+common.o: common.c common.h
+ $(CC) $(CFLAGS) -c common.c $(INCLUDES)
+
+uppga: $(UTILS) common.o uppga.c
+ $(CC) -Wall -o uppga uppga.c common.o $(UTILS) $(INCLUDES)
+
+uppgb: $(UTILS) common.o uppgb.c
+ $(CC) -Wall -o uppgb uppgb.c common.o $(UTILS) $(INCLUDES)
+
+utils:
+ make -C ../utils
+
+clean:
+ rm -rf common.o uppga uppgb
diff --git a/day15/common.c b/day15/common.c
@@ -0,0 +1,78 @@
+#include "common.h"
+
+void parse(int* coords, char** lines, size_t nlines)
+{
+ size_t i;
+ for(i = 0; i < nlines; i++) {
+ sscanf(lines[i], "Sensor at x=%d, y=%d: closest beacon is at x=%d, y=%d",
+ &coords[4*i], &coords[4*i+1], &coords[4*i+2], &coords[4*i + 3]);
+ }
+}
+
+static inline int min(const int x, const int y)
+{
+ return x < y ? x : y;
+}
+
+static inline int max(const int x, const int y)
+{
+ return x < y ? y : x;
+}
+
+static inline int overlap(const iv *x, const iv *y)
+{
+ return (x->a <= y->b && y->b <= x->b) ||
+ (y->a <= x->b && x->b <= y->b);
+}
+
+void insert_interval(lh* head, iv* t)
+{
+ assert(t->a <= t->b);
+
+ iv* k;
+ LIST_FOREACH(k, head, entries) {
+ if(overlap(k, t)) {
+ t->a = min(k->a, t->a);
+ t->b = max(k->b, t->b);
+ LIST_REMOVE(k, entries);
+ insert_interval(head, t);
+ return;
+ }
+ }
+ LIST_INSERT_HEAD(head, t, entries);
+}
+
+lh* compintervals(int* coords, size_t n, int yl)
+{
+ int x0,y0,x1,y1,d;
+
+ lh* ret = malloc(sizeof(*ret));
+ LIST_INIT(ret);
+
+ iv* t;
+
+ size_t i;
+ for(i = 0; i < n; i++) {
+ x0 = coords[4*i]; y0 = coords[4*i+1]; x1 = coords[4*i+2]; y1 = coords[4*i+3];
+ d = abs(x0-x1) + abs(y0-y1);
+ if(abs(y0 - yl) <= d) {
+ t = malloc(sizeof(*t));
+ t->a = x0 - d + abs(y0 - yl);
+ t->b = x0 + d - abs(y0 - yl);
+ insert_interval(ret, t);
+ }
+ }
+
+ return ret;
+}
+
+void clear_lh(lh* head)
+{
+ iv* t;
+ while (!LIST_EMPTY(head)) {
+ t = LIST_FIRST(head);
+ LIST_REMOVE(t, entries);
+ free(t);
+ }
+ free(head);
+}
+\ No newline at end of file
diff --git a/day15/common.h b/day15/common.h
@@ -0,0 +1,23 @@
+#ifndef COMMON_H_
+#define COMMON_H_
+
+#include <stdio.h>
+#include <stdint.h>
+#include <assert.h>
+#include <sys/queue.h>
+#include <reading.h>
+
+
+typedef struct entry {
+ int a;
+ int b;
+
+ LIST_ENTRY(entry) entries;
+} iv;
+typedef LIST_HEAD(listhead, entry) lh;
+
+void parse(int* coords, char** lines, size_t nlines);
+lh* compintervals(int* coords, size_t n, int yl);
+void clear_lh(lh* head);
+
+#endif
diff --git a/day15/einput b/day15/einput
@@ -0,0 +1,14 @@
+Sensor at x=2, y=18: closest beacon is at x=-2, y=15
+Sensor at x=9, y=16: closest beacon is at x=10, y=16
+Sensor at x=13, y=2: closest beacon is at x=15, y=3
+Sensor at x=12, y=14: closest beacon is at x=10, y=16
+Sensor at x=10, y=20: closest beacon is at x=10, y=16
+Sensor at x=14, y=17: closest beacon is at x=10, y=16
+Sensor at x=8, y=7: closest beacon is at x=2, y=10
+Sensor at x=2, y=0: closest beacon is at x=2, y=10
+Sensor at x=0, y=11: closest beacon is at x=2, y=10
+Sensor at x=20, y=14: closest beacon is at x=25, y=17
+Sensor at x=17, y=20: closest beacon is at x=21, y=22
+Sensor at x=16, y=7: closest beacon is at x=15, y=3
+Sensor at x=14, y=3: closest beacon is at x=15, y=3
+Sensor at x=20, y=1: closest beacon is at x=15, y=3
+\ No newline at end of file
diff --git a/day15/input b/day15/input
@@ -0,0 +1,27 @@
+Sensor at x=3523437, y=2746095: closest beacon is at x=3546605, y=2721324
+Sensor at x=282831, y=991087: closest beacon is at x=743030, y=-87472
+Sensor at x=1473740, y=3283213: closest beacon is at x=1846785, y=3045894
+Sensor at x=1290563, y=46916: closest beacon is at x=743030, y=-87472
+Sensor at x=3999451, y=15688: closest beacon is at x=3283637, y=-753607
+Sensor at x=1139483, y=2716286: closest beacon is at x=1846785, y=3045894
+Sensor at x=3137614, y=2929987: closest beacon is at x=3392051, y=3245262
+Sensor at x=2667083, y=2286333: closest beacon is at x=2126582, y=2282363
+Sensor at x=3699264, y=2920959: closest beacon is at x=3546605, y=2721324
+Sensor at x=3280991, y=2338486: closest beacon is at x=3546605, y=2721324
+Sensor at x=833202, y=92320: closest beacon is at x=743030, y=-87472
+Sensor at x=3961416, y=2485266: closest beacon is at x=3546605, y=2721324
+Sensor at x=3002132, y=3500345: closest beacon is at x=3392051, y=3245262
+Sensor at x=2482128, y=2934657: closest beacon is at x=1846785, y=3045894
+Sensor at x=111006, y=2376713: closest beacon is at x=354526, y=3163958
+Sensor at x=424237, y=2718408: closest beacon is at x=354526, y=3163958
+Sensor at x=3954504, y=3606495: closest beacon is at x=3392051, y=3245262
+Sensor at x=2275050, y=2067292: closest beacon is at x=2333853, y=2000000
+Sensor at x=1944813, y=2557878: closest beacon is at x=2126582, y=2282363
+Sensor at x=2227536, y=2152792: closest beacon is at x=2126582, y=2282363
+Sensor at x=3633714, y=1229193: closest beacon is at x=3546605, y=2721324
+Sensor at x=1446898, y=1674290: closest beacon is at x=2333853, y=2000000
+Sensor at x=3713985, y=2744503: closest beacon is at x=3546605, y=2721324
+Sensor at x=2281504, y=3945638: closest beacon is at x=1846785, y=3045894
+Sensor at x=822012, y=3898848: closest beacon is at x=354526, y=3163958
+Sensor at x=89817, y=3512049: closest beacon is at x=354526, y=3163958
+Sensor at x=2594265, y=638715: closest beacon is at x=2333853, y=2000000
diff --git a/day15/uppga.c b/day15/uppga.c
@@ -0,0 +1,27 @@
+#include "common.h"
+
+int sumup(lh* head)
+{
+ int sum = 0;
+ iv* t;
+
+ LIST_FOREACH(t, head, entries) {
+ sum += (t->b - t->a);
+ }
+ return sum;
+}
+
+int main(int argc, char** argv)
+{
+ char** lines;
+ size_t nlines = readlines(&lines, "input");
+
+ int coords[nlines*4];
+ parse(coords, lines, nlines);
+
+ lh* h = compintervals(coords, nlines, 2000000);
+ int sum = sumup(h);
+ printf("%d\n", sum);
+
+ clear_lh(h);
+}
diff --git a/day15/uppgb.c b/day15/uppgb.c
@@ -0,0 +1,77 @@
+#include "common.h"
+
+typedef struct {
+ int x;
+ int y;
+ int d;
+} boll;
+
+#define LMT 4000000
+
+static inline int d(boll a, boll b)
+{
+ return abs(a.x - b.x) + abs(a.y - b.y);
+}
+
+static inline int inaball(int x, int y, boll* bs, size_t n) {
+ size_t i;
+ for(i = 0; i < n; i++)
+ if(abs(bs[i].x - x) + abs(bs[i].y - y) <= bs[i].d) return 1;
+ return 0;
+}
+
+int main(int argc, char** argv)
+{
+ char** lines;
+ size_t nlines = readlines(&lines, "input");
+
+ boll bs[nlines];
+ int x1, y1;
+ size_t i,j;
+ for(i = 0; i < nlines; i++) {
+ sscanf(lines[i], "Sensor at x=%d, y=%d: closest beacon is at x=%d, y=%d",
+ &bs[i].x, &bs[i].y, &x1, &y1);
+ bs[i].d = abs(bs[i].x - x1) + abs(bs[i].y - y1);
+ }
+
+ size_t ndownlines = 0;
+ int downline[4*nlines];
+ size_t nuplines = 0;
+ int upline[4*nlines];
+
+ for(i = 0; i < nlines; i++) {
+ for(j = i+1; j < nlines; j++) {
+ if(d(bs[i], bs[j]) == bs[i].d + bs[j].d + 2) {
+ if(abs(bs[i].x - bs[j].x + bs[i].y - bs[j].y) == bs[i].d + bs[j].d + 2) {
+ if(bs[i].x - bs[j].x + bs[i].y - bs[j].y == bs[i].d + bs[j].d + 2) {
+ downline[ndownlines] = bs[i].x + bs[i].y - bs[i].d - 1;
+ } else {
+ downline[ndownlines] = bs[i].x + bs[i].y - bs[i].d + 1;
+ }
+ ndownlines++;
+ } else {
+ if(bs[j].x - bs[i].x + bs[i].y - bs[j].y == bs[i].d + bs[j].d + 2) {
+ upline[nuplines] = - bs[i].y + bs[i].x + bs[i].d + 1;
+ } else {
+ upline[nuplines] = - bs[i].y + bs[i].x - bs[i].d - 1;
+ }
+ nuplines++;
+ }
+ }
+ }
+ }
+
+ for(i = 0; i < ndownlines; i++) {
+ for(j = 0; j < nuplines; j++) {
+ int x, y;
+ x = (downline[i] + upline[j])/2;
+ y = (downline[i] - upline[j])/2;
+ if(x >= 0 && y >= 0 && x <= LMT && y <= LMT && !inaball(x,y,bs,nlines)) {
+ printf("%llu\n", ((uint64_t) x)*((uint64_t) LMT) + ((uint64_t) y));
+ return 0;
+ }
+ }
+ }
+
+ return 0;
+}
diff --git a/day15/uppgb_old.c b/day15/uppgb_old.c
@@ -0,0 +1,46 @@
+#include "common.h"
+
+#define LMT 4000000
+
+int main(int argc, char** argv)
+{
+ char** lines;
+ size_t nlines = readlines(&lines, "input");
+
+ int coords[nlines*4];
+ parse(coords, lines, nlines);
+
+ uint64_t xc = UINT64_MAX;
+ uint64_t yc = UINT64_MAX;
+ int i;
+ for(i = 0; i < LMT; i++) {
+ lh* h = compintervals(coords, nlines, i);
+ iv* t;
+
+ int found = 0;
+ LIST_FOREACH(t, h, entries) {
+ if(t->a <= 0 && t->b >= LMT) {
+ found = 1;
+ break;
+ }
+ }
+
+ if(found) {
+ continue;
+ } else {
+ //this must be the line
+ LIST_FOREACH(t, h, entries) {
+ if(t->a <= 0 && t->b >= 0) {
+ xc = (uint64_t) (t->b + 1);
+ yc = (uint64_t) i;
+ break;
+ }
+ }
+ clear_lh(h);
+ break;
+ }
+ clear_lh(h);
+ }
+
+ printf("%lu\n", LMT*xc + yc);
+}
+\ No newline at end of file
diff --git a/day16/Makefile b/day16/Makefile
@@ -0,0 +1,21 @@
+CC=clang
+UTILS=../utils/reading.o
+INCLUDES=-I../utils
+CFLAGS=-O3
+
+all: utils common.o uppga uppgb
+
+common.o: common.c common.h
+ $(CC) $(CFLAGS) -c common.c $(INCLUDES)
+
+uppga: $(UTILS) common.o uppga.c
+ $(CC) $(CFLAGS) -Wall -o uppga uppga.c common.o $(UTILS) $(INCLUDES)
+
+uppgb: $(UTILS) common.o uppgb.c
+ $(CC) $(CFLAGS) -Wall -o uppgb uppgb.c common.o $(UTILS) $(INCLUDES)
+
+utils:
+ make -C ../utils
+
+clean:
+ rm -rf common.o uppga uppgb
diff --git a/day16/common.c b/day16/common.c
@@ -0,0 +1,6 @@
+#include "common.h"
+
+size_t fn(char** lines, size_t nlines)
+{
+ return 0;
+}
diff --git a/day16/common.h b/day16/common.h
@@ -0,0 +1,11 @@
+#ifndef COMMON_H_
+#define COMMON_H_
+
+#include <stdio.h>
+#include <stdint.h>
+#include <assert.h>
+#include <reading.h>
+
+size_t fn(char** lines, size_t nlines);
+
+#endif
diff --git a/day16/einput b/day16/einput
@@ -0,0 +1,10 @@
+Valve AA has flow rate=0; tunnels lead to valves DD, II, BB
+Valve BB has flow rate=13; tunnels lead to valves CC, AA
+Valve CC has flow rate=2; tunnels lead to valves DD, BB
+Valve DD has flow rate=20; tunnels lead to valves CC, AA, EE
+Valve EE has flow rate=3; tunnels lead to valves FF, DD
+Valve FF has flow rate=0; tunnels lead to valves EE, GG
+Valve GG has flow rate=0; tunnels lead to valves FF, HH
+Valve HH has flow rate=22; tunnel leads to valve GG
+Valve II has flow rate=0; tunnels lead to valves AA, JJ
+Valve JJ has flow rate=21; tunnel leads to valve II
diff --git a/day16/input b/day16/input
@@ -0,0 +1,52 @@
+Valve AP has flow rate=0; tunnels lead to valves AA, ON
+Valve QN has flow rate=21; tunnels lead to valves RI, CG
+Valve LK has flow rate=0; tunnels lead to valves XM, AA
+Valve HA has flow rate=0; tunnels lead to valves WH, KF
+Valve DS has flow rate=16; tunnel leads to valve II
+Valve KD has flow rate=0; tunnels lead to valves KG, QB
+Valve JW has flow rate=0; tunnels lead to valves AD, KF
+Valve HU has flow rate=0; tunnels lead to valves UK, CO
+Valve AE has flow rate=10; tunnels lead to valves IR, PT, UV
+Valve XA has flow rate=0; tunnels lead to valves CG, EU
+Valve SE has flow rate=17; tunnels lead to valves YR, AD
+Valve TR has flow rate=0; tunnels lead to valves AL, CS
+Valve BS has flow rate=0; tunnels lead to valves YH, XM
+Valve IJ has flow rate=24; tunnels lead to valves XN, WE
+Valve AA has flow rate=0; tunnels lead to valves LK, AP, IZ, PC, QD
+Valve KG has flow rate=0; tunnels lead to valves KD, CS
+Valve QV has flow rate=0; tunnels lead to valves XM, II
+Valve PC has flow rate=0; tunnels lead to valves AA, YF
+Valve GJ has flow rate=20; tunnel leads to valve RI
+Valve UV has flow rate=0; tunnels lead to valves UK, AE
+Valve IR has flow rate=0; tunnels lead to valves EU, AE
+Valve EU has flow rate=13; tunnels lead to valves IR, DT, XA, ON
+Valve ED has flow rate=0; tunnels lead to valves XN, CO
+Valve DT has flow rate=0; tunnels lead to valves EU, UK
+Valve YE has flow rate=0; tunnels lead to valves XM, WS
+Valve AD has flow rate=0; tunnels lead to valves JW, SE
+Valve WE has flow rate=0; tunnels lead to valves IJ, NA
+Valve UK has flow rate=5; tunnels lead to valves UV, DT, QD, HU
+Valve YR has flow rate=0; tunnels lead to valves OS, SE
+Valve II has flow rate=0; tunnels lead to valves QV, DS
+Valve GT has flow rate=0; tunnels lead to valves CS, MN
+Valve YH has flow rate=0; tunnels lead to valves BS, QB
+Valve BQ has flow rate=0; tunnels lead to valves XM, KF
+Valve OS has flow rate=0; tunnels lead to valves YR, NA
+Valve WH has flow rate=0; tunnels lead to valves QB, HA
+Valve QB has flow rate=4; tunnels lead to valves WH, KD, YH, IZ
+Valve ON has flow rate=0; tunnels lead to valves AP, EU
+Valve IZ has flow rate=0; tunnels lead to valves AA, QB
+Valve MN has flow rate=25; tunnel leads to valve GT
+Valve CG has flow rate=0; tunnels lead to valves XA, QN
+Valve QD has flow rate=0; tunnels lead to valves UK, AA
+Valve AL has flow rate=0; tunnels lead to valves KF, TR
+Valve XN has flow rate=0; tunnels lead to valves ED, IJ
+Valve WS has flow rate=0; tunnels lead to valves YE, CS
+Valve CO has flow rate=18; tunnels lead to valves ED, PT, HU
+Valve PT has flow rate=0; tunnels lead to valves CO, AE
+Valve RI has flow rate=0; tunnels lead to valves QN, GJ
+Valve CS has flow rate=9; tunnels lead to valves YF, GT, WS, TR, KG
+Valve YF has flow rate=0; tunnels lead to valves PC, CS
+Valve NA has flow rate=23; tunnels lead to valves OS, WE
+Valve KF has flow rate=12; tunnels lead to valves HA, AL, JW, BQ
+Valve XM has flow rate=3; tunnels lead to valves LK, QV, YE, BS, BQ
diff --git a/day16/sinput b/day16/sinput
@@ -0,0 +1,52 @@
+Valve AA has flow rate=0; tunnels lead to valves LK, AP, IZ, PC, QD
+Valve AD has flow rate=0; tunnels lead to valves JW, SE
+Valve AE has flow rate=10; tunnels lead to valves IR, PT, UV
+Valve AL has flow rate=0; tunnels lead to valves KF, TR
+Valve AP has flow rate=0; tunnels lead to valves AA, ON
+Valve BQ has flow rate=0; tunnels lead to valves XM, KF
+Valve BS has flow rate=0; tunnels lead to valves YH, XM
+Valve CG has flow rate=0; tunnels lead to valves XA, QN
+Valve CO has flow rate=18; tunnels lead to valves ED, PT, HU
+Valve CS has flow rate=9; tunnels lead to valves YF, GT, WS, TR, KG
+Valve DS has flow rate=16; tunnel leads to valve II
+Valve DT has flow rate=0; tunnels lead to valves EU, UK
+Valve ED has flow rate=0; tunnels lead to valves XN, CO
+Valve EU has flow rate=13; tunnels lead to valves IR, DT, XA, ON
+Valve GJ has flow rate=20; tunnel leads to valve RI
+Valve GT has flow rate=0; tunnels lead to valves CS, MN
+Valve HA has flow rate=0; tunnels lead to valves WH, KF
+Valve HU has flow rate=0; tunnels lead to valves UK, CO
+Valve II has flow rate=0; tunnels lead to valves QV, DS
+Valve IJ has flow rate=24; tunnels lead to valves XN, WE
+Valve IR has flow rate=0; tunnels lead to valves EU, AE
+Valve IZ has flow rate=0; tunnels lead to valves AA, QB
+Valve JW has flow rate=0; tunnels lead to valves AD, KF
+Valve KD has flow rate=0; tunnels lead to valves KG, QB
+Valve KF has flow rate=12; tunnels lead to valves HA, AL, JW, BQ
+Valve KG has flow rate=0; tunnels lead to valves KD, CS
+Valve LK has flow rate=0; tunnels lead to valves XM, AA
+Valve MN has flow rate=25; tunnel leads to valve GT
+Valve NA has flow rate=23; tunnels lead to valves OS, WE
+Valve ON has flow rate=0; tunnels lead to valves AP, EU
+Valve OS has flow rate=0; tunnels lead to valves YR, NA
+Valve PC has flow rate=0; tunnels lead to valves AA, YF
+Valve PT has flow rate=0; tunnels lead to valves CO, AE
+Valve QB has flow rate=4; tunnels lead to valves WH, KD, YH, IZ
+Valve QD has flow rate=0; tunnels lead to valves UK, AA
+Valve QN has flow rate=21; tunnels lead to valves RI, CG
+Valve QV has flow rate=0; tunnels lead to valves XM, II
+Valve RI has flow rate=0; tunnels lead to valves QN, GJ
+Valve SE has flow rate=17; tunnels lead to valves YR, AD
+Valve TR has flow rate=0; tunnels lead to valves AL, CS
+Valve UK has flow rate=5; tunnels lead to valves UV, DT, QD, HU
+Valve UV has flow rate=0; tunnels lead to valves UK, AE
+Valve WE has flow rate=0; tunnels lead to valves IJ, NA
+Valve WH has flow rate=0; tunnels lead to valves QB, HA
+Valve WS has flow rate=0; tunnels lead to valves YE, CS
+Valve XA has flow rate=0; tunnels lead to valves CG, EU
+Valve XM has flow rate=3; tunnels lead to valves LK, QV, YE, BS, BQ
+Valve XN has flow rate=0; tunnels lead to valves ED, IJ
+Valve YE has flow rate=0; tunnels lead to valves XM, WS
+Valve YF has flow rate=0; tunnels lead to valves PC, CS
+Valve YH has flow rate=0; tunnels lead to valves BS, QB
+Valve YR has flow rate=0; tunnels lead to valves OS, SE
diff --git a/day16/uppga.c b/day16/uppga.c
@@ -0,0 +1,231 @@
+#include "common.h"
+
+#define SEC 30ULL
+#define NOTCOMPUTED UINT64_MAX
+#define NONBR SIZE_MAX
+
+#define ASIZE ((uint64_t)('Z'-'A'+1))
+#define MAP_SIZE (ASIZE*ASIZE)
+
+typedef struct {
+ size_t n;
+ size_t m;
+
+ size_t nv;
+ uint64_t* v; // store computed values
+
+ uint64_t* flows;
+ size_t* nzflows; // maps position to index of nonzero flow (in e.g. state)
+ size_t** nbrs;
+} valves;
+
+static inline size_t statelen(valves v) {
+ return v.m + 2;
+}
+
+static inline size_t statemax(valves v) {
+ return ((v.n)*(SEC+1) << v.m)-1;
+}
+
+static inline int notime(uint64_t fs, valves v) {
+ return (fs >> v.m) % (SEC+1) == 0;
+}
+
+static inline char* goto_nbrs(char* s)
+{
+ size_t i=0, c=0;
+ while(c != 9) {
+ if(s[i] == ' ') c++;
+ i++;
+ }
+ return &(s[i]);
+}
+
+static inline size_t map_index(char* x)
+{
+ return ASIZE * ((uint64_t)(x[0] - 'A')) + ((uint64_t)(x[1] - 'A'));
+}
+
+void init_valves(valves* v, char** lines, const size_t n)
+{
+ v->n = n;
+ v->m = 0;
+
+ v->flows = malloc((v->n) * sizeof(*(v->flows)));
+ v->nzflows = malloc((v->n) * sizeof(*(v->nzflows)));
+ v->nbrs = malloc((v->n) * sizeof(*(v->nbrs)));
+
+ size_t i,j;
+ size_t map[MAP_SIZE];
+ for(i = 0; i < MAP_SIZE; i++) map[i] = SIZE_MAX;
+ for(i = 0; i < n; i++) {
+ char* line = lines[i];
+ map[map_index(&line[6])] = i;
+ }
+
+ for(i = 0; i < n; i++) {
+ char* line = lines[i];
+
+ char* flowstr = &line[23];
+ uint64_t flow;
+ sread_next_u64(&flow, flowstr);
+ v->flows[i] = flow;
+ if(flow != 0) {
+ v->nzflows[i] = v->m+2;
+ v->m++;
+ } else {
+ v->nzflows[i] = SIZE_MAX;
+ }
+
+ v->nbrs[i] = malloc((v->n) * sizeof(*(v->nbrs[i])));
+ char* nbrs = goto_nbrs(line);
+ char* cn = nbrs;
+ j = 0;
+ while(cn[0] != '\n' && cn[0] != '\0') {
+ assert(cn[0] <= 'Z' && cn[0] >= 'A');
+ assert(cn[1] <= 'Z' && cn[1] >= 'A');
+ v->nbrs[i][j] = map[map_index(cn)];
+ if(strlen(cn) < 4) {
+ j++;
+ break;
+ }
+ j++;
+ cn = &cn[4];
+ }
+ while(j < v->n) {
+ v->nbrs[i][j] = NONBR;
+ j++;
+ }
+ }
+
+ v->nv = statemax(*v) + 1;
+ v->v = malloc((v->nv) * sizeof(*(v->v)));
+ for(i = 0; i < v->nv; i++) v->v[i] = NOTCOMPUTED;
+}
+
+size_t f(const uint8_t* state, const valves* v) {
+ size_t r = ((unsigned long) state[0])*(SEC+1) + (unsigned long) state[1];
+ size_t i;
+ for(i = 0; i < v->m; i++) {
+ r <<= 1;
+ if(state[i+2]) r++;
+ }
+ return r;
+}
+
+void f_inv(uint8_t* state, const size_t y, const valves* v) {
+ size_t i;
+ size_t slen = statelen(*v);
+
+ size_t x = y;
+
+ for(i = 1; i <= v->m; i++) {
+ if((x & 0x01) != 0) {
+ state[slen-i] = 1;
+ } else {
+ state[slen-i] = 0;
+ }
+ x >>= 1;
+ }
+
+ assert(x < (SEC+1)*(v->n));
+
+ state[1] = (uint8_t) (x % (SEC+1));
+ state[0] = (uint8_t) (x / (SEC+1));
+}
+
+uint8_t* init_starting_state(valves v)
+{
+ uint8_t* r = malloc(statelen(v));
+
+ r[0] = 0; // posituon AA == 0
+ r[1] = SEC; // 30 secs remaining
+
+ size_t i;
+ for(i = 2; i < v.m+2; i++) r[i] = 0; // no valves on
+
+ return r;
+}
+
+static inline uint64_t stateflow(const uint8_t* state, const valves* v)
+{
+ uint64_t r = 0;
+ size_t i;
+ for(i = 0; i < v->n; i++) {
+ if(v->flows[i] != 0) {
+ r += ((uint64_t) state[v->nzflows[i]]) * v->flows[i];
+ }
+ }
+ return r;
+}
+
+void print_state(const uint8_t* state, const valves* v)
+{
+ printf("%u : %u : ", state[0], state[1]);
+ size_t i;
+ for(i = 0; i < v->m; i++) {
+ printf("%u ", state[i+2]);
+ }
+ printf("\n");
+}
+
+uint64_t recurse(const uint64_t fs, valves* v, int level)
+{
+ if(v->v[fs] != NOTCOMPUTED) return v->v[fs];
+ uint64_t r = 0;
+
+ if(notime(fs, *v)) {
+ v->v[fs] = r;
+ return r;
+ }
+
+ uint8_t state[statelen(*v)];
+ f_inv(state, fs, v);
+
+ size_t pos = (size_t) state[0];
+
+ // nonzero flow
+ if(v->flows[pos] != 0) {
+ if(state[v->nzflows[pos]] == 0) {
+ uint8_t new_state[statelen(*v)];
+ memcpy(new_state, state, statelen(*v));
+ new_state[v->nzflows[pos]] = 1;
+ new_state[1]--;
+ uint64_t t = stateflow(state, v) + recurse(f(new_state, v), v, level+1);
+ if(t > r) r = t;
+ }
+ }
+
+ // neighbours
+ size_t i = 0;
+ while(v->nbrs[pos][i] != NONBR) {
+ uint8_t new_state[statelen(*v)];
+ memcpy(new_state, state, statelen(*v));
+ new_state[1]--;
+ new_state[0] = (uint8_t) v->nbrs[pos][i];
+ uint64_t t = stateflow(state, v) + recurse(f(new_state, v), v, level+1);
+ if(t > r) r = t;
+ i++;
+ }
+
+ v->v[fs] = r;
+ return r;
+}
+
+int main(int argc, char** argv)
+{
+ char** lines;
+ valves v;
+ size_t nlines = readlines(&lines, "sinput");
+
+ init_valves(&v, lines, nlines);
+
+ uint8_t* starting_state = init_starting_state(v);
+
+ size_t f_ss = f(starting_state, &v);
+ uint8_t* tmp_state = malloc(statelen(v));
+ f_inv(tmp_state, f_ss, &v);
+
+ uint64_t r = recurse(f_ss, &v, 0);
+ printf("%llu\n", r);
+}
diff --git a/day16/uppgb.c b/day16/uppgb.c
@@ -0,0 +1,260 @@
+#include "common.h"
+
+#define SEC 30ULL
+#define NOTCOMPUTED UINT64_MAX
+#define NONBR SIZE_MAX
+
+#define ASIZE ((uint64_t)('Z'-'A'+1))
+#define MAP_SIZE (ASIZE*ASIZE)
+
+typedef struct {
+ size_t n;
+ size_t m;
+
+ size_t nv;
+ uint64_t* v; // store computed values
+
+ uint64_t* flows;
+ size_t* nzflows; // maps position to index of nonzero flow (in e.g. state)
+ size_t** nbrs;
+} valves;
+
+static inline size_t statelen(valves v) {
+ return v.m + 2;
+}
+
+static inline size_t statemax(valves v) {
+ return ((v.n)*(v.n) << v.m)-1;
+}
+
+static inline char* goto_nbrs(char* s)
+{
+ size_t i=0, c=0;
+ while(c != 9) {
+ if(s[i] == ' ') c++;
+ i++;
+ }
+ return &(s[i]);
+}
+
+static inline size_t map_index(char* x)
+{
+ return ASIZE * ((uint64_t)(x[0] - 'A')) + ((uint64_t)(x[1] - 'A'));
+}
+
+void init_valves(valves* v, char** lines, const size_t n)
+{
+ v->n = n;
+ v->m = 0;
+
+ v->flows = malloc((v->n) * sizeof(*(v->flows)));
+ v->nzflows = malloc((v->n) * sizeof(*(v->nzflows)));
+ v->nbrs = malloc((v->n) * sizeof(*(v->nbrs)));
+
+ size_t i,j;
+ size_t map[MAP_SIZE];
+ for(i = 0; i < MAP_SIZE; i++) map[i] = SIZE_MAX;
+ for(i = 0; i < n; i++) {
+ char* line = lines[i];
+ map[map_index(&line[6])] = i;
+ }
+
+ for(i = 0; i < n; i++) {
+ char* line = lines[i];
+
+ char* flowstr = &line[23];
+ uint64_t flow;
+ sread_next_u64(&flow, flowstr);
+ v->flows[i] = flow;
+ if(flow != 0) {
+ v->nzflows[i] = v->m;
+ v->m++;
+ } else {
+ v->nzflows[i] = SIZE_MAX;
+ }
+
+ v->nbrs[i] = malloc((v->n) * sizeof(*(v->nbrs[i])));
+ char* nbrs = goto_nbrs(line);
+ char* cn = nbrs;
+ j = 0;
+ while(cn[0] != '\n' && cn[0] != '\0') {
+ assert(cn[0] <= 'Z' && cn[0] >= 'A');
+ assert(cn[1] <= 'Z' && cn[1] >= 'A');
+ v->nbrs[i][j] = map[map_index(cn)];
+ if(strlen(cn) < 4) {
+ j++;
+ break;
+ }
+ j++;
+ cn = &cn[4];
+ }
+ while(j < v->n) {
+ v->nbrs[i][j] = NONBR;
+ j++;
+ }
+ }
+
+ v->nv = statemax(*v) + 1;
+ v->v = malloc((v->nv) * sizeof(*(v->v)));
+}
+
+size_t f(const uint8_t* state, const valves* v) {
+ size_t r = ((unsigned long) state[0])*(v->n) + (unsigned long) state[1];
+ size_t i;
+ for(i = 0; i < v->m; i++) {
+ r <<= 1;
+ if(state[i+2]) r++;
+ }
+ return r;
+}
+
+void f_inv(uint8_t* state, const size_t y, const valves* v) {
+ size_t i;
+ size_t slen = statelen(*v);
+
+ size_t x = y;
+
+ for(i = 1; i <= v->m; i++) {
+ if((x & 0x01) != 0) {
+ state[slen-i] = 1;
+ } else {
+ state[slen-i] = 0;
+ }
+ x >>= 1;
+ }
+
+ assert(x < (v->n)*(v->n));
+
+ state[1] = (uint8_t) (x % (v->n));
+ state[0] = (uint8_t) (x / (v->n));
+}
+
+uint8_t* init_starting_state(valves v)
+{
+ uint8_t* r = malloc(statelen(v));
+
+ r[0] = 0; // posituon AA == 0
+ r[1] = 0; // elephant position same
+
+ size_t i;
+ for(i = 2; i < v.m+2; i++) r[i] = 0; // no valves on
+
+ return r;
+}
+
+static inline uint64_t stateflow(uint64_t b, const valves* v)
+{
+ uint64_t r = 0;
+ size_t i;
+ for(i = 0; i < v->n; i++) {
+ if(v->flows[i] != 0 && (b & (0x1 << v->nzflows[i])) != 0) {
+ r += v->flows[i];
+ }
+ }
+ return r;
+}
+
+void print_state(const uint8_t* state, const valves* v)
+{
+ printf("%u : %u : ", state[0], state[1]);
+ size_t i;
+ for(i = 0; i < v->m; i++) {
+ printf("%u ", state[i+2]);
+ }
+ printf("\n");
+}
+
+static inline uint64_t vss(size_t s, valves* v) {
+ return 0x01 << (v->m - s - 1);
+}
+
+static inline uint64_t fss(uint64_t py, uint64_t pe, uint64_t b, valves* v)
+{
+ uint64_t r = py * (v->n) + pe;
+ size_t i;
+ for(i = 0; i < v->m; i++) {
+ r <<= 1;
+ if((b & vss(i, v)) != 0) r++;
+ }
+ return r;
+}
+
+uint64_t* compute_level(valves* v, int level)
+{
+ size_t i,j;
+ uint64_t b;
+ uint64_t* new = malloc((v->nv) * sizeof(*new));
+
+ if(level <= 0) {
+ for(i = 0; i < v->nv; i++) new[i] = 0;
+ } else {
+ size_t blim = (1 << v->m);
+ for(i = 0; i < v->n; i++) { // you pos
+ for(j = 0; j < v->n; j++) { // E pos
+ for(b = 0; b < blim; b++) {
+ uint64_t best = 0;
+ if(v->flows[i] != 0 && v->flows[j] != 0) {
+ best = v->v[fss(i, j, (b | (0x01 << v->nzflows[i]) | (0x01 << v->nzflows[j])), v)];
+ }
+
+ uint64_t bprim;
+ size_t k = 0, l;
+ uint64_t t;
+ if(v->flows[i] != 0) {
+ k = 0;
+ bprim = b | (0x01 << v->nzflows[i]);
+ while(v->nbrs[j][k] != NONBR) {
+ t = v->v[fss(i, v->nbrs[j][k], bprim, v)];
+ if(t > best) best = t;
+ k++;
+ }
+ }
+
+ if(v->flows[j] != 0) {
+ bprim = b | (0x01 << v->nzflows[j]);
+ k = 0;
+ while(v->nbrs[i][k] != NONBR) {
+ t = v->v[fss(v->nbrs[i][k], j, bprim, v)];
+ if(t > best) best = t;
+ k++;
+ }
+ }
+
+ k = 0;
+ while(v->nbrs[i][k] != NONBR) {
+ l = 0;
+ while(v->nbrs[j][l] != NONBR) {
+ t = v->v[fss(v->nbrs[i][k], v->nbrs[j][l], b, v)];
+ if(t > best) best = t;
+ l++;
+ }
+ k++;
+ }
+
+ new[fss(i,j,b,v)] = stateflow(b,v) + best;
+ }
+ }
+ }
+ }
+
+ return new;
+}
+
+int main(int argc, char** argv)
+{
+ char** lines;
+ valves v;
+ size_t nlines = readlines(&lines, "sinput");
+
+ init_valves(&v, lines, nlines);
+ uint64_t* r;
+ size_t i;
+ for(i = 0; i < 27; i++) {
+ printf("--- LEVEL %zu ---\n", i);
+ r = compute_level(&v, i);
+ free(v.v);
+ v.v = r;
+ }
+
+ printf("%llu\n", v.v[fss(0,0,0,&v)]);
+}
diff --git a/day17/Makefile b/day17/Makefile
@@ -0,0 +1,23 @@
+CC=clang
+UTILS=../utils/reading.o
+INCLUDES=-I../utils
+
+all: utils common.o uppga uppgb uppgc
+
+common.o: common.c common.h
+ $(CC) $(CFLAGS) -c common.c $(INCLUDES)
+
+uppga: $(UTILS) common.o uppga.c
+ $(CC) -Wall -o uppga uppga.c common.o $(UTILS) $(INCLUDES)
+
+uppgb: $(UTILS) common.o uppgb.c
+ $(CC) -Wall -o uppgb uppgb.c common.o $(UTILS) $(INCLUDES)
+
+uppgc: $(UTILS) common.o uppgc.c
+ $(CC) -O3 -o uppgc uppgc.c common.o $(UTILS) $(INCLUDES)
+
+utils:
+ make -C ../utils
+
+clean:
+ rm -rf common.o uppga uppgb uppgc
diff --git a/day17/common.c b/day17/common.c
@@ -0,0 +1,6 @@
+#include "common.h"
+
+size_t fn(char** lines, size_t nlines)
+{
+ return 0;
+}
diff --git a/day17/common.h b/day17/common.h
@@ -0,0 +1,11 @@
+#ifndef COMMON_H_
+#define COMMON_H_
+
+#include <stdio.h>
+#include <stdint.h>
+#include <assert.h>
+#include <reading.h>
+
+size_t fn(char** lines, size_t nlines);
+
+#endif
diff --git a/day17/einput b/day17/einput
@@ -0,0 +1 @@
+>>><<><>><<<>><>>><<<>>><<<><<<>><>><<>>
diff --git a/day17/input b/day17/input
@@ -0,0 +1 @@
+><<<>>><<<><<<>>><<>>>><<<>>>><>>>><<<>>><<<<>>><<>>>><<<>>><<<<>>><<<<>>><<<<>>>><<<<>>>><<<<>><<<<><<<<><<<>>>><<<>><<>>><<<>><<>>><<>>><>><<<>><<<<>>><<>><>>><<<<>>><>><>>><<<<>>>><<<>>><<<><<<<>>><><>>>><<<><<<<>><<<>><<<>>>><><<<><<>>>><<>>>><<<><<>>>><<>><<><<<>><>>>><<<>>>><<<>><>><<<>>>><<<<><<><<<>><<>>>><<<<>><<<<><<<<><<<<><>><<><<>>><>><<<<>>><>>><>>>><<<<>>><><<>><<<<><<<>>><>>><<<><<<<><<<<><<<<>><>>><><><<<<>><>>>><<<<><>><<<<>>><<<>>><<>>>><<<<><>>>><<>><<<<>>>><<>>><<<>>><><<>>>><<<<>><<>>><<<>><><<<<>>>><<<<>>><>>>><<>>>><<<>>><>>>><<<>>>><<><<>>><>>><<<>>><<<>><>>><<<<>><<<><<>>><>>>><<<<>>><<<>>><<<<>>><<<<>><<>><><<<<>><<<>>><<<<><<<<>>>><<<>><<<><>>><<>>>><<<>>>><<>>><<<<>>><<<>>>><<<>><<<<>>><<<<>>><<>>>><<<>>>><>>><<<>>>><<>><>>>><<>>>><<<>>>><<<<><<<><<>><<<>><<<>>>><<>>>><<<<>><>>>><<<<><<<<>><<>><<>><<<<>>><<>><<><>>>><<<>><>><<>><<>><>><<<>><<<<><<<>>>><<<>>>><<<<>><>><<<<><<<>><<<<>>><>>><<<<><<<>><<<<>><<>>>><<<>>>><<<<>><<<>><><<<<>>><>><<><<<<>><<<><<<><<<<>>>><<<<>>>><><>><<<>>>><<<<>><>>><<<<><<>>><<<>>>><<>><<<>>><>>><<><<<>>><<<><<<>>><<<<><<<<>><<><<>><><<<<>><<<<>>>><><<<>>>><<<>><>>>><<>>>><<<<>>>><<<>>><<<<><<>>>><<<><<<>>>><<><<<>>>><><<<><>>>><>>>><<<>>><>><>>>><>><<>>><>>>><<<>>><<>>>><<>>>><<><<<<>>>><<>>><>><<<<>>><<<>>>><<<>>>><<>>><>><>><<<<>>>><<><<><>>>><<>>>><>>><<<<>>>><<<<>>><<><<<><<>>>><<>>><>>><>>><<<><<<>>>><<<>><<>>><><<<<>>><<<<>><<<>>>><<>><<<<><<<><<<<>><<<<>>>><<><<<><<<<>>>><<<<><<<<>>><<<>>>><<<>>><><<<<>>>><<<>><<<<><>><<<><<>>><>>>><<<><<<<>><<<<><<<<>><<>>>><>><<<>>>><<<<><<<>><<<>>>><><<<>><<<><<<<>>>><><<>><<>>><<<<><<<<><<<<><<>>>><<>>>><<><<<<>><<<<>><<<><>><<<<><<<>>>><<<>><>>>><<<<><<<<><<>><<>><<<<>><<<<>><><><<>><<<<>>>><<<>>>><>>><<<>>>><<>>><><><<><>>><<<<>>>><<>>><<<>>>><<<>>>><>><<<<>>>><<<<>>><<>>>><>>><<<<>>>><<<>>>><<<<>><><>><<<>>>><<>><<<>>><>>>><<<>>>><>><<<>>><<<<>><<<>><<<<>>>><>>>><><><<>><<<<>><<<>><<><<<<>><<>>><>><<><<>><<<<>>><>>>><<<>>>><<>>><>>>><<<><<<<>>>><<<><<<><<<>><<>>>><<<><<<<><<<<>>>><<<<>>>><<<><<<<>>><<>>>><<<>><<<>><<>>>><<>><<<>>>><><<<<>><><<<<>><<<>>><<<>>>><<<>>>><<>>><<<>><<<><>><><<<><>>>><<><<<<>>>><>>><<>>><>>>><<<<>>>><<>><<<<>><<<>><><<<<>><<>>>><<>>>><<<>><<<<>>><<><<<<>>><<>>>><<>><<<<>><<><<<><>><>>><>><<<>>><<<<>>><<>>>><<<><<<<><<<<>><<<<>>>><<<<>>><<>><<<><>>>><<<><<>>>><<<>><>>>><<<<>><<<<>><<>>>><<><<<><>>><<<>>><<>>><<>><<<<>>>><<<<>><<<<>><<<>>>><<<<>>><<>>><<<<><<<>>><<<><<>><<<<>><>>><<><<>>><<<<>>>><<<>>><<<>><<<<>>>><<>><<<<>><><<>>>><>><<<>><<<>><<<<>><>><>><<<>>>><<>><<><<>>><<>>>><<<<>>><<>>>><><<<>>><<>><<<<><<<<>><<>>>><<<<>>>><>>><>>><<<>><><<<>>><<<<>>><>>>><<<>><<<<><<<>>><<<<>>>><<<>>>><<<<>>><<<>><<<<>>><<<>>>><<<<>>>><>>><<<<><><<><<><<>>>><>>>><<<>>><<><><><<<<><<<<>>><<<>>>><<<<>>>><>>><<>>><<>><<<>>>><<><<>><<>>><<<><<<><<<>>>><>><>>><>>>><<<<>>><>><<<><>>>><<<>>>><<<><<<<>>><<<<><<>>><>>>><><<><<<<>>><>>><>><<>>><<<>>>><<<>>>><<<<><<<>>><<<<><<<>>>><<<>>>><>>><<>>>><<>>><<<<><>>><<<><<>><>>><>><<>><<>><<<>>>><<<<>><<<>>><<<<>>>><<>><>>><>>><<<>><<<><<>><>><><<<>>>><<<><<>><<<>>><<<<>><<<>>>><<<<>><>>>><>><<<><>>>><<<<><<<><>>>><<<>>>><><>>><><>>><<<>>>><<>>><<>><<>><>><>>>><<<>>>><><>>><<<<>>><<<>><<><>><<<<>>><<>>>><<<>>><<<>>><<<><<<>><<<<>>><><>>>><<>><<<>>><<<<>><<<>><><<<>>><<<><>>>><><<>><<<><<<>>><<<>>><<>>>><<<>>><<<<>>>><<>>>><<>>><<<<>><>>>><<>>>><><<>><><<<<>><<>>><<>>><<<><<>>><<<>><<<>>>><<>>><>>>><<<><<<><<>>>><><<<<>>><<>>><<<<>>>><<<>>><<<<>>>><<<<>><<>><<>>><<<>>><<<><<<<>>>><<>><<<><<<<>><<<<>>>><<><<<<><>><><<<>><<><<<>>>><<><<<><>>>><<<>>>><<<<><<>>><<<>>><<>>><<><<<<><>>><<>><<<<><<<>><<><><<<><<<><><>>><<><>>>><<><<<><<<<>>>><><<>>>><<><<><<<>>><<<<>><<<><<<>>><<<>>>><<<<>>><<>>>><<<><<<<>><<<<><<<>>>><<<>>>><<<>>>><<<>><<>>>><>><<<><<>>><<<<>>>><><<<<>>><<>><<>><<<<>><<<<><<<<>><<<<>><<<<>>><<>>>><<<<>>>><<<<>>><<<><><<<<>>><<<>>><<>><<><<<>>>><<>><<<><>><<<<>>><<<<><<<<><<><>><<>>><<<><<><<<<>>><<<>>><<<<>><<<<>>>><>>>><><<>><<>><>><<<><<>>>><<<>><<<><<>><<><<<<>>><<>>><<<<>>>><>><<>>>><<<>>><>><<<<>>><<<<>>>><<<>>><<>>><<<<><<<><>>><>><<<>>>><><<<>><<><>><<<><<<>><<>>>><<>>>><<<>><<<>>>><>>><><>>><<<>>>><<<>>><<<><<<<>><<<<><><<<><<><<<<>><><<<<>>><<<>><<<<>>>><<<>>>><<<>>><<<>>><<>>>><<>>>><<<>>>><<<>>><<<>><>>><>>><<<>>>><<>>>><<><>>>><<<><<<>>>><<><<<>><<>><<<<><<<<>>>><<<<><>>><<<<>>>><<<>>>><><<><<<>>>><<<><<>><<>>>><>>><>>>><<>>><<>><<>>><>>><<<>>>><<<>>><<<<>>><<<>>>><<<<>><><<>>>><<<<><>>><<><<<>>>><>>>><<>>>><<<><<><<<<>>>><>>><<<>>>><<<>><><<>>><<<><<>><><<<>>><<<<><<><<<>>><<>>><>>>><>>><<>>><>><><<<<>>>><<<<>>>><><<<<><<<<><<<<>>>><<<<>>><<<<><<<>><<>>>><<><<<>>><<><<<>><>>><<<<>>><<><<>>><<<><<><<<>><<<<><<>>><><<>><><><<<><<>>><<>>>><<<<>>><<<>><<<<><<>>>><>>>><<<<><<<<>>>><<>>><<<<>>><<>>><<<>>><>>><<<>>>><<<>><<><<<<><>>>><<>><<>>>><<<>>><<<>>><>>><<<<>><<<<>><<><<<<>>><<>>>><>>>><>>><<<<>>>><><<<>>>><<<<>>>><<<>>>><<<>>>><<<<><<<>>>><<<>>><<<<>>>><<<><>>><><>>>><<<<>><<>>><<<><<<<><<>><<<<>><><<><<<>>><<<<>><<<>>>><<<>>>><<><>>><<>>><<<>>><<<<><<<<>>><<<<>><>>>><<<<>>>><<<><<<<>>><<>>>><<<>>>><<><>>>><<>>>><<>><<<>><<>>><<<<>>>><<><>>><<><<<>>>><<<<>><>>><><>>>><<<>><<<<>>>><<<<><<>>>><<<<>><<<>>><><<<<>>><<>>>><<>>>><<<><<><<<<>>><<<<>>>><<<><<<<><><<<<>>>><<<<>>><<<<><<<><<<>><><<<<><<>>><<<>><<<>>>><<>>>><<>>>><<>>>><<><<<<>><<<<><<<<>>><<><>>>><>>><><>><<><<>>>><<<<><>><<<<><<>><<>>><>><<<>><>><>><<<>>><<>>>><<<>>>><<>>><<>>>><<>>><<<<>>><<<<>>><<<<><<>>>><<<<>>>><<<>>><>>><<>>>><<<>>>><>>>><>><<<<>>>><<<<><<>>>><<<<><>>>><<<>><<<<>>>><>>><<<<>>>><<>>><<<<>><<<<><<<>><<<>><<>><>>>><>><<<<>>>><<<>><<>><<>>><<<>>>><>>>><<>>><>>><<><<>><<<<>><<<>>><<<><<<>>><<<<>>><<<><<<>>>><<<<><<>>><<<>>>><>>>><<<<><><<<<>>>><<>>><>>><<<<>>>><<<<>><<>><<<>>>><<<>><>>>><>>>><><<<>>>><<<<><<<>>><<>>><><<<<>><<<<>><>>><>><<<>>>><<<>>>><<<<>><<>>><<<><<<>><<<>><<<>><<>>><<<<>><<<>>>><<>>>><<<>><>>><>>>><<<<>>>><<<>><>>><<>><><<<>>>><>><<<<>>>><<<<><>>>><<<<><<><<<<>>>><<>><<<>>>><<<><<>>><<<<><<<<>><<>>><<<<>>><<><<<<>>><<><<>>><<>><<<<><>>><<<<>>><<>><<<<>>><<<><>>>><><<><><<<>><>>><>><>>><<<>>>><>><<<<>><<<>><<<<>>><<<>>><<<>>>><><<><<<>><<<<>><<><<<<>><<<<>>>><<<<>><<<>>><<<<>>>><<>>>><<<><<<>>>><<>>><<>>>><<<<>>><<>>>><>>>><<<<>>>><<<>>><<<>>><<<><>>>><>>>><<<<>>><<<>>>><>>>><<>>><<>>><><<<<>><<>><<>><<<<>>><<<<>>>><<<>>>><<<>><>><<<<><>><>>>><<<<>>>><<<>>>><<<>>>><<>>>><>>>><<<<>>><>>>><<<<>><<><<<>><<<<>><<<>><<<<><<<>>>><<>><>><>><<<>>>><>><<<><<><<<<>>><<<<><>>>><<><>><<<>><>><<<>>>><<<><<<<>>>><<<<><>>>><<<<>><<<<>><<<<><>>>><>>><<<<>>>><<<><<<>>><<<>><<>><<<<>>>><<<>><<<<>>><<>>>><<>><<>>>><<><<><<<<>>>><<<>>><<<><>>>><<>>>><><<<>><>><<><<>>>><><>>>><<<>>>><<<<>><<>><<<>>>><>>><<>>><>>><><<><<<<>><>><<<>>><<<>><><<<<>><<<>>><><<<<><>>><<<><><<<<>>><<>>><>>><>>>><<<>><<<<>>>><>>><<>>>><<>>><<<>>>><>>><<<>>>><<<<>>><<<<>>><<><<><<>>><<<<>>>><<<><>><>>>><<>>>><<<>>>><>>><<<><<><>>>><<>>><<<>>>><<>>>><<<><<<<>>>><>><<<>>><<<><<<>>><><<<<>>>><>><>>>><<<<><<<<>>>><<>>>><><<<>><>>><<<<>><<<<>>><<<<>>>><<<>><<<<>>>><<><>><<<>>><><<<<>>>><<<<><<<>><>><<>>><<<><<<<>><<>>>><<<>>>><<>>>><<<<>><<>><>>><<<<>>><<<>>>><<<<>>>><<>><<><<>><<<<>>><<<<>>><<<<>>>><><<<>>><<<<>>><<<<><><<<<><>><<<<>>><<<>>><<<<>>>><<<<>>><>>><<>>><<<<>><<<>><>><<>>>><>>>><>><<<>>>><<<<>>>><<<>>>><<<><<<><<<>><>>><<<<>>>><<<>>>><<<<>>><<<<>><<>><<<<><<<><>><>>><><<<><<<>>>><<<>>><<<<>>>><<<<><<>>>><<<<><<<>>><<>><<<<>><>>><<>>>><<<><<>>><>>><<>>><<<>>>><>><><<<<>>><><<<<>>><<<>>>><<><><<><<>>><>><<<<>>><<<>>>><<<><<<>><<<<>>><><>><<>>>><<<><<<<><>>><>><<<<>>>><<>>><<<<>>>><<<<>>><<>>><<<<><<>>>><<<>>>><<>>><>>><<>>><<<><<<>><<<<>>>><<<<>>><<>><>>>><<<<>>>><<<><>>>><<<<><<<<>><<>>><<<<>>>><><<>><<<<><>>>><<<<>><>>><><>>><<>>>><<<><><<<<>><<<><<<<>>>><><>>><<>>><<<>>><<<<>>><<<<>><<>>>><<<>>><>>><<<<>>>><<><>>><<<><<<>>>><<<>>>><<<><>>>><<<<>>><>>>><<<>>><<<><<<<>>><<<<><<<<>>><<>>>><<<>>><<<<><<><<<<>>>><<<>><<<<>><>>><<<<><<>>>><<>><>>>><<<<><<<>><<>>>><<>>>><<<<>><<<<>>>><<>>>><<<>>>><<>>><><<<>>><<><<>>>><<<>>>><<>>>><>><<<<>>>><<<<>>>><<><<><<<<><<>>><<>>><<<<>>>><<<>><<<<><<<<>>><<<<>>><<<>>><<<<><<>>>><<<<>>>><<<>><<<>><>>>><<<><><<<<><><<<>>><<<<>>>><<<><<<<>>>><<<>>>><>><<<<>>>><<>>>><<<>>>><<<<><<<>>>><>>>><><<<><<<>><>>>><<<>><<<<><<<<>><<>>><>>>><<>><>><>><<<>>><<<>>><<<>>><<>>><<>><<<>>>><<<<>>><<<>><>>>><<<<><<><>>>><<>>><<><<<<>><<<<>>>><<>><<<><<>>><<<<>><<<>><<><<<<>>>><<<>>>><<<<>>><>><<<<>><<<><>><<>>><<<<><<<<>>>><<<>><<<>>>><<<<>>>><<<>>><<>><>>><>>><<<>>><><<<<>>><>>><>>>><>>><<<<>>>><<<><<><><<<>>>><<<><<<>><<<<>>><<<><<><<<<>>>><<><<<<>>><>>>><>>>><>><<<<>>>><<<<>>><>>><<<>><>>>><<<<>><<<<>>>><>>><>>><<<<>><<<>>>><<<><<<<><>>><<<<>>><<<>>>><><<<><>><<<<>><<<><<<<>>>><>><><<<<><<<<>>>><<<>>>><<>><<<<><<>>><<<<><<<><<<<>><<<><<>>>><<<<>><>>>><<<>>><<>><<<>><><<<<>>>><<<>><<>><>>>><<<>>><<>>><<<>>><<>>><<<><<<<>>><>><<<>>>><<<<>>>><<<>><<<<>>>><>><<<><><<<<>><<<>>>><>>>><<<<>>>><<>>><<>>><><>>><<<><>><<>>>><>>><<<>>>><><>><>>>><<>>><>><<<<>><<>>><<>>>><><<><<<>><<>>>><<<>>><<><<<>>>><<<><><<>><<<>><<<><<<>>>><<<>>><>><<<>>><>>><>>><<>>><<<<><<<<>><<<>>><<<><>>><<<<>><>><<<>>><<>><>><<><>>><<<<>><>>><<<<><<<><<<><<<>>><<>>>><<<<>><<>><<>>><<>><<>><<<<>>><<><<<><>>><>><<><<>>>><<>>><<<<>>><<<>>>><>>><>>><<>>><><<<><<><<>>><>>>><>>>><<<<>>><>><<<>>>><>><<<>><<>>><>><<><<<><<<>>><<>>><<<<>>><><<<<>>><<<>><>>>><<<>>>><<<<><<<<>>>><<>><><<>>><<<><<>>><<>>>><<>><<<><<<><<<>>><<>><<<>>>><><<<<>>>><<>>><<>><<>>><<>>><<>>>><<<><<<<>><<>>>><<<>>><><<><<><<>>><<<<><<<><<><<>>>><<>>><><<<<>><<>><><<><>>><>>><<>>><<<<>>><<<<><>><<>>>><<<<>>>><>><<<<>><<><<<>>>><>><<<<>>>><<<><<<>><><<<<>>>><><<<<>><<<><<>>>><<><<<>><<<>><<<>><<<>>><<><<<>>>><>><<>>>><<>>><>>>><>>><><>><<<>>><<<><><<>><<<>>><<<<>>><<<>>>><><>>><<><>><<<>><<>><<>>><<<<>>><<<><<<<><>><<<>>><<<>>><<>>>><<<<>>><<>>><<<><<>>><<<>><<<>>><>>>><<<<>>>><<<<>><<<<>>><<>><<<<>><<<>>><<<>><><<<>>>><<>>>><<<<>>>><<>><>>>><<<<>>><>>>><>><<<<>>><>>><<>>>><<<<><<<><<<>><<>>><<><>>><<<<>>><>>>><<>>><<<<>>><>><<<>><<><<<><<<<>>><><<<<>>><<<<>>><<><<<<>><<>>>><>>>><<><><<<>>><>><>><>>>><><<<<>>><<<<>>>><<>><<>
diff --git a/day17/pieces b/day17/pieces
@@ -0,0 +1,17 @@
+####
+
+.#.
+###
+.#.
+
+..#
+..#
+###
+
+#
+#
+#
+#
+
+##
+##
diff --git a/day17/uppga.c b/day17/uppga.c
@@ -0,0 +1,224 @@
+#include "common.h"
+
+#define DEFAULT_BOARD_SIZE 10000000
+
+typedef struct {
+ size_t nalloc;
+ long cmax;
+ uint8_t* bd;
+} board;
+
+typedef struct {
+ size_t height;
+ uint8_t bd[4];
+} piece;
+
+static inline int isset(uint8_t row, size_t i)
+{
+ assert(i < 7);
+ if((row & (0x40 >> i)) != 0) return 1;
+ return 0;
+}
+
+static inline void set(uint8_t* row, size_t i)
+{
+ assert(i < 7);
+ *row |= (0x40 >> i);
+}
+
+void init_board(board* b)
+{
+ b->nalloc = DEFAULT_BOARD_SIZE;
+ b->cmax = -1;
+ b->bd = calloc(b->nalloc, sizeof(*b->bd));
+}
+
+static inline void print_line(uint8_t v)
+{
+ size_t j;
+ for(j = 0; j < 7; j++) {
+ if(isset(v, j)) {
+ printf("#");
+ } else {
+ printf(".");
+ }
+ }
+}
+
+void print_piece(piece p)
+{
+ printf("piece> h = %zu\n", p.height);
+ size_t i;
+ for(i = 0; i < p.height; i++) {
+ print_line(p.bd[i]);
+ printf("\n");
+ }
+}
+
+void print_board(board* b)
+{
+ int i;
+ printf("+-------+\n");
+ for(i = 0; i < b->cmax+2; i++) {
+ printf("|");
+ print_line(b->bd[i]);
+ printf("|\n");
+ }
+}
+
+void print_board_with_piece(board* b, piece* p, long height)
+{
+ size_t i;
+ printf("+-------+\n");
+ for(i = 0; i < height+4; i++) {
+ uint8_t d = 0;
+ if(i < b->nalloc) {
+ d |= b->bd[i];
+ }
+ if(i >= height && (i-height) < p->height){
+ d |= p->bd[i-height];
+ }
+ printf("|");
+ print_line(d);
+ printf("|\n");
+ }
+}
+
+#define SWAP(x,y) (x^=y^=x^=y)
+
+void read_pieces(piece* pcs, size_t npcs, char* filename)
+{
+ char** lines;
+ size_t nlines = readlines(&lines, filename);
+ size_t cp = 0;
+ size_t cpi = 0;
+ size_t i, j;
+
+ for(i = 0; i < npcs; i++)
+ memset(pcs[i].bd, 0, 4);
+
+ for(i = 0; i < nlines; i++) {
+ if(strlen(lines[i]) < 2) {
+ pcs[cp].height = cpi;
+ cp++;
+ cpi = 0;
+ continue;
+ }
+ for(j = 0; j < strlen(lines[i]); j++) {
+ if(lines[i][j] == '#') {
+ set(&(pcs[cp].bd[cpi]), j);
+ }
+ }
+ cpi++;
+ }
+ pcs[cp].height = cpi;
+
+ for(i = 0; i < npcs; i++) {
+ for(j = 0; j < pcs[i].height/2; j++) {
+ SWAP(pcs[i].bd[j], pcs[i].bd[pcs[i].height-1-j]);
+ }
+ for(j = 0; j < pcs[i].height; j++) pcs[i].bd[j] >>= 2;
+ }
+}
+
+static inline void r_push_piece(piece* p, board* b, long h)
+{
+ size_t i;
+ for(i = 0; i < p->height; i++) {
+ if((p->bd[i] & 0x01) != 0) return; // cannot push
+ if(((p->bd[i] >> 1) & b->bd[h + i]) != 0) return;
+ }
+
+ // pushable
+ for(i = 0; i < p->height; i++)
+ p->bd[i] >>= 1;
+}
+
+static inline void l_push_piece(piece* p, board* b, long h)
+{
+ size_t i;
+ for(i = 0; i < p->height; i++) {
+ if((p->bd[i] & 0x40) != 0) return; // cannot
+ if(((p->bd[i] << 1) & b->bd[h + i]) != 0) return;
+ }
+
+ // pushable
+ for(i = 0; i < p->height; i++)
+ p->bd[i] <<= 1;
+}
+
+static inline int can_move_up(piece* p, board* b, long cheight)
+{
+ size_t i;
+ if(cheight <= 0) return 0;
+ for(i = 0; i < p->height; i++) {
+ if((b->bd[i + cheight - 1] & p->bd[i]) != 0) return 0;
+ }
+ return 1;
+}
+
+static inline void draw_piece(piece* p, board* b, long height)
+{
+ size_t i;
+ for(i = 0; i < p->height; i++) {
+ b->bd[i + height] |= p->bd[i];
+ }
+// printf("> drawing piece of h %zu at h %ld\n", p->height, height);
+ long nmax = height + p->height - 1;
+ b->cmax = nmax > b->cmax ? nmax : b->cmax;
+}
+
+static inline void try_lr_move(piece* p, board* b, long h, char* moves, size_t nmoves, size_t* i)
+{
+ if(moves[*i % nmoves] == '>') {
+ r_push_piece(p, b, h);
+ } else {
+ l_push_piece(p, b, h);
+ }
+ (*i)++;
+}
+
+void drop_piece(board* b, piece p, char* moves, size_t nmoves, size_t* i)
+{
+ long cheight = b->cmax + 4;
+ try_lr_move(&p, b, cheight, moves, nmoves, i);
+ while(can_move_up(&p, b, cheight)) {
+ cheight--;
+ try_lr_move(&p, b, cheight, moves, nmoves, i);
+ }
+
+ draw_piece(&p, b, cheight);
+}
+
+int main(int argc, char** argv)
+{
+ char** lines;
+ size_t nlines = readlines(&lines, "einput");
+ printf("#lines: %lu\n", nlines);
+
+ assert(nlines == 1);
+
+ char* moves = lines[0];
+ size_t nmoves = strlen(moves);
+ if(moves[nmoves-1] == '\n') nmoves--;
+
+ printf("#moves: %zu\n", nmoves);
+
+ board b;
+ init_board(&b);
+
+ piece pcs[5];
+ read_pieces(pcs, 5, "pieces");
+
+ size_t i;
+ for(i = 0; i < 5; i++) {
+ print_piece(pcs[i]);
+ }
+
+ i = 0;
+ size_t j;
+ for(j = 0; j < 2022; j++) {
+ drop_piece(&b, pcs[j % 5], moves, nmoves, &i);
+ }
+ printf("(%zu): %lu\n", j, b.cmax+1);
+}
diff --git a/day17/uppgb.c b/day17/uppgb.c
@@ -0,0 +1,389 @@
+#include "common.h"
+
+#define DEFAULT_BOARD_SIZE 100000000
+#define TOP_SIZE 16 // experimentally enough
+#define MAX_NTOPS 20000
+#define MAXJ 1000000000000L
+
+#define NO_TOP SIZE_MAX
+
+typedef struct {
+ size_t nalloc;
+ long cmax;
+ uint8_t* bd;
+} board;
+
+typedef struct {
+ size_t height;
+ uint8_t bd[4];
+} piece;
+
+typedef struct {
+ uint8_t bd[TOP_SIZE];
+ char moves[5*TOP_SIZE];
+ size_t midiff;
+ long cmax;
+} top;
+
+static top tops[MAX_NTOPS];
+static size_t next[MAX_NTOPS] = {0};
+static size_t lastnext = SIZE_MAX;
+static size_t ntops = 0;
+static size_t cycle_length = 0;
+static long cycle_height = 0;
+
+static inline int cmp_top(top a, top b)
+{
+ size_t i,j;
+ for(i = 0; i < TOP_SIZE; i++) {
+ if(a.bd[i] != b.bd[i]) return 1;
+ for(j = 0; j < 5; j++) {
+ if(a.moves[5*i+j] != b.moves[5*i+j]) return 1;
+ }
+ }
+ return 0;
+}
+
+static inline top get_top(board* b, char* moves, size_t nmoves, size_t mi, size_t midiff)
+{
+ top r;
+ size_t i;
+ size_t si = b->cmax >= TOP_SIZE ? b->cmax - TOP_SIZE : 0;
+ for(i = 0; i < TOP_SIZE; i++) {
+ r.bd[i] = b->bd[si + i];
+ r.moves[i] = moves[(mi + i) % nmoves];
+ }
+ for(i = 0; i < 5*TOP_SIZE; i++) {
+ r.moves[i] = moves[(mi + i) % nmoves];
+ }
+ r.midiff = midiff;
+ return r;
+}
+
+static inline int isset(uint8_t row, size_t i)
+{
+ assert(i < 7);
+ if((row & (0x40 >> i)) != 0) return 1;
+ return 0;
+}
+
+static inline void set(uint8_t* row, size_t i)
+{
+ assert(i < 7);
+ *row |= (0x40 >> i);
+}
+
+void init_board(board* b)
+{
+ b->nalloc = DEFAULT_BOARD_SIZE;
+ b->cmax = -1;
+ b->bd = calloc(b->nalloc, sizeof(*b->bd));
+}
+
+static inline void print_line(uint8_t v)
+{
+ size_t j;
+ for(j = 0; j < 7; j++) {
+ if(isset(v, j)) {
+ printf("#");
+ } else {
+ printf(".");
+ }
+ }
+}
+
+void print_piece(piece p)
+{
+ printf("piece> h = %zu\n", p.height);
+ size_t i;
+ for(i = 0; i < p.height; i++) {
+ print_line(p.bd[i]);
+ printf("\n");
+ }
+}
+
+void print_board(board* b)
+{
+ int i;
+ printf("+-------+\n");
+ for(i = 0; i < b->cmax+2; i++) {
+ printf("|");
+ print_line(b->bd[i]);
+ printf("|\n");
+ }
+}
+
+void print_top(top t)
+{
+ int i;
+ printf("+-------+ (%c..%c)\n", t.moves[0], t.moves[TOP_SIZE-1]);
+ for(i = 0; i < TOP_SIZE; i++) {
+ printf("|");
+ print_line(t.bd[i]);
+ printf("|\n");
+ }
+}
+
+void print_board_with_piece(board* b, piece* p, long height)
+{
+ size_t i;
+ printf("+-------+\n");
+ for(i = 0; i < height+4; i++) {
+ uint8_t d = 0;
+ if(i < b->nalloc) {
+ d |= b->bd[i];
+ }
+ if(i >= height && (i-height) < p->height){
+ d |= p->bd[i-height];
+ }
+ printf("|");
+ print_line(d);
+ printf("|\n");
+ }
+}
+
+#define SWAP(x,y) (x^=y^=x^=y)
+
+void read_pieces(piece* pcs, size_t npcs, char* filename)
+{
+ char** lines;
+ size_t nlines = readlines(&lines, filename);
+ size_t cp = 0;
+ size_t cpi = 0;
+ size_t i, j;
+
+ for(i = 0; i < npcs; i++)
+ memset(pcs[i].bd, 0, 4);
+
+ for(i = 0; i < nlines; i++) {
+ if(strlen(lines[i]) < 2) {
+ pcs[cp].height = cpi;
+ cp++;
+ cpi = 0;
+ continue;
+ }
+ for(j = 0; j < strlen(lines[i]); j++) {
+ if(lines[i][j] == '#') {
+ set(&(pcs[cp].bd[cpi]), j);
+ }
+ }
+ cpi++;
+ }
+ pcs[cp].height = cpi;
+
+ for(i = 0; i < npcs; i++) {
+ for(j = 0; j < pcs[i].height/2; j++) {
+ SWAP(pcs[i].bd[j], pcs[i].bd[pcs[i].height-1-j]);
+ }
+ for(j = 0; j < pcs[i].height; j++) pcs[i].bd[j] >>= 2;
+ }
+}
+
+static inline void r_push_piece(piece* p, board* b, long h)
+{
+ size_t i;
+ for(i = 0; i < p->height; i++) {
+ if((p->bd[i] & 0x01) != 0) return; // cannot push
+ if(((p->bd[i] >> 1) & b->bd[h + i]) != 0) return;
+ }
+
+ // pushable
+ for(i = 0; i < p->height; i++)
+ p->bd[i] >>= 1;
+}
+
+static inline void l_push_piece(piece* p, board* b, long h)
+{
+ size_t i;
+ for(i = 0; i < p->height; i++) {
+ if((p->bd[i] & 0x40) != 0) return; // cannot
+ if(((p->bd[i] << 1) & b->bd[h + i]) != 0) return;
+ }
+
+ // pushable
+ for(i = 0; i < p->height; i++)
+ p->bd[i] <<= 1;
+}
+
+static inline int can_move_up(piece* p, board* b, long cheight)
+{
+ size_t i;
+ if(cheight <= 0) return 0;
+ for(i = 0; i < p->height; i++) {
+ if((b->bd[i + cheight - 1] & p->bd[i]) != 0) return 0;
+ }
+ return 1;
+}
+
+static inline void draw_piece(piece* p, board* b, long height)
+{
+ size_t i;
+ for(i = 0; i < p->height; i++) {
+ b->bd[i + height] |= p->bd[i];
+ }
+ long nmax = height + p->height - 1;
+ b->cmax = nmax > b->cmax ? nmax : b->cmax;
+}
+
+static inline void try_lr_move(piece* p, board* b, long h, char* moves, size_t nmoves, size_t* i)
+{
+ if(moves[*i % nmoves] == '>') {
+ r_push_piece(p, b, h);
+ } else {
+ l_push_piece(p, b, h);
+ }
+ (*i)++;
+}
+
+static inline size_t add_top(board* b, char* moves, size_t nmoves, size_t *i, size_t midiff, top t)
+{
+ size_t j;
+ t.midiff = midiff;
+
+ int seen = 0;
+ for(j = 0; j < ntops; j++) {
+ if(cmp_top(t, tops[j]) == 0) {
+ seen = 1;
+ break;
+ }
+ }
+ if(seen) {
+ printf(">> seen top (ntops = %zu)\n", ntops);
+ return j;
+ } else {
+ printf(">> new top (ntops = %zu)\n", ntops);
+ assert(ntops < MAX_NTOPS);
+ tops[ntops] = t;
+ ntops++;
+ }
+
+ return ntops-1;
+}
+
+void drop_piece(board* b, piece p, char* moves, size_t nmoves, size_t* i)
+{
+ long cheight = b->cmax + 4;
+ try_lr_move(&p, b, cheight, moves, nmoves, i);
+ while(can_move_up(&p, b, cheight)) {
+ cheight--;
+ try_lr_move(&p, b, cheight, moves, nmoves, i);
+ }
+
+ draw_piece(&p, b, cheight);
+}
+
+static inline size_t find_top(top* t, board* b, char* moves, size_t nmoves, size_t* mi)
+{
+ *t = get_top(b, moves, nmoves, *mi, 0);
+
+ print_top(*t);
+
+ printf("next> ");
+ size_t j;
+ for(j = 0; j < ntops; j++) printf("%zu ", next[j]);
+ printf("\n");
+
+ int seen = 0;
+ for(j = 0; j < ntops; j++) {
+ if(cmp_top(*t, tops[j]) == 0) {
+ seen = 1;
+ break;
+ }
+ }
+ if(seen) {
+ printf(">> seen top (ntops = %zu)\n", ntops);
+ return j;
+ }
+
+ return NO_TOP;
+}
+
+void drop_round(board* b, piece* pcs, char* moves, size_t nmoves, size_t* mi)
+{
+ top t;
+ if(cycle_length == 0) {
+ size_t ti = find_top(&t, b, moves, nmoves, mi);
+ if(ti != NO_TOP) {
+ printf("ti = %zu\n", ti);
+ cycle_length = ntops - ti;
+ cycle_height = b->cmax - tops[ti].cmax;
+ printf("cycle length = %ld\n", cycle_length);
+ printf("cycle height = %ld\n", cycle_height);
+ }
+ }
+
+ size_t last_mi = *mi;
+ size_t i;
+ for(i = 0; i < 5; i++) {
+ drop_piece(b, pcs[i % 5], moves, nmoves, mi);
+ }
+
+ if(cycle_length == 0) {
+ assert(*mi >= last_mi);
+ t.cmax = b->cmax;
+ size_t new_top_idx = add_top(b, moves, nmoves, &i, *mi-last_mi, t);
+ if(lastnext != SIZE_MAX) {
+ next[lastnext] = new_top_idx;
+ lastnext = new_top_idx;
+ } else {
+ lastnext = new_top_idx;
+ }
+ }
+}
+
+int main(int argc, char** argv)
+{
+ char** lines;
+ size_t nlines = readlines(&lines, "input");
+ printf("#lines: %lu\n", nlines);
+
+ assert(nlines == 1);
+
+ char* moves = lines[0];
+ size_t nmoves = strlen(moves);
+ if(moves[nmoves-1] == '\n') nmoves--;
+
+ printf("#moves: %zu\n", nmoves);
+
+ board b;
+ init_board(&b);
+
+ piece pcs[5];
+ read_pieces(pcs, 5, "pieces");
+
+ size_t i;
+ for(i = 0; i < 5; i++) {
+ print_piece(pcs[i]);
+ }
+
+ size_t j;
+ size_t mi = 0;
+ i = 0;
+ top t;
+ size_t is[MAX_NTOPS];
+ long skipval = 0;
+ for(j = MAXJ; j > 0; j--) {
+ drop_piece(&b, pcs[i % 5], moves, nmoves, &mi);
+
+ if(skipval == 0 && i % 5 == 0) {
+ size_t ti = find_top(&t, &b, moves, nmoves, &mi);
+ if(ti == NO_TOP) {
+ is[ntops] = i;
+ add_top(&b, moves, nmoves, &mi, 0, t);
+ } else {
+ printf("ti = %zu\n", ti);
+ long diff = b.cmax - tops[ti].cmax;
+ printf("diff = %ld\n", diff);
+ long idiff = i - is[ti];
+ printf("idiff = %ld\n", idiff);
+ size_t jold = j;
+ j = j % (i - is[ti]);
+ printf("skipping %ld js\n", (jold - j)/idiff);
+ skipval = ((jold - j)/idiff)*diff;
+ }
+ }
+ i++;
+ }
+
+ printf("%lu\n", skipval + b.cmax + 1);
+}
diff --git a/day17/uppgc.c b/day17/uppgc.c
@@ -0,0 +1,240 @@
+#include "common.h"
+#include <strings.h>
+
+#define DEFAULT_BOARD_SIZE 250000000
+#define MAXJ 1000000000000L
+//#define MAXJ 2022L
+
+typedef struct {
+ size_t nalloc;
+ long cmax;
+ uint8_t* bd;
+} board;
+
+typedef struct {
+ size_t height;
+ uint8_t bd[4];
+} piece;
+
+static inline int isset(uint8_t row, size_t i)
+{
+ assert(i < 7);
+ if((row & (0x40 >> i)) != 0) return 1;
+ return 0;
+}
+
+static inline void set(uint8_t* row, size_t i)
+{
+ assert(i < 7);
+ *row |= (0x40 >> i);
+}
+
+void init_board(board* b)
+{
+ b->nalloc = DEFAULT_BOARD_SIZE;
+ b->cmax = -1;
+ b->bd = calloc(b->nalloc, sizeof(*b->bd));
+}
+
+static inline void print_line(uint8_t v)
+{
+ size_t j;
+ for(j = 0; j < 7; j++) {
+ if(isset(v, j)) {
+ printf("#");
+ } else {
+ printf(".");
+ }
+ }
+}
+
+void print_piece(piece p)
+{
+ printf("piece> h = %zu\n", p.height);
+ size_t i;
+ for(i = 0; i < p.height; i++) {
+ print_line(p.bd[i]);
+ printf("\n");
+ }
+}
+
+void print_board(board* b)
+{
+ int i;
+ printf("+-------+\n");
+ for(i = 0; i < b->cmax+2; i++) {
+ printf("|");
+ print_line(b->bd[i]);
+ printf("|\n");
+ }
+}
+
+void print_board_with_piece(board* b, piece* p, long height)
+{
+ size_t i;
+ printf("+-------+\n");
+ for(i = 0; i < height+4; i++) {
+ uint8_t d = 0;
+ if(i < b->nalloc) {
+ d |= b->bd[i];
+ }
+ if(i >= height && (i-height) < p->height){
+ d |= p->bd[i-height];
+ }
+ printf("|");
+ print_line(d);
+ printf("|\n");
+ }
+}
+
+#define SWAP(x,y) (x^=y^=x^=y)
+
+void read_pieces(piece* pcs, size_t npcs, char* filename)
+{
+ char** lines;
+ size_t nlines = readlines(&lines, filename);
+ size_t cp = 0;
+ size_t cpi = 0;
+ size_t i, j;
+
+ for(i = 0; i < npcs; i++)
+ memset(pcs[i].bd, 0, 4);
+
+ for(i = 0; i < nlines; i++) {
+ if(strlen(lines[i]) < 2) {
+ pcs[cp].height = cpi;
+ cp++;
+ cpi = 0;
+ continue;
+ }
+ for(j = 0; j < strlen(lines[i]); j++) {
+ if(lines[i][j] == '#') {
+ set(&(pcs[cp].bd[cpi]), j);
+ }
+ }
+ cpi++;
+ }
+ pcs[cp].height = cpi;
+
+ for(i = 0; i < npcs; i++) {
+ for(j = 0; j < pcs[i].height/2; j++) {
+ SWAP(pcs[i].bd[j], pcs[i].bd[pcs[i].height-1-j]);
+ }
+ for(j = 0; j < pcs[i].height; j++) pcs[i].bd[j] >>= 2;
+ }
+}
+
+static inline void r_push_piece(piece* p, board* b, long h)
+{
+ size_t i;
+ for(i = 0; i < p->height; i++) {
+ if((p->bd[i] & 0x01) != 0) return; // cannot push
+ if(((p->bd[i] >> 1) & b->bd[h + i]) != 0) return;
+ }
+
+ // pushable
+ for(i = 0; i < p->height; i++)
+ p->bd[i] >>= 1;
+}
+
+static inline void l_push_piece(piece* p, board* b, long h)
+{
+ size_t i;
+ for(i = 0; i < p->height; i++) {
+ if((p->bd[i] & 0x40) != 0) return; // cannot
+ if(((p->bd[i] << 1) & b->bd[h + i]) != 0) return;
+ }
+
+ // pushable
+ for(i = 0; i < p->height; i++)
+ p->bd[i] <<= 1;
+}
+
+static inline int can_move_up(piece* p, board* b, long cheight)
+{
+ size_t i;
+ if(cheight <= 0) return 0;
+ for(i = 0; i < p->height; i++) {
+ if((b->bd[i + cheight - 1] & p->bd[i]) != 0) return 0;
+ }
+ return 1;
+}
+
+static inline void draw_piece(piece* p, board* b, long height)
+{
+ size_t i;
+ for(i = 0; i < p->height; i++) {
+ b->bd[i + height] |= p->bd[i];
+ }
+// printf("> drawing piece of h %zu at h %ld\n", p->height, height);
+ long nmax = height + p->height - 1;
+ b->cmax = nmax > b->cmax ? nmax : b->cmax;
+}
+
+static inline void try_lr_move(piece* p, board* b, long h, char* moves, size_t nmoves, size_t* i)
+{
+ if(moves[*i % nmoves] == '>') {
+ r_push_piece(p, b, h);
+ } else {
+ l_push_piece(p, b, h);
+ }
+ (*i)++;
+}
+
+static inline void drop_piece(board* b, piece p, char* moves, size_t nmoves, size_t* i)
+{
+ long cheight = b->cmax + 4;
+ try_lr_move(&p, b, cheight, moves, nmoves, i);
+ while(can_move_up(&p, b, cheight)) {
+ cheight--;
+ try_lr_move(&p, b, cheight, moves, nmoves, i);
+ }
+
+ draw_piece(&p, b, cheight);
+}
+
+static inline long chomp_board(board* b) {
+ long chomping = DEFAULT_BOARD_SIZE/2;
+ b->cmax -= chomping;
+ memcpy(b->bd, &(b->bd[chomping]), chomping);
+ bzero(&(b->bd[chomping]), chomping);
+ return chomping;
+}
+
+int main(int argc, char** argv)
+{
+ char** lines;
+ size_t nlines = readlines(&lines, "input");
+ printf("#lines: %lu\n", nlines);
+
+ assert(nlines == 1);
+
+ char* moves = lines[0];
+ size_t nmoves = strlen(moves);
+ if(moves[nmoves-1] == '\n') nmoves--;
+
+ printf("#moves: %zu\n", nmoves);
+
+ board b;
+ init_board(&b);
+
+ piece pcs[5];
+ read_pieces(pcs, 5, "pieces");
+
+ size_t i;
+ for(i = 0; i < 5; i++) {
+ print_piece(pcs[i]);
+ }
+
+ i = 0;
+ size_t j;
+ long chompd = 0;
+ for(j = 0; j < MAXJ; j++) {
+ drop_piece(&b, pcs[j % 5], moves, nmoves, &i);
+ if(b.cmax + 5 > DEFAULT_BOARD_SIZE)
+ chompd += chomp_board(&b);
+ if((j % (MAXJ/1000)) == 0) printf("%lu\n", j / (MAXJ/1000));
+ }
+ printf("(%zu): %lu\n", j, chompd+b.cmax+1);
+ printf("chompd %lu\n", chompd);
+}
diff --git a/day18/Makefile b/day18/Makefile
@@ -0,0 +1,20 @@
+CC=clang
+UTILS=../utils/reading.o
+INCLUDES=-I../utils
+
+all: utils common.o uppga uppgb
+
+common.o: common.c common.h
+ $(CC) $(CFLAGS) -c common.c $(INCLUDES)
+
+uppga: $(UTILS) common.o uppga.c
+ $(CC) -Wall -o uppga uppga.c common.o $(UTILS) $(INCLUDES)
+
+uppgb: $(UTILS) common.o uppgb.c
+ $(CC) -Wall -o uppgb uppgb.c common.o $(UTILS) $(INCLUDES)
+
+utils:
+ make -C ../utils
+
+clean:
+ rm -rf common.o uppga uppgb
diff --git a/day18/common.c b/day18/common.c
@@ -0,0 +1,6 @@
+#include "common.h"
+
+size_t fn(char** lines, size_t nlines)
+{
+ return 0;
+}
diff --git a/day18/common.h b/day18/common.h
@@ -0,0 +1,11 @@
+#ifndef COMMON_H_
+#define COMMON_H_
+
+#include <stdio.h>
+#include <stdint.h>
+#include <assert.h>
+#include <reading.h>
+
+size_t fn(char** lines, size_t nlines);
+
+#endif
diff --git a/day18/einput b/day18/einput
@@ -0,0 +1,13 @@
+2,2,2
+1,2,2
+3,2,2
+2,1,2
+2,3,2
+2,2,1
+2,2,3
+2,2,4
+2,2,6
+1,2,5
+3,2,5
+2,1,5
+2,3,5
diff --git a/day18/input b/day18/input
@@ -0,0 +1,2742 @@
+13,6,3
+13,5,16
+11,2,10
+7,6,15
+8,11,3
+5,6,15
+6,11,3
+5,14,15
+11,18,8
+9,16,7
+2,10,11
+8,3,11
+5,7,6
+18,14,15
+10,5,5
+17,6,14
+6,4,7
+9,2,14
+3,11,16
+7,18,14
+14,12,4
+7,14,3
+12,16,4
+16,5,7
+14,7,3
+9,3,14
+14,14,16
+4,17,12
+17,16,14
+8,10,20
+16,10,17
+10,5,4
+11,5,4
+13,16,4
+12,2,12
+3,8,14
+8,5,14
+17,14,7
+16,7,3
+7,7,3
+15,15,7
+6,3,9
+5,6,5
+8,3,13
+16,14,4
+19,9,11
+5,8,5
+13,15,17
+15,7,16
+18,9,9
+4,6,8
+11,4,8
+9,19,12
+17,8,4
+13,4,16
+13,20,12
+9,17,12
+17,12,8
+14,11,2
+12,4,16
+3,7,8
+12,9,3
+14,16,4
+14,3,14
+4,16,9
+7,2,10
+12,5,5
+19,9,8
+17,11,3
+14,17,17
+13,12,19
+14,17,5
+11,13,20
+6,18,10
+12,1,10
+6,5,7
+2,8,8
+13,4,14
+5,3,13
+14,16,5
+12,17,7
+6,14,4
+5,10,17
+9,8,2
+13,4,5
+13,7,18
+5,19,8
+18,11,14
+1,10,9
+16,16,7
+5,5,8
+3,5,10
+6,3,8
+5,16,7
+6,9,4
+10,16,3
+18,7,13
+5,4,10
+9,14,18
+18,13,12
+19,11,15
+14,17,8
+15,6,13
+16,15,6
+3,15,10
+17,14,9
+14,15,16
+10,14,1
+10,2,15
+9,18,13
+2,10,9
+5,17,8
+14,9,3
+3,14,15
+12,3,13
+4,16,13
+7,6,17
+4,4,8
+13,3,10
+4,4,12
+11,19,14
+9,10,4
+14,10,16
+6,18,13
+9,4,4
+20,9,11
+3,11,5
+5,13,15
+2,14,11
+5,12,17
+10,20,12
+10,2,6
+14,5,15
+14,11,19
+9,20,13
+10,2,11
+17,16,12
+17,7,16
+3,8,10
+3,15,12
+4,7,14
+3,13,12
+19,12,12
+10,20,9
+10,1,12
+12,2,9
+17,16,15
+14,20,11
+6,17,6
+5,16,11
+6,19,9
+11,15,2
+11,8,2
+3,11,10
+10,4,5
+10,15,16
+7,4,7
+3,5,13
+2,13,8
+18,6,7
+19,8,12
+15,15,5
+17,12,5
+6,15,16
+7,12,18
+13,17,15
+15,4,7
+12,18,11
+18,12,14
+6,16,7
+13,12,4
+1,11,10
+10,14,3
+8,6,18
+14,4,9
+18,10,5
+5,16,14
+13,3,14
+5,6,6
+10,7,4
+7,7,16
+19,12,13
+11,4,15
+10,14,16
+18,8,13
+10,8,18
+3,13,10
+4,7,16
+15,3,14
+12,14,19
+6,7,4
+11,3,4
+18,9,12
+3,5,12
+9,3,6
+19,13,13
+4,7,13
+7,19,10
+2,11,6
+5,5,10
+8,16,17
+5,4,14
+18,7,15
+5,7,13
+9,11,2
+3,16,13
+16,4,8
+15,17,6
+10,4,4
+6,4,11
+2,13,14
+13,6,17
+7,3,12
+13,19,12
+10,19,16
+16,11,4
+12,15,18
+17,11,5
+4,12,13
+3,16,9
+12,3,10
+8,1,12
+18,12,15
+6,2,14
+16,6,14
+17,15,9
+14,13,3
+13,1,9
+16,13,17
+15,18,13
+7,13,18
+4,13,16
+6,4,13
+9,4,13
+11,19,10
+7,4,4
+9,7,18
+18,16,11
+3,12,12
+12,2,14
+7,10,18
+17,16,11
+11,13,2
+11,3,5
+11,3,14
+3,10,15
+16,18,11
+4,15,7
+11,11,20
+4,14,17
+8,12,19
+4,15,10
+10,16,7
+10,6,17
+19,12,11
+16,5,10
+10,4,6
+17,5,10
+16,10,4
+8,11,19
+7,5,17
+14,18,14
+12,2,10
+9,4,6
+6,9,3
+7,15,11
+6,4,10
+15,8,2
+3,7,13
+4,4,7
+14,19,14
+11,8,20
+14,8,3
+16,16,12
+18,13,8
+5,17,10
+17,14,15
+15,8,18
+7,3,8
+8,7,3
+15,11,4
+8,4,14
+19,11,10
+6,11,5
+10,9,1
+4,14,15
+11,1,12
+13,16,8
+4,10,17
+11,14,18
+8,10,3
+6,14,16
+4,6,11
+5,16,10
+7,17,12
+12,17,16
+16,10,3
+12,2,8
+3,11,7
+2,12,11
+17,17,13
+17,9,14
+17,18,13
+7,17,16
+9,17,15
+5,18,9
+11,4,17
+5,8,16
+14,11,3
+14,6,17
+17,8,11
+12,9,2
+9,18,7
+10,3,13
+8,6,19
+12,16,5
+18,5,9
+1,11,8
+12,7,2
+9,19,8
+11,3,7
+6,8,15
+6,13,18
+14,13,16
+6,8,4
+16,3,14
+6,17,12
+17,12,17
+11,11,19
+12,14,2
+11,3,13
+15,17,7
+15,14,3
+13,17,17
+9,10,3
+13,7,19
+16,6,5
+6,1,11
+17,8,14
+2,14,6
+15,4,14
+12,5,15
+17,4,7
+18,10,7
+9,14,3
+13,18,7
+15,8,4
+6,5,5
+7,17,6
+7,8,18
+4,17,10
+16,7,12
+10,18,11
+8,6,17
+8,13,1
+12,18,8
+4,14,7
+17,7,7
+10,7,18
+3,12,13
+10,2,12
+16,13,4
+10,2,8
+15,10,4
+18,12,5
+15,19,10
+8,7,2
+17,11,6
+7,4,9
+14,3,16
+14,9,18
+11,6,18
+4,8,10
+15,3,11
+17,17,10
+19,10,13
+6,16,16
+16,13,3
+10,1,10
+15,15,4
+18,9,5
+3,15,9
+9,19,9
+14,14,4
+11,4,16
+4,11,14
+13,18,16
+12,18,13
+15,4,11
+20,12,11
+6,3,6
+8,18,15
+10,3,11
+12,14,3
+13,18,5
+10,15,4
+10,5,17
+11,12,20
+4,8,5
+6,2,12
+7,4,5
+16,6,17
+6,12,3
+10,4,14
+18,11,15
+19,13,12
+3,11,15
+17,6,9
+16,6,7
+14,8,17
+1,9,10
+1,10,10
+15,8,16
+4,9,16
+8,11,2
+14,19,11
+12,20,13
+5,11,16
+4,12,16
+9,3,5
+15,13,18
+10,18,15
+3,15,11
+10,3,5
+11,12,2
+10,13,19
+20,9,10
+16,8,16
+7,14,16
+3,13,15
+8,7,5
+2,15,9
+6,10,3
+20,11,11
+7,12,19
+8,15,17
+15,9,20
+5,14,4
+7,11,2
+11,10,2
+5,17,13
+14,3,8
+4,6,6
+13,10,19
+12,17,3
+9,10,19
+3,9,8
+6,16,8
+9,13,2
+8,19,15
+16,8,11
+10,9,18
+17,4,10
+17,8,13
+9,10,20
+5,4,12
+19,13,14
+8,5,8
+14,3,10
+9,19,10
+4,12,15
+12,2,13
+9,16,3
+15,2,12
+13,10,2
+9,2,9
+11,12,19
+14,10,3
+8,8,2
+12,7,16
+16,12,16
+8,14,19
+5,13,3
+17,5,8
+11,17,4
+19,11,6
+7,19,12
+15,5,17
+17,6,15
+12,5,16
+5,6,8
+5,5,6
+2,13,12
+8,19,10
+3,14,8
+15,16,7
+13,12,18
+10,9,2
+6,4,6
+3,8,11
+10,18,13
+17,4,8
+18,15,9
+5,9,16
+10,19,9
+3,9,6
+17,3,11
+6,10,4
+12,5,17
+5,6,9
+6,5,13
+19,11,11
+18,11,7
+16,4,14
+15,5,4
+14,4,7
+12,8,4
+6,3,7
+5,4,7
+16,11,17
+2,9,8
+13,20,11
+5,10,15
+15,5,15
+10,12,18
+7,5,6
+5,14,6
+8,7,15
+19,13,8
+18,12,11
+10,3,16
+13,8,18
+17,7,5
+8,14,17
+6,15,7
+7,10,19
+15,2,11
+11,11,2
+14,5,4
+14,15,15
+12,16,16
+7,5,16
+9,9,1
+14,13,17
+17,16,10
+10,17,5
+18,14,8
+3,8,6
+3,11,6
+9,16,17
+3,7,9
+6,4,8
+5,12,18
+6,16,17
+16,14,16
+20,11,7
+14,18,9
+15,13,17
+13,16,17
+4,3,7
+1,12,13
+5,17,15
+13,19,9
+12,3,14
+9,15,4
+18,12,13
+3,14,12
+13,9,2
+16,14,6
+10,4,11
+6,17,8
+5,11,17
+7,5,4
+2,9,9
+8,3,15
+2,11,11
+6,17,11
+7,3,13
+15,3,7
+6,14,5
+16,16,11
+12,9,19
+18,16,10
+11,14,4
+2,14,9
+4,6,9
+12,4,4
+18,5,15
+8,9,19
+3,10,17
+8,1,11
+8,16,15
+10,12,4
+15,14,17
+1,13,7
+8,12,3
+7,7,17
+9,7,3
+10,15,17
+17,12,15
+14,4,15
+12,14,17
+19,14,9
+17,10,5
+8,13,2
+15,8,3
+4,16,14
+17,14,12
+2,11,9
+15,6,7
+18,13,15
+5,10,3
+9,14,16
+18,15,15
+10,1,7
+13,2,12
+11,13,19
+11,5,3
+13,15,3
+6,14,6
+14,19,8
+18,17,13
+10,7,3
+12,4,14
+10,2,5
+4,7,6
+10,17,7
+13,5,3
+8,14,4
+8,3,5
+15,18,9
+4,14,5
+14,17,15
+4,14,4
+15,13,3
+12,10,19
+1,9,9
+18,5,8
+12,12,17
+8,6,3
+15,7,18
+18,12,16
+17,13,8
+4,12,6
+11,18,13
+18,10,8
+16,8,6
+6,5,15
+6,15,4
+8,19,11
+12,19,11
+12,12,3
+12,16,18
+15,6,18
+14,11,1
+10,6,20
+3,6,7
+9,5,18
+15,12,3
+5,9,8
+9,1,11
+6,7,5
+7,10,17
+13,6,16
+15,16,10
+4,12,5
+5,13,19
+12,4,6
+8,6,4
+7,16,3
+7,4,14
+10,6,15
+8,14,2
+15,11,19
+6,5,10
+18,8,14
+3,4,13
+16,16,15
+5,5,16
+13,5,15
+15,18,11
+16,8,13
+11,10,18
+18,7,8
+6,17,14
+4,13,17
+16,10,18
+6,5,6
+2,8,10
+13,16,2
+15,18,10
+6,16,13
+17,5,14
+17,6,13
+20,7,10
+19,7,13
+9,16,4
+5,18,10
+11,6,4
+15,14,4
+14,12,3
+11,10,3
+19,11,7
+7,3,11
+4,8,6
+10,10,20
+18,8,18
+4,15,13
+12,14,18
+18,9,13
+16,3,10
+15,6,4
+12,5,3
+7,13,16
+12,11,20
+4,4,11
+14,17,16
+19,10,15
+15,3,12
+5,4,9
+6,16,5
+15,17,10
+13,10,5
+18,9,11
+12,19,10
+10,4,16
+9,14,4
+11,5,18
+7,5,7
+9,3,13
+7,8,4
+19,12,8
+15,6,17
+16,9,4
+6,18,8
+13,14,17
+3,12,6
+18,16,12
+9,4,12
+14,4,4
+11,17,14
+16,16,6
+5,6,16
+11,3,6
+4,6,10
+13,4,18
+12,19,9
+10,3,8
+2,13,9
+9,18,10
+2,13,10
+8,2,11
+6,15,6
+16,16,14
+17,15,12
+10,3,14
+3,13,14
+18,16,9
+8,14,5
+9,9,17
+5,17,6
+5,18,14
+18,8,11
+10,5,13
+11,19,11
+14,5,16
+8,7,18
+18,5,10
+4,17,5
+18,15,14
+6,4,9
+8,8,19
+4,11,6
+14,5,6
+11,6,2
+20,12,12
+8,10,2
+3,7,10
+13,4,15
+14,7,18
+10,16,16
+2,11,16
+18,8,15
+8,5,17
+20,12,7
+6,17,16
+6,10,17
+12,4,8
+10,17,17
+10,16,5
+3,10,8
+14,2,10
+9,9,18
+19,13,10
+8,9,2
+4,11,8
+15,11,17
+16,12,6
+16,15,14
+16,16,16
+15,4,15
+7,9,3
+18,10,14
+11,14,3
+17,6,10
+9,8,4
+2,10,17
+7,9,4
+4,9,5
+17,11,15
+4,6,13
+7,16,17
+5,5,14
+9,19,15
+10,5,19
+5,5,15
+4,15,16
+19,9,9
+3,14,7
+14,14,17
+17,14,4
+19,5,11
+17,16,8
+8,19,13
+11,18,9
+6,18,14
+15,17,9
+15,9,4
+18,6,9
+18,14,7
+13,2,13
+4,8,7
+19,10,11
+14,4,14
+9,18,6
+8,15,18
+5,12,5
+8,17,9
+17,8,8
+17,6,5
+2,6,9
+2,8,11
+8,9,6
+17,9,8
+6,6,14
+17,4,9
+10,18,7
+19,7,9
+16,14,5
+4,13,4
+11,6,3
+17,4,14
+14,16,17
+5,7,4
+18,11,12
+12,15,5
+3,9,11
+5,11,4
+12,18,9
+7,16,5
+5,5,5
+11,1,13
+14,14,3
+5,17,7
+17,9,5
+9,2,15
+10,11,2
+6,11,14
+7,2,9
+14,2,8
+8,18,7
+11,19,13
+6,3,11
+13,5,18
+15,14,5
+6,3,15
+7,9,19
+16,5,8
+8,2,12
+14,9,4
+13,19,7
+14,13,18
+14,7,17
+7,8,19
+6,9,16
+12,10,3
+6,15,17
+12,18,14
+4,14,16
+6,13,2
+18,11,8
+4,11,13
+18,13,9
+18,17,11
+17,5,13
+2,8,13
+1,14,8
+7,12,3
+9,6,3
+17,15,6
+9,20,9
+15,5,12
+6,6,5
+11,16,4
+7,3,5
+16,17,14
+4,17,8
+5,5,7
+6,18,12
+11,7,3
+15,4,8
+20,10,12
+7,18,10
+17,8,5
+2,11,12
+3,6,10
+15,6,16
+15,10,17
+2,7,6
+18,15,7
+14,9,2
+2,12,7
+10,3,17
+14,12,2
+13,12,20
+20,11,13
+7,10,2
+1,9,11
+17,9,16
+3,9,4
+16,5,5
+14,9,19
+7,3,9
+7,13,3
+17,6,6
+15,11,18
+16,4,12
+10,12,3
+5,16,5
+18,7,11
+11,16,16
+2,6,8
+10,16,15
+16,9,5
+5,15,15
+10,8,19
+3,8,15
+13,15,4
+11,19,12
+15,12,18
+12,19,12
+12,15,19
+19,9,12
+3,10,14
+15,3,8
+4,5,5
+16,5,13
+5,13,17
+14,6,5
+11,19,15
+15,17,16
+3,14,9
+10,2,13
+9,4,16
+10,18,14
+9,3,15
+14,11,18
+13,13,3
+18,15,5
+18,7,6
+10,15,2
+9,18,11
+10,2,14
+13,11,1
+19,8,11
+11,10,19
+2,6,11
+8,8,4
+16,12,4
+14,15,13
+19,16,10
+10,2,9
+9,18,12
+7,4,15
+5,7,8
+12,9,18
+15,6,15
+4,14,6
+11,8,19
+14,18,8
+14,17,13
+6,13,3
+8,17,15
+8,2,14
+13,14,19
+3,5,9
+13,18,6
+18,7,7
+13,12,2
+5,9,3
+13,11,19
+5,4,11
+11,3,17
+3,5,8
+8,16,6
+13,10,20
+13,18,14
+7,17,15
+14,16,12
+8,12,2
+17,4,13
+10,11,20
+12,10,2
+11,2,8
+9,2,10
+12,1,9
+8,5,16
+12,8,3
+20,15,9
+6,8,16
+10,17,16
+16,14,8
+12,17,5
+4,8,16
+7,15,18
+9,5,14
+13,16,5
+10,8,1
+11,20,12
+17,7,8
+7,2,12
+14,19,12
+10,10,19
+7,17,8
+15,7,6
+9,11,3
+14,6,15
+5,9,5
+20,14,11
+6,17,10
+17,11,16
+8,19,9
+17,13,16
+18,14,14
+3,12,9
+16,17,12
+14,7,5
+14,17,9
+19,9,14
+10,2,10
+16,15,4
+15,10,2
+11,2,14
+8,7,6
+8,19,6
+12,2,7
+16,3,12
+14,6,4
+4,8,4
+8,4,10
+14,15,4
+12,19,13
+10,6,18
+18,6,8
+2,9,10
+11,15,3
+16,13,16
+8,9,3
+10,18,8
+11,17,15
+17,13,5
+7,2,11
+17,13,15
+8,4,9
+18,7,14
+6,17,9
+12,12,18
+4,13,12
+19,7,10
+11,10,20
+13,19,13
+15,6,11
+4,5,15
+8,11,1
+12,7,18
+13,5,5
+6,7,16
+4,6,7
+15,16,9
+6,3,14
+18,15,13
+12,13,19
+17,17,8
+12,19,7
+15,5,5
+5,6,13
+19,6,11
+14,12,5
+2,12,9
+9,4,5
+15,5,11
+3,17,10
+16,17,11
+14,13,2
+20,9,8
+17,10,16
+2,9,15
+14,4,10
+7,4,16
+13,13,17
+12,9,16
+10,7,2
+9,8,19
+13,3,6
+11,7,18
+4,8,9
+17,10,18
+10,3,7
+16,8,4
+7,6,5
+1,7,11
+5,13,18
+3,6,11
+8,11,18
+17,12,6
+8,8,3
+18,14,13
+11,9,18
+5,13,13
+15,6,6
+7,14,19
+7,12,4
+9,7,2
+13,3,13
+15,17,11
+10,17,4
+8,17,18
+12,19,14
+19,8,9
+6,16,12
+8,7,4
+4,7,7
+13,3,15
+10,20,11
+7,14,4
+18,10,9
+17,14,8
+16,7,7
+15,4,13
+18,11,5
+4,8,15
+2,9,11
+1,13,12
+2,8,9
+6,19,10
+14,8,18
+11,18,12
+16,7,4
+4,10,16
+10,18,17
+3,11,8
+12,15,17
+17,5,11
+19,9,10
+19,8,16
+2,11,13
+20,9,12
+14,4,16
+5,13,9
+15,4,9
+18,10,11
+3,12,7
+4,9,12
+4,13,5
+11,15,18
+7,13,2
+12,1,12
+5,9,11
+2,8,12
+17,7,15
+14,5,12
+12,5,18
+3,14,11
+5,13,4
+17,8,7
+15,5,6
+19,8,7
+13,16,16
+5,11,15
+3,10,11
+8,6,16
+19,8,15
+6,18,7
+18,7,10
+14,3,9
+10,16,4
+15,19,13
+8,16,16
+17,14,17
+3,13,8
+4,5,11
+9,18,3
+5,17,14
+7,9,18
+6,16,6
+9,6,18
+6,9,19
+6,7,3
+9,19,13
+16,15,5
+14,16,7
+12,17,17
+18,9,17
+12,11,19
+16,7,17
+13,4,6
+3,6,12
+13,17,5
+8,18,14
+5,14,5
+15,18,12
+13,2,10
+5,5,9
+18,6,10
+9,13,18
+3,10,9
+6,6,18
+17,15,7
+4,9,7
+3,11,17
+15,6,8
+4,7,15
+11,12,1
+12,7,17
+6,14,3
+15,15,15
+17,14,11
+6,6,7
+13,20,13
+15,9,2
+12,2,11
+5,6,7
+13,8,3
+2,7,10
+19,10,12
+6,10,16
+16,17,6
+13,8,17
+17,13,4
+7,2,7
+11,9,3
+12,11,2
+13,8,16
+5,10,2
+10,19,7
+8,4,6
+17,5,9
+13,1,10
+16,4,13
+13,6,1
+6,11,4
+18,14,6
+12,13,17
+17,15,10
+7,12,1
+6,4,12
+4,7,9
+16,7,15
+6,9,6
+5,12,3
+4,14,14
+14,13,20
+15,18,15
+19,14,11
+16,18,12
+10,15,15
+6,6,17
+9,5,6
+14,18,11
+13,2,11
+7,19,8
+19,14,8
+18,11,11
+13,6,4
+1,10,8
+9,14,17
+16,17,13
+4,7,17
+10,1,11
+9,2,13
+4,10,7
+4,8,13
+8,15,3
+13,10,3
+10,9,20
+19,12,6
+3,14,10
+1,12,10
+7,9,2
+9,17,16
+9,1,12
+18,8,6
+6,5,4
+6,14,7
+12,19,8
+14,10,19
+17,6,7
+8,5,15
+11,19,7
+13,18,9
+18,6,13
+8,17,16
+10,7,14
+18,11,4
+15,17,8
+1,7,10
+10,19,12
+16,5,6
+9,11,18
+17,16,7
+6,7,8
+5,9,4
+6,4,14
+16,9,16
+13,4,13
+11,3,9
+12,13,2
+11,3,16
+5,6,17
+13,3,7
+9,4,7
+5,15,9
+16,10,5
+15,13,14
+15,11,3
+7,17,11
+11,5,5
+7,3,15
+4,16,10
+11,9,19
+15,12,2
+16,6,16
+19,11,14
+13,3,8
+15,17,14
+1,8,9
+19,13,9
+10,11,18
+7,1,10
+13,4,7
+12,1,16
+5,6,10
+13,18,11
+10,10,1
+5,11,2
+19,9,13
+4,17,13
+19,14,10
+15,16,6
+7,12,2
+10,11,1
+8,17,4
+10,15,1
+7,16,4
+3,15,14
+11,9,2
+19,8,14
+4,11,4
+10,13,20
+3,15,13
+15,16,18
+16,18,13
+14,13,4
+1,10,12
+11,20,13
+12,6,4
+5,12,4
+17,4,12
+4,10,3
+5,9,6
+5,15,12
+16,11,16
+5,7,10
+15,6,14
+3,10,10
+5,16,17
+18,10,16
+11,4,13
+9,5,16
+11,2,9
+12,5,8
+3,14,14
+6,11,6
+15,6,3
+8,11,20
+9,15,3
+12,4,3
+17,12,4
+6,9,18
+7,11,18
+4,18,10
+6,5,8
+3,13,6
+14,2,11
+7,11,19
+1,10,13
+4,15,14
+8,16,3
+16,7,6
+13,8,19
+15,17,5
+5,8,8
+17,10,7
+15,7,5
+14,5,3
+16,15,12
+1,9,13
+2,9,13
+11,1,9
+16,5,14
+2,12,13
+3,6,16
+5,16,8
+10,3,12
+3,14,16
+12,2,15
+5,12,6
+12,3,16
+8,3,7
+16,4,11
+5,8,17
+11,2,11
+13,17,13
+11,4,18
+3,16,10
+3,12,8
+2,10,13
+18,15,11
+18,5,12
+2,7,11
+14,3,6
+15,6,5
+14,10,2
+2,12,14
+6,13,4
+15,16,16
+8,19,12
+2,10,8
+15,9,19
+14,6,6
+15,4,10
+17,14,16
+2,11,14
+9,16,5
+8,18,9
+10,7,1
+16,5,9
+18,6,16
+15,13,16
+5,15,7
+16,4,15
+15,16,14
+6,8,6
+14,5,10
+16,5,15
+9,5,15
+6,3,13
+8,16,18
+16,3,11
+7,3,7
+9,13,19
+16,14,13
+12,3,8
+9,9,3
+2,11,10
+17,14,13
+14,16,6
+20,12,14
+10,5,16
+13,9,4
+12,5,4
+1,13,8
+17,17,14
+3,10,7
+10,13,2
+15,9,17
+14,19,10
+4,5,12
+7,10,3
+13,16,6
+16,7,9
+3,16,12
+4,9,4
+16,8,18
+2,11,5
+13,17,6
+7,17,5
+6,19,14
+5,16,6
+10,17,13
+3,8,13
+3,7,15
+12,4,7
+4,6,4
+11,14,19
+9,18,16
+8,3,6
+9,2,12
+13,2,7
+8,4,13
+8,17,14
+19,10,10
+10,15,5
+15,15,6
+18,15,10
+5,9,18
+10,20,13
+12,17,14
+19,7,12
+6,8,18
+16,2,10
+2,7,12
+7,13,4
+17,15,14
+8,15,5
+12,17,6
+18,9,8
+16,12,3
+11,9,1
+10,18,16
+16,10,16
+12,5,7
+15,19,11
+12,8,20
+10,9,3
+6,12,17
+1,14,9
+8,7,17
+13,5,4
+13,14,1
+9,13,4
+7,16,10
+9,17,18
+15,16,4
+5,8,15
+3,6,13
+7,11,3
+19,11,12
+10,11,3
+4,9,3
+12,7,4
+10,19,11
+17,8,3
+10,17,3
+6,12,2
+9,17,9
+6,7,15
+8,14,7
+15,10,18
+4,8,14
+19,14,7
+13,1,8
+18,14,12
+14,14,18
+13,15,15
+6,5,14
+10,15,18
+14,2,9
+12,13,3
+7,15,7
+14,4,5
+11,1,8
+16,14,15
+18,10,13
+4,16,12
+5,5,13
+4,15,5
+17,9,7
+14,5,17
+6,10,14
+11,17,5
+20,8,10
+14,17,7
+11,13,4
+9,3,8
+9,16,18
+2,7,14
+5,3,9
+6,11,18
+14,5,11
+8,2,7
+7,14,5
+7,3,6
+6,2,13
+9,18,9
+1,11,15
+3,7,4
+4,12,18
+16,9,18
+9,18,14
+3,7,14
+7,18,11
+19,7,8
+5,11,3
+6,12,4
+17,12,7
+13,5,7
+16,18,10
+7,18,12
+5,8,7
+9,2,5
+9,2,11
+10,2,7
+13,19,8
+12,19,16
+3,6,14
+16,7,14
+16,15,16
+18,8,9
+5,13,14
+5,7,17
+3,10,13
+6,2,11
+3,9,5
+6,13,19
+16,16,5
+9,9,19
+10,16,17
+15,17,15
+11,2,5
+11,19,9
+8,5,18
+5,16,15
+15,8,5
+19,11,13
+20,12,10
+9,13,20
+14,18,16
+12,17,12
+13,15,14
+6,6,4
+14,8,6
+18,12,8
+6,6,6
+16,4,9
+11,20,11
+9,3,10
+5,9,17
+18,11,9
+4,10,5
+4,13,9
+17,8,16
+9,17,17
+7,13,19
+19,13,11
+14,8,5
+7,18,6
+9,12,18
+4,16,7
+2,10,12
+17,9,15
+12,12,20
+17,12,14
+2,13,7
+5,15,5
+5,15,17
+11,3,10
+16,3,6
+12,16,17
+4,7,10
+11,2,12
+16,4,10
+17,6,11
+9,4,17
+8,4,15
+15,10,19
+15,17,12
+9,3,7
+15,15,3
+9,16,16
+11,11,18
+16,5,4
+14,16,15
+2,15,7
+9,7,19
+2,9,12
+14,11,4
+16,13,15
+10,6,4
+20,13,9
+5,2,10
+19,9,7
+3,8,16
+2,13,11
+7,18,8
+16,18,14
+12,3,17
+5,7,11
+10,19,6
+7,6,18
+4,5,6
+19,8,8
+5,6,4
+7,18,5
+19,17,10
+4,5,14
+17,10,3
+16,13,14
+13,9,3
+10,6,2
+11,19,6
+9,6,19
+7,19,9
+18,9,4
+14,7,6
+8,18,10
+15,6,12
+11,18,6
+11,17,18
+18,9,14
+19,15,10
+14,5,5
+7,19,11
+3,7,11
+9,16,14
+4,5,7
+4,18,13
+17,7,12
+15,8,6
+17,17,11
+3,8,5
+11,5,17
+8,10,18
+10,8,2
+16,2,12
+5,10,16
+17,8,12
+16,11,5
+4,12,7
+15,10,3
+8,4,4
+14,1,12
+8,3,8
+10,7,19
+16,7,5
+4,13,13
+8,4,16
+6,13,17
+18,9,7
+15,7,4
+8,14,18
+9,7,14
+16,12,17
+1,8,11
+1,14,12
+14,5,8
+16,15,13
+18,6,11
+3,13,9
+10,4,15
+19,6,13
+6,6,8
+15,16,5
+9,15,18
+7,4,6
+8,5,10
+8,2,13
+5,11,5
+6,13,15
+13,3,12
+17,9,10
+6,5,11
+11,18,5
+6,6,16
+14,5,18
+17,10,17
+11,12,3
+11,4,4
+11,18,10
+16,16,13
+11,17,7
+10,19,10
+2,10,15
+7,4,17
+8,10,19
+11,17,9
+15,18,6
+2,15,8
+18,13,4
+3,7,7
+2,12,15
+6,6,9
+7,16,16
+5,5,4
+15,14,18
+8,20,13
+7,11,4
+18,10,17
+17,9,9
+14,3,15
+5,14,3
+14,3,7
+6,8,17
+4,15,12
+17,15,11
+13,11,17
+4,9,15
+15,4,5
+8,17,10
+18,14,11
+7,18,13
+15,12,4
+14,4,11
+16,5,12
+2,10,7
+15,9,5
+2,14,16
+16,15,9
+8,4,5
+19,12,10
+8,6,7
+7,1,9
+10,12,2
+17,9,3
+5,3,14
+6,11,16
+7,4,13
+14,15,5
+11,7,2
+12,4,5
+5,13,5
+4,10,9
+16,7,13
+4,10,8
+7,8,3
+4,10,14
+8,3,18
+3,14,13
+6,17,5
+3,8,7
+16,7,16
+4,6,15
+15,17,13
+6,4,4
+12,3,6
+8,4,17
+6,3,10
+15,8,17
+19,10,9
+7,4,8
+19,15,11
+18,4,9
+10,3,15
+13,19,14
+4,15,9
+9,19,11
+9,2,8
+17,6,8
+18,9,6
+17,8,6
+4,13,8
+16,17,10
+9,2,7
+7,10,16
+18,12,6
+9,8,18
+7,17,13
+14,5,9
+10,19,14
+17,12,16
+8,17,8
+16,15,8
+11,16,5
+8,18,12
+10,13,1
+15,18,7
+15,13,4
+8,3,14
+17,15,15
+5,17,9
+18,9,15
+4,3,11
+8,17,6
+5,3,10
+18,8,12
+18,8,16
+17,7,9
+4,4,14
+9,12,19
+13,5,14
+5,18,12
+8,2,10
+12,3,11
+11,12,4
+11,8,17
+13,14,4
+10,18,12
+17,13,10
+17,15,16
+2,7,8
+12,6,16
+5,7,14
+7,16,15
+13,13,4
+13,5,17
+13,17,9
+17,13,13
+10,3,18
+13,18,15
+8,19,14
+9,3,12
+4,12,4
+17,10,15
+11,7,17
+7,17,7
+17,10,14
+13,6,6
+2,9,7
+13,7,4
+7,7,14
+4,12,14
+8,14,16
+13,14,3
+17,16,16
+5,16,12
+18,16,13
+13,13,18
+4,16,8
+9,10,1
+5,3,11
+12,18,12
+3,12,15
+14,10,18
+4,5,13
+6,5,16
+7,16,14
+17,16,6
+11,18,11
+16,6,12
+14,6,16
+8,4,7
+5,12,8
+15,19,14
+15,15,17
+13,16,7
+15,14,6
+5,14,7
+8,15,2
+13,8,2
+15,2,10
+18,10,6
+5,15,3
+9,4,15
+12,11,4
+9,17,4
+20,10,15
+11,2,7
+20,8,13
+9,17,5
+9,5,17
+11,18,7
+11,1,10
+10,14,17
+17,3,7
+9,1,8
+14,5,13
+13,9,1
+10,20,7
+17,13,6
+13,2,9
+10,19,8
+12,17,11
+12,13,4
+4,15,15
+10,13,16
+13,11,18
+15,5,13
+5,10,5
+11,15,6
+5,18,11
+14,7,4
+5,17,11
+7,7,20
+6,16,14
+7,8,17
+12,3,5
+13,19,6
+3,13,7
+9,10,16
+12,16,3
+12,9,1
+6,15,14
+12,3,12
+15,3,13
+7,15,16
+4,11,17
+2,7,9
+8,19,5
+2,12,8
+16,11,2
+14,3,11
+4,14,9
+15,15,16
+4,16,15
+9,5,5
+3,13,5
+10,6,5
+15,10,14
+16,4,16
+18,12,7
+8,18,13
+7,19,13
+14,19,9
+10,14,2
+13,16,3
+12,4,17
+12,17,15
+19,11,5
+8,6,5
+10,10,3
+11,20,10
+17,7,14
+13,17,16
+13,20,10
+8,18,5
+7,5,3
+2,14,10
+3,8,9
+14,6,18
+6,10,2
+14,16,8
+9,20,14
+18,5,11
+9,4,14
+5,17,12
+7,18,15
+7,5,13
+17,7,13
+9,5,4
+18,13,16
+7,18,9
+7,15,6
+3,10,6
+12,17,4
+12,12,19
+13,17,8
+12,3,3
+5,15,13
+4,10,6
+16,3,9
+6,16,4
+7,19,14
+3,11,13
+10,10,18
+4,5,8
+11,15,4
+14,12,19
+17,16,9
+9,11,17
+18,11,16
+10,16,19
+10,1,13
+13,8,1
+19,12,7
+5,14,16
+10,14,5
+7,2,8
+15,15,10
+12,8,2
+7,15,17
+8,12,17
+2,16,8
+10,16,6
+7,6,7
+5,17,5
+7,8,16
+11,17,6
+5,6,14
+4,4,9
+11,20,9
+2,13,13
+18,3,10
+11,5,15
+18,7,12
+12,12,2
+4,16,11
+19,12,9
+14,18,13
+19,12,14
+8,20,8
+9,3,16
+8,19,8
+11,13,18
+15,16,3
+13,12,3
+2,6,10
+8,18,6
+15,4,6
+5,14,17
+6,14,17
+2,14,12
+11,6,19
+20,8,12
+1,9,14
+18,10,4
+13,6,15
+7,14,2
+3,15,8
+13,7,2
+4,13,6
+10,17,8
+5,5,11
+10,0,10
+10,9,19
+18,13,6
+13,7,15
+13,7,17
+7,15,3
+7,16,6
+14,15,7
+9,10,2
+10,10,17
+3,8,17
+15,13,2
+9,18,17
+9,13,1
+12,3,15
+12,6,18
+17,12,11
+7,3,10
+4,4,10
+16,14,18
+15,16,17
+10,18,9
+17,7,17
+1,8,12
+7,6,16
+13,1,11
+15,16,15
+17,13,7
+10,17,15
+19,9,16
+2,14,14
+14,16,16
+6,15,5
+3,4,9
+12,16,20
+3,12,16
+1,9,12
+11,16,17
+19,5,12
+14,17,14
+13,6,5
+8,4,12
+5,7,5
+12,7,3
+16,12,18
+6,19,11
+11,19,8
+8,17,17
+15,2,13
+15,16,8
+19,11,9
+13,9,17
+5,13,16
+4,10,4
+4,4,13
+4,6,5
+15,9,16
+14,14,19
+19,9,5
+4,7,5
+13,19,15
+12,12,1
+12,1,13
+9,12,20
+9,11,19
+11,13,3
+13,17,10
+6,19,12
+16,6,13
+2,13,6
+18,5,13
+20,9,9
+3,6,9
+9,20,12
+5,6,12
+15,16,11
+19,10,6
+10,13,3
+16,12,15
+18,11,17
+1,12,11
+6,18,9
+5,12,14
+5,14,18
+6,7,18
+9,6,4
+12,1,11
+11,3,12
+13,4,4
+13,7,3
+18,9,16
+3,17,13
+18,13,11
+14,6,3
+16,15,15
+12,14,16
+11,1,14
+9,12,2
+1,11,12
+4,7,8
+10,18,6
+11,3,8
+8,17,5
+9,9,20
+11,7,4
+2,15,10
+11,4,14
+7,16,9
+3,4,7
+4,18,9
+13,10,17
+17,5,12
+12,8,18
+13,9,19
+14,6,7
+12,13,20
+6,12,19
+13,8,20
+17,11,17
+8,13,20
+16,17,7
+14,17,6
+16,16,8
+15,4,12
+4,11,16
+11,12,18
+15,19,7
+16,5,11
+2,7,13
+15,7,17
+13,19,11
+18,10,10
+15,9,3
+7,7,4
+11,18,14
+5,12,13
+11,13,16
+12,10,1
+5,12,2
+2,10,14
+19,8,10
+6,9,17
+15,3,15
+10,15,3
+3,5,14
+2,11,7
+12,4,10
+13,10,18
+10,12,19
+8,9,20
+6,12,18
+14,12,18
+18,15,6
+13,20,14
+7,16,18
+13,4,10
+16,11,10
+8,2,8
+4,12,17
+5,7,12
+11,14,17
+7,8,20
+18,6,6
+16,8,17
+4,12,8
+11,1,11
+15,12,16
+14,4,17
+11,6,17
+9,3,11
+19,9,6
+13,18,12
+12,3,4
+14,4,6
+16,17,8
+4,13,15
+3,8,8
+1,12,8
+16,4,7
+12,6,19
+13,6,18
+12,8,1
+3,4,8
+4,5,10
+12,18,7
+14,18,10
+18,4,12
+15,7,15
+16,7,11
+17,15,5
+16,14,14
+17,13,14
+11,11,1
+5,11,18
+16,11,3
+20,10,6
+15,10,16
+17,13,11
+6,19,7
+9,8,3
+4,13,7
+14,11,17
+10,1,8
+15,18,14
+3,5,7
+14,7,16
+3,15,7
+7,8,2
+13,14,5
+2,14,8
+15,5,7
+3,12,14
+14,13,5
+10,8,3
+8,15,4
+12,7,19
+4,14,10
+2,12,10
+13,11,4
+18,12,17
+14,15,17
+17,6,12
+14,19,7
+6,9,2
+17,11,8
+15,3,9
+13,13,19
+9,9,2
+18,5,14
+18,10,15
+18,9,10
+17,14,5
+4,9,14
+5,7,16
+4,6,14
+14,2,12
+7,4,11
+6,17,7
+14,9,17
+14,15,8
+16,9,7
+10,6,19
+19,13,7
+4,10,15
+4,15,4
+7,17,4
+3,10,5
+4,17,11
+6,17,15
+7,14,18
+3,9,12
+10,18,5
+9,15,19
+10,16,2
+14,4,12
+16,9,17
+15,4,16
+19,16,12
+17,8,17
+5,6,11
+14,18,7
+1,10,11
+12,14,4
+17,8,10
+5,10,18
+7,4,10
+8,13,4
+17,12,12
+6,11,19
+18,12,9
+3,12,11
+3,7,12
+16,13,12
+16,11,18
+5,4,13
+13,1,13
+6,14,20
+18,15,8
+17,9,11
+16,8,3
+5,4,8
+5,13,8
+20,10,7
+11,13,1
+4,11,7
+14,15,18
+12,20,14
+12,7,5
+6,6,15
+11,1,7
+5,8,3
+13,4,17
+14,8,2
+11,3,15
+8,15,15
+4,9,6
+16,9,15
+15,19,12
+6,2,9
+12,18,10
+5,18,7
+8,1,8
+14,3,5
+8,5,2
+18,13,13
+10,17,6
+10,6,3
+14,6,2
+6,7,17
+12,19,15
+10,18,10
+13,18,13
+9,10,18
+16,14,7
+3,9,17
+20,11,8
+19,6,9
+9,6,14
+7,13,17
+11,0,11
+9,18,8
+15,11,16
+18,7,9
+11,15,19
+16,17,16
+18,8,8
+18,13,14
+11,18,15
+5,8,12
+5,19,11
+8,7,19
+6,16,10
+6,15,15
+4,15,8
+14,17,4
+3,13,16
+12,10,4
+19,7,14
+2,14,7
+14,18,12
+21,10,10
+20,10,10
+8,18,4
+10,16,14
+5,15,10
+10,20,10
+16,4,6
+17,15,4
+7,2,15
+7,17,9
+4,13,14
+12,6,3
+8,9,18
+4,5,9
+13,17,7
+18,14,5
+8,13,19
+19,9,15
+2,8,15
+17,10,4
+12,16,6
+19,8,13
+8,18,16
+10,19,15
+6,12,5
+5,4,6
+7,14,17
+4,8,17
+20,13,10
+11,18,4
+11,8,1
+7,19,6
+12,7,8
+10,8,20
+17,11,4
+9,20,7
+4,14,11
+11,7,19
+12,4,15
+19,14,12
+13,19,10
+11,14,2
+2,9,6
+18,8,10
+9,17,11
+16,14,3
+7,11,17
+13,16,10
+13,18,8
+6,15,3
+12,20,10
+15,14,16
+13,11,2
+8,16,5
+8,13,18
+17,15,13
+3,11,12
+17,7,6
+6,12,16
+3,3,12
+16,3,15
+3,9,15
+6,18,11
+9,3,9
+4,7,11
+14,12,17
+7,15,4
+14,10,17
+5,19,12
+6,6,3
+7,7,18
+10,16,18
+13,17,11
+12,8,17
+9,19,6
+15,17,17
+13,11,3
+5,12,15
+2,14,13
+9,18,4
+3,8,12
+17,14,14
+2,8,7
+19,10,8
+6,5,9
+12,17,18
+18,12,10
+8,4,8
+17,11,10
+3,12,10
+7,9,16
+13,3,9
+5,8,18
+3,11,9
+7,17,10
+11,15,16
+2,10,10
+16,9,3
+9,14,19
+2,11,15
+14,15,3
+11,14,5
+5,10,14
+18,15,12
+8,3,4
+9,19,7
+8,20,12
+10,5,18
+5,12,16
+9,11,4
+20,10,8
+5,15,11
+19,6,10
+18,6,14
+11,20,8
+15,8,13
+8,5,4
+5,18,8
+19,8,6
+15,12,17
+14,8,19
+14,8,20
+10,14,19
+13,15,18
+9,16,19
+17,6,17
+11,18,16
+12,11,1
+19,12,15
+4,14,13
+17,18,11
+3,4,10
+11,5,19
+13,2,15
+8,8,17
+4,12,3
+16,8,5
+3,7,5
+16,12,5
+5,15,14
+4,12,9
+18,13,7
+10,6,6
+10,14,18
+5,8,6
+1,11,13
+8,7,16
+2,16,11
+10,3,9
+8,3,9
+18,16,6
+16,6,15
+15,5,8
+12,5,6
+9,16,8
+7,17,17
+2,12,12
+9,6,2
+10,5,3
+10,14,20
+17,18,10
+13,6,2
+9,17,6
+6,15,8
+16,9,6
+3,6,8
+17,12,18
+3,10,16
+10,17,14
+7,6,11
+15,9,18
+10,16,13
+13,1,12
+15,15,19
+17,16,13
+13,17,4
+14,17,12
+7,7,5
+20,10,9
+10,13,18
+10,19,5
+3,15,15
+10,6,16
+14,1,7
+7,7,19
+19,15,12
+13,1,7
+1,12,14
+3,7,6
+6,13,16
+2,9,16
+3,14,6
+13,13,2
+11,17,17
+5,16,16
+13,15,5
+5,7,15
+2,10,6
+11,15,17
+3,16,14
+18,13,10
+17,10,6
+13,20,9
+13,3,5
+4,3,10
+10,4,18
+1,10,14
+12,13,18
+7,14,14
+18,8,7
+8,5,3
+11,17,16
+15,7,2
+4,5,16
+3,12,5
+11,19,16
+14,4,8
+5,3,12
+18,14,9
+16,13,13
+15,13,5
+12,11,18
+14,4,13
+8,10,1
+2,8,6
+16,7,18
+3,5,11
+18,13,17
+14,15,6
+8,11,4
+3,9,9
+15,8,15
+16,6,8
+13,14,2
+15,7,14
+17,9,6
+18,13,5
+15,18,8
+11,6,20
+15,11,2
+18,16,7
+8,20,9
+2,11,8
+14,11,6
+9,17,13
+17,16,5
+12,3,9
+7,10,5
+13,3,11
+1,8,10
+17,9,18
+4,17,15
+2,9,14
+9,8,17
+11,9,20
+4,15,6
+16,11,15
+17,13,9
+12,4,13
+18,12,12
+9,14,2
+8,11,16
+9,7,4
+5,3,7
+10,18,4
+5,15,4
+6,14,18
+17,7,4
+8,18,11
+14,18,6
+16,15,10
+18,17,12
+4,14,8
+12,15,3
+6,3,12
+10,11,4
+9,5,7
+5,5,17
+5,2,11
+15,5,14
+10,4,13
+10,5,14
+6,5,17
+5,16,13
+13,9,18
+14,5,14
+17,15,8
+1,13,10
+12,6,15
+1,12,12
+14,17,10
+10,4,17
+6,18,6
+12,19,6
+14,2,13
+19,15,9
+15,7,3
+17,17,15
+14,9,5
+14,14,2
diff --git a/day18/uppga.c b/day18/uppga.c
@@ -0,0 +1,88 @@
+#include "common.h"
+
+typedef struct cube {
+ uint64_t coord[3];
+ size_t nnbrs;
+ size_t* nbrs;
+} cube;
+
+void print_cube(cube* c)
+{
+ printf("(%llu, %llu, %llu)\n", c->coord[0], c->coord[1], c->coord[2]);
+
+ size_t i;
+ printf(" |->");
+ for(i = 0; i < c->nnbrs; i++) {
+ printf(" %zu", c->nbrs[i]);
+ }
+ printf("\n");
+}
+
+int adjacent(cube* a, cube* b)
+{
+ int x1 = a->coord[0];
+ int x2 = b->coord[0];
+ int y1 = a->coord[1];
+ int y2 = b->coord[1];
+ int z1 = a->coord[2];
+ int z2 = b->coord[2];
+ return (abs(x1 - x2) <= 1 && y1 == y2 && z1 == z2)
+ || (abs(y1 - y2) <= 1 && x1 == x2 && z1 == z2)
+ || (abs(z1 - z2) <= 1 && x1 == x2 && y1 == y2);
+}
+
+void add_nbr(cube* x, size_t nbr_index)
+{
+// printf("adding nbrs to cube (%llu, %llu, %llu)\n", x->coord[0], x->coord[1], x->coord[2]);
+ x->nbrs[x->nnbrs] = nbr_index;
+ x->nnbrs++;
+}
+
+uint64_t e(cube* cubes, size_t ncubes)
+{
+ uint64_t c = 0;
+
+ size_t i;
+ for(i = 0; i < ncubes; i++)
+ c += cubes[i].nnbrs;
+
+ return c/2;
+}
+
+int main(int argc, char** argv)
+{
+ char** lines;
+ size_t nlines = readlines(&lines, "input");
+ printf("#lines: %lu\n", nlines);
+
+ cube cubes[nlines];
+ size_t i,j;
+ for(i = 0; i < nlines; i++) {
+ char* line = lines[i];
+ line = sread_next_u64(&cubes[i].coord[0], line);
+ line = sread_next_u64(&cubes[i].coord[1], line);
+ line = sread_next_u64(&cubes[i].coord[2], line);
+
+ cubes[i].nnbrs = 0;
+ cubes[i].nbrs = malloc(nlines * sizeof(*(cubes[i].nbrs)));
+ }
+
+ for(i = 0; i < nlines; i++) {
+ for(j = i+1; j < nlines; j++) {
+ if(adjacent(&cubes[i], &cubes[j])) {
+ add_nbr(&cubes[i], j);
+ add_nbr(&cubes[j], i);
+ }
+ }
+ }
+
+ uint64_t ee = e(cubes, nlines);
+ printf("%llu\n", ee);
+
+ for(i = 0; i < nlines; i++) {
+ print_cube(&cubes[i]);
+ }
+
+ assert(6*nlines >= ee);
+ printf("%llu\n", 6*nlines - 2*ee);
+}
diff --git a/day18/uppgb.c b/day18/uppgb.c
@@ -0,0 +1,230 @@
+#include "common.h"
+#include <sys/queue.h>
+
+typedef struct cube {
+ uint64_t coord[3];
+
+ size_t nnbrs;
+ size_t* nbrs;
+} cube;
+
+void print_cube(cube* c)
+{
+ printf("(%llu, %llu, %llu)\n", c->coord[0], c->coord[1], c->coord[2]);
+}
+
+typedef struct entry {
+ uint64_t x;
+ uint64_t y;
+ uint64_t z;
+
+ STAILQ_ENTRY(entry) entries;
+} entry;
+
+int adjacent(cube* a, cube* b)
+{
+ int x1 = a->coord[0];
+ int x2 = b->coord[0];
+ int y1 = a->coord[1];
+ int y2 = b->coord[1];
+ int z1 = a->coord[2];
+ int z2 = b->coord[2];
+ return (abs(x1 - x2) <= 1 && y1 == y2 && z1 == z2)
+ || (abs(y1 - y2) <= 1 && x1 == x2 && z1 == z2)
+ || (abs(z1 - z2) <= 1 && x1 == x2 && y1 == y2);
+}
+
+void add_nbr(cube* x, size_t nbr_index)
+{
+// printf("adding nbrs to cube (%llu, %llu, %llu)\n", x->coord[0], x->coord[1], x->coord[2]);
+ x->nbrs[x->nnbrs] = nbr_index;
+ x->nnbrs++;
+}
+
+uint64_t e(cube* cubes, size_t ncubes)
+{
+ uint64_t c = 0;
+
+ size_t i;
+ for(i = 0; i < ncubes; i++)
+ c += cubes[i].nnbrs;
+
+ return c/2;
+}
+
+int main(int argc, char** argv)
+{
+ char** lines;
+ size_t nlines = readlines(&lines, "input");
+ printf("#lines: %lu\n", nlines);
+
+ cube cubes[nlines];
+ size_t i,j,k;
+ for(i = 0; i < nlines; i++) {
+ char* line = lines[i];
+ line = sread_next_u64(&cubes[i].coord[0], line);
+ line = sread_next_u64(&cubes[i].coord[1], line);
+ line = sread_next_u64(&cubes[i].coord[2], line);
+ }
+
+ uint64_t maxx = 0, maxy = 0, maxz = 0;
+ for(i = 0; i < nlines; i++) {
+ if(maxx < cubes[i].coord[0]) maxx = cubes[i].coord[0];
+ if(maxy < cubes[i].coord[1]) maxy = cubes[i].coord[1];
+ if(maxz < cubes[i].coord[2]) maxz = cubes[i].coord[2];
+ }
+
+ printf("maxx = %llu, maxy = %llu, maxz = %llu\n", maxx, maxy, maxz);
+
+ uint8_t filler[maxx+1][maxy+1][maxz+1];
+ memset(filler, 0, (maxx+1)*(maxy+1)*(maxz+1));
+
+ for(i = 0; i < nlines; i++) {
+ filler[cubes[i].coord[0]][cubes[i].coord[1]][cubes[i].coord[2]] = 2;
+ }
+
+ size_t filled = 0;
+ STAILQ_HEAD(listhead, entry) head = STAILQ_HEAD_INITIALIZER(head);
+
+
+ entry *elt;
+
+ for(i = 0; i < maxy+1; i++) {
+ for(j = 0; j < maxz+1; j++) {
+ if(filler[0][i][j] == 0) {
+ elt = malloc(sizeof(*elt));
+ elt->x = 0; elt->y = i; elt->z = j;
+ filler[elt->x][elt->y][elt->z] = 1;
+ STAILQ_INSERT_TAIL(&head, elt, entries);
+ }
+ if(filler[maxx][i][j] == 0) {
+ elt = malloc(sizeof(*elt));
+ elt->x = maxx; elt->y = i; elt->z = j;
+ filler[elt->x][elt->y][elt->z] = 1;
+ STAILQ_INSERT_TAIL(&head, elt, entries);
+ }
+ }
+ }
+
+ for(i = 0; i < maxx+1; i++) {
+ for(j = 0; j < maxz+1; j++) {
+ if(filler[i][0][j] == 0) {
+ elt = malloc(sizeof(*elt));
+ elt->x = i; elt->y = 0; elt->z = j;
+ filler[elt->x][elt->y][elt->z] = 1;
+ STAILQ_INSERT_TAIL(&head, elt, entries);
+ }
+ if(filler[i][maxy][j] == 0) {
+ elt = malloc(sizeof(*elt));
+ elt->x = i; elt->y = maxy; elt->z = j;
+ filler[elt->x][elt->y][elt->z] = 1;
+ STAILQ_INSERT_TAIL(&head, elt, entries);
+ }
+ }
+ }
+
+ for(i = 0; i < maxx+1; i++) {
+ for(j = 0; j < maxy+1; j++) {
+ if(filler[i][j][0] == 0) {
+ elt = malloc(sizeof(*elt));
+ elt->x = i; elt->y = j; elt->z = 0;
+ filler[elt->x][elt->y][elt->z] = 1;
+ STAILQ_INSERT_TAIL(&head, elt, entries);
+ }
+ if(filler[i][j][maxz] == 0) {
+ elt = malloc(sizeof(*elt));
+ elt->x = i; elt->y = j; elt->z = maxz;
+ filler[elt->x][elt->y][elt->z] = 1;
+ STAILQ_INSERT_TAIL(&head, elt, entries);
+ }
+ }
+ }
+
+ while(!STAILQ_EMPTY(&head)) {
+ elt = STAILQ_FIRST(&head);
+ STAILQ_REMOVE_HEAD(&head, entries);
+ filled++;
+
+ if(elt->x > 0 && filler[elt->x-1][elt->y][elt->z] == 0) {
+ entry* new = malloc(sizeof(*new));
+ new->x = elt->x-1; new->y = elt->y; new->z = elt->z;
+ filler[new->x][new->y][new->z] = 1;
+ STAILQ_INSERT_TAIL(&head, new, entries);
+ }
+ if(elt->x < maxx && filler[elt->x+1][elt->y][elt->z] == 0) {
+ entry* new = malloc(sizeof(*new));
+ new->x = elt->x+1; new->y = elt->y; new->z = elt->z;
+ filler[new->x][new->y][new->z] = 1;
+ STAILQ_INSERT_TAIL(&head, new, entries);
+ }
+
+ if(elt->y > 0 && filler[elt->x][elt->y-1][elt->z] == 0) {
+ entry* new = malloc(sizeof(*new));
+ new->x = elt->x; new->y = elt->y-1; new->z = elt->z;
+ filler[new->x][new->y][new->z] = 1;
+ STAILQ_INSERT_TAIL(&head, new, entries);
+ }
+ if(elt->y < maxy && filler[elt->x][elt->y+1][elt->z] == 0) {
+ entry* new = malloc(sizeof(*new));
+ new->x = elt->x; new->y = elt->y+1; new->z = elt->z;
+ filler[new->x][new->y][new->z] = 1;
+ STAILQ_INSERT_TAIL(&head, new, entries);
+ }
+
+ if(elt->z > 0 && filler[elt->x][elt->y][elt->z-1] == 0) {
+ entry* new = malloc(sizeof(*new));
+ new->x = elt->x; new->y = elt->y; new->z = elt->z-1;
+ filler[new->x][new->y][new->z] = 1;
+ STAILQ_INSERT_TAIL(&head, new, entries);
+ }
+ if(elt->z < maxz && filler[elt->x][elt->y][elt->z+1] == 0) {
+ entry* new = malloc(sizeof(*new));
+ new->x = elt->x; new->y = elt->y; new->z = elt->z+1;
+ filler[new->x][new->y][new->z] = 1;
+ STAILQ_INSERT_TAIL(&head, new, entries);
+ }
+
+ free(elt);
+ }
+
+ size_t nucubes = (maxx+1)*(maxy+1)*(maxz+1) - filled;
+ printf("nucubes = %zu\n", nucubes);
+
+ cube ucubes[nucubes];
+ size_t c = 0;
+ for(i = 0; i < maxx+1; i++) {
+ for(j = 0; j < maxy+1; j++) {
+ for(k = 0; k < maxz+1; k++) {
+ if(filler[i][j][k] != 1) {
+ ucubes[c].coord[0] = i;
+ ucubes[c].coord[1] = j;
+ ucubes[c].coord[2] = k;
+
+ ucubes[c].nnbrs = 0;
+ ucubes[c].nbrs = malloc(nucubes * sizeof(*(ucubes[c].nbrs)));
+
+ c++;
+ }
+ }
+ }
+ }
+
+ for(i = 0; i < nucubes; i++) {
+ for(j = i+1; j < nucubes; j++) {
+ if(adjacent(&ucubes[i], &ucubes[j])) {
+ add_nbr(&ucubes[i], j);
+ add_nbr(&ucubes[j], i);
+ }
+ }
+ }
+
+ for(i = 0; i < nucubes; i++) {
+ print_cube(&ucubes[i]);
+ }
+
+ uint64_t ee = e(ucubes, nucubes);
+ printf("ee = %llu\n", ee);
+
+ assert(6*nucubes >= ee);
+ printf("%llu\n", 6*nucubes - 2*ee);
+}
diff --git a/day19/Makefile b/day19/Makefile
@@ -0,0 +1,20 @@
+CC=clang
+UTILS=../utils/reading.o
+INCLUDES=-I../utils
+
+all: utils common.o uppga uppgb
+
+common.o: common.c common.h
+ $(CC) $(CFLAGS) -c common.c $(INCLUDES)
+
+uppga: $(UTILS) common.o uppga.c
+ $(CC) -Wall -o uppga uppga.c common.o $(UTILS) $(INCLUDES)
+
+uppgb: $(UTILS) common.o uppgb.c
+ $(CC) -Wall -o uppgb uppgb.c common.o $(UTILS) $(INCLUDES)
+
+utils:
+ make -C ../utils
+
+clean:
+ rm -rf common.o uppga uppgb
diff --git a/day19/common.c b/day19/common.c
@@ -0,0 +1,55 @@
+#include "common.h"
+
+void print_blueprint(blueprint* bp)
+{
+ size_t i,j;
+ for(i = 0; i < RTYPES; i++) {
+ printf("(%zu):\t", i);
+ for(j = 0; j < MTYPES; j++) {
+ printf("%llu\t", bp->c[i][j]);
+ }
+ printf("\n");
+ }
+}
+
+blueprint* parse(char** lines, size_t nlines)
+{
+ uint64_t idx;
+ blueprint* bps = malloc(nlines * sizeof(*bps));
+
+ size_t i;
+ for(i = 0; i < nlines; i++) {
+ char* line = lines[i];
+ memset(bps[i].c, 0, RTYPES * MTYPES * sizeof(bps[i].c[0][0]));
+ line = sread_next_u64(&idx, line);
+ line = sread_next_u64(&bps[i].c[ORE][ORE], line);
+ line = sread_next_u64(&bps[i].c[CLA][ORE], line);
+ line = sread_next_u64(&bps[i].c[OBS][ORE], line);
+ line = sread_next_u64(&bps[i].c[OBS][CLA], line);
+ line = sread_next_u64(&bps[i].c[GEO][ORE], line);
+ line = sread_next_u64(&bps[i].c[GEO][OBS], line);
+ }
+
+ return bps;
+}
+
+state start_state()
+{
+ state s;
+
+ memset(s.nmin, 0, MTYPES * sizeof(s.nmin[0]));
+ s.nrob[ORE] = 1;
+ s.nrob[CLA] = 0; s.nrob[OBS] = 0; s.nrob[GEO] = 0;
+
+ return s;
+}
+
+state empty_state()
+{
+ state s;
+
+ memset(s.nmin, 0, MTYPES * sizeof(s.nmin[0]));
+ s.nrob[CLA] = 0; s.nrob[OBS] = 0; s.nrob[GEO] = 0; s.nrob[ORE] = 0;
+
+ return s;
+}
diff --git a/day19/common.h b/day19/common.h
@@ -0,0 +1,38 @@
+#ifndef COMMON_H_
+#define COMMON_H_
+
+#include <stdio.h>
+#include <stdint.h>
+#include <assert.h>
+#include <reading.h>
+
+#define RTYPES 4 // ore, clay, obsidian, geode
+#define MTYPES 4 // ore, clay, obsidian, geode
+#define ORE 0
+#define CLA 1
+#define OBS 2
+#define GEO 3
+#define NOT (255)
+
+#define DONOTHING 0
+#define BUILDORE 1
+#define BUILDCLA 2
+#define BUILDOBS 3
+#define BUILDGEO 4
+#define NOPT 5
+
+typedef struct {
+ uint64_t c[RTYPES][MTYPES];
+} blueprint;
+
+typedef struct {
+ uint64_t nrob[RTYPES];
+ uint64_t nmin[MTYPES];
+} state;
+
+blueprint* parse(char** lines, size_t nlines);
+void print_blueprint(blueprint* bp);
+state start_state();
+state empty_state();
+
+#endif
diff --git a/day19/einput b/day19/einput
@@ -0,0 +1,2 @@
+Blueprint 1: Each ore robot costs 4 ore. Each clay robot costs 2 ore. Each obsidian robot costs 3 ore and 14 clay. Each geode robot costs 2 ore and 7 obsidian.
+Blueprint 2: Each ore robot costs 2 ore. Each clay robot costs 3 ore. Each obsidian robot costs 3 ore and 8 clay. Each geode robot costs 3 ore and 12 obsidian.
diff --git a/day19/input b/day19/input
@@ -0,0 +1,30 @@
+Blueprint 1: Each ore robot costs 4 ore. Each clay robot costs 4 ore. Each obsidian robot costs 4 ore and 14 clay. Each geode robot costs 3 ore and 16 obsidian.
+Blueprint 2: Each ore robot costs 3 ore. Each clay robot costs 3 ore. Each obsidian robot costs 2 ore and 19 clay. Each geode robot costs 2 ore and 12 obsidian.
+Blueprint 3: Each ore robot costs 4 ore. Each clay robot costs 4 ore. Each obsidian robot costs 4 ore and 9 clay. Each geode robot costs 4 ore and 16 obsidian.
+Blueprint 4: Each ore robot costs 4 ore. Each clay robot costs 3 ore. Each obsidian robot costs 4 ore and 20 clay. Each geode robot costs 2 ore and 15 obsidian.
+Blueprint 5: Each ore robot costs 3 ore. Each clay robot costs 4 ore. Each obsidian robot costs 4 ore and 18 clay. Each geode robot costs 2 ore and 11 obsidian.
+Blueprint 6: Each ore robot costs 4 ore. Each clay robot costs 4 ore. Each obsidian robot costs 3 ore and 11 clay. Each geode robot costs 3 ore and 8 obsidian.
+Blueprint 7: Each ore robot costs 2 ore. Each clay robot costs 3 ore. Each obsidian robot costs 2 ore and 17 clay. Each geode robot costs 3 ore and 19 obsidian.
+Blueprint 8: Each ore robot costs 4 ore. Each clay robot costs 3 ore. Each obsidian robot costs 2 ore and 7 clay. Each geode robot costs 3 ore and 8 obsidian.
+Blueprint 9: Each ore robot costs 3 ore. Each clay robot costs 4 ore. Each obsidian robot costs 3 ore and 15 clay. Each geode robot costs 4 ore and 16 obsidian.
+Blueprint 10: Each ore robot costs 3 ore. Each clay robot costs 3 ore. Each obsidian robot costs 2 ore and 7 clay. Each geode robot costs 2 ore and 9 obsidian.
+Blueprint 11: Each ore robot costs 4 ore. Each clay robot costs 4 ore. Each obsidian robot costs 4 ore and 18 clay. Each geode robot costs 4 ore and 9 obsidian.
+Blueprint 12: Each ore robot costs 4 ore. Each clay robot costs 4 ore. Each obsidian robot costs 2 ore and 17 clay. Each geode robot costs 3 ore and 11 obsidian.
+Blueprint 13: Each ore robot costs 4 ore. Each clay robot costs 3 ore. Each obsidian robot costs 3 ore and 17 clay. Each geode robot costs 3 ore and 13 obsidian.
+Blueprint 14: Each ore robot costs 4 ore. Each clay robot costs 3 ore. Each obsidian robot costs 4 ore and 18 clay. Each geode robot costs 4 ore and 11 obsidian.
+Blueprint 15: Each ore robot costs 4 ore. Each clay robot costs 4 ore. Each obsidian robot costs 4 ore and 8 clay. Each geode robot costs 3 ore and 19 obsidian.
+Blueprint 16: Each ore robot costs 4 ore. Each clay robot costs 3 ore. Each obsidian robot costs 2 ore and 13 clay. Each geode robot costs 2 ore and 10 obsidian.
+Blueprint 17: Each ore robot costs 4 ore. Each clay robot costs 4 ore. Each obsidian robot costs 4 ore and 20 clay. Each geode robot costs 2 ore and 8 obsidian.
+Blueprint 18: Each ore robot costs 3 ore. Each clay robot costs 3 ore. Each obsidian robot costs 3 ore and 17 clay. Each geode robot costs 2 ore and 13 obsidian.
+Blueprint 19: Each ore robot costs 4 ore. Each clay robot costs 3 ore. Each obsidian robot costs 2 ore and 13 clay. Each geode robot costs 2 ore and 9 obsidian.
+Blueprint 20: Each ore robot costs 2 ore. Each clay robot costs 3 ore. Each obsidian robot costs 3 ore and 11 clay. Each geode robot costs 2 ore and 16 obsidian.
+Blueprint 21: Each ore robot costs 3 ore. Each clay robot costs 4 ore. Each obsidian robot costs 2 ore and 20 clay. Each geode robot costs 4 ore and 7 obsidian.
+Blueprint 22: Each ore robot costs 2 ore. Each clay robot costs 4 ore. Each obsidian robot costs 3 ore and 19 clay. Each geode robot costs 4 ore and 13 obsidian.
+Blueprint 23: Each ore robot costs 3 ore. Each clay robot costs 3 ore. Each obsidian robot costs 3 ore and 17 clay. Each geode robot costs 4 ore and 8 obsidian.
+Blueprint 24: Each ore robot costs 3 ore. Each clay robot costs 3 ore. Each obsidian robot costs 3 ore and 20 clay. Each geode robot costs 2 ore and 12 obsidian.
+Blueprint 25: Each ore robot costs 2 ore. Each clay robot costs 2 ore. Each obsidian robot costs 2 ore and 17 clay. Each geode robot costs 2 ore and 10 obsidian.
+Blueprint 26: Each ore robot costs 3 ore. Each clay robot costs 3 ore. Each obsidian robot costs 3 ore and 9 clay. Each geode robot costs 3 ore and 7 obsidian.
+Blueprint 27: Each ore robot costs 4 ore. Each clay robot costs 4 ore. Each obsidian robot costs 2 ore and 11 clay. Each geode robot costs 2 ore and 7 obsidian.
+Blueprint 28: Each ore robot costs 4 ore. Each clay robot costs 3 ore. Each obsidian robot costs 3 ore and 14 clay. Each geode robot costs 4 ore and 17 obsidian.
+Blueprint 29: Each ore robot costs 4 ore. Each clay robot costs 4 ore. Each obsidian robot costs 2 ore and 8 clay. Each geode robot costs 3 ore and 9 obsidian.
+Blueprint 30: Each ore robot costs 3 ore. Each clay robot costs 4 ore. Each obsidian robot costs 3 ore and 18 clay. Each geode robot costs 4 ore and 19 obsidian.
diff --git a/day19/uppga.c b/day19/uppga.c
@@ -0,0 +1,171 @@
+#include "common.h"
+
+static inline void printopt(uint8_t* opt, size_t nopt)
+{
+ size_t i;
+ for(i = 0; i < nopt; i++) {
+ printf("%hhu ", opt[i]);
+ }
+ printf("\n");
+}
+
+static inline int affordable(size_t rtype, const blueprint* bp, state* s)
+{
+ size_t i;
+ for(i = 0; i < MTYPES; i++) {
+ if(s->nmin[i] < bp->c[rtype][i]) return 0;
+ }
+ return 1;
+}
+
+static inline int verbose_affordable(size_t rtype, const blueprint* bp, state* s)
+{
+ size_t i;
+ for(i = 0; i < MTYPES; i++) {
+ printf("%llu ?< %llu\n", s->nmin[i], bp->c[rtype][i]);
+ if(s->nmin[i] < bp->c[rtype][i]) return 0;
+ }
+ return 1;
+}
+
+size_t try_opt(uint64_t* score, uint8_t* opt, size_t nopt, const blueprint* bp)
+{
+ size_t i,j;
+ state s = start_state();
+ for(i = 0; i < nopt; i++) {
+ switch(opt[i]) {
+ case DONOTHING:
+ for(j = 0; j < MTYPES; j++) s.nmin[j] += s.nrob[j];
+ break;
+ case BUILDORE:
+ if(affordable(ORE, bp, &s) == 0) return i;
+ for(j = 0; j < MTYPES; j++) {
+ s.nmin[j] += s.nrob[j];
+ s.nmin[j] -= bp->c[ORE][j];
+ }
+ s.nrob[ORE]++;
+ break;
+ case BUILDCLA:
+ if(affordable(CLA, bp, &s) == 0) {
+ return i;
+ }
+ for(j = 0; j < MTYPES; j++) {
+ s.nmin[j] += s.nrob[j];
+ s.nmin[j] -= bp->c[CLA][j];
+ }
+ s.nrob[CLA]++;
+ break;
+ case BUILDOBS:
+ if(affordable(OBS, bp, &s) == 0) return i;
+ for(j = 0; j < MTYPES; j++) {
+ s.nmin[j] += s.nrob[j];
+ s.nmin[j] -= bp->c[OBS][j];
+ }
+ s.nrob[OBS]++;
+ break;
+ case BUILDGEO:
+ if(affordable(GEO, bp, &s) == 0) return i;
+ for(j = 0; j < MTYPES; j++) {
+ s.nmin[j] += s.nrob[j];
+ s.nmin[j] -= bp->c[GEO][j];
+ }
+ s.nrob[GEO]++;
+ break;
+ default:
+ printopt(opt, nopt);
+ assert(1 == 2);
+ }
+ }
+
+ *score = s.nmin[GEO];
+// printf("*score = %llu\n", *score);
+ return i;
+}
+
+static inline int increment(uint8_t* opt, size_t nopt)
+{
+ int i = nopt-1;
+ while(i >= 0 && opt[i] == NOPT-1) {
+ opt[i] = 0;
+ i--;
+ }
+
+ if(i < 0) {
+ return -1;
+ }
+
+ opt[i]++;
+ return(0);
+}
+
+uint64_t wouldbescore(uint8_t* opt, size_t nopt)
+{
+ uint64_t r = 0;
+ uint64_t i;
+ for(i = 0; i < nopt; i++) {
+ if(opt[i] == BUILDGEO) {
+ r += (nopt-1-i);
+ }
+ }
+ return r;
+}
+
+static inline int decrement(uint8_t* opt, size_t nopt, size_t i, uint64_t max)
+{
+ do {
+ int j = i;
+ if(j == nopt) j--;
+
+ while(j >= 0 && opt[j] == 0) j--;
+ if(j < 0) return -1;
+
+ opt[j]--;
+ memset(&opt[j+1], NOPT-1, nopt-j-1);
+ } while(wouldbescore(opt, nopt) <= max);
+
+ return 0;
+}
+
+int main(int argc, char** argv)
+{
+ char** lines;
+ size_t nlines = readlines(&lines, "input");
+ printf("#lines: %lu\n", nlines);
+
+ blueprint* bps = parse(lines, nlines);
+
+ size_t i;
+ for(i = 0; i < nlines; i++) {
+ printf("--- %zu ---\n", i);
+ print_blueprint(&bps[i]);
+ }
+
+ uint64_t tot = 0;
+
+ for(i = 0; i < nlines; i++) {
+ uint8_t opt[24];
+ memset(opt, NOPT-1, 24);
+ size_t sk = 0;
+ uint64_t max = 0;
+ uint64_t tmp = 0;
+ do {
+ // printopt(opt, 24);
+ sk = try_opt(&tmp, opt, 24, &bps[i]);
+ if(tmp > max) {
+ max = tmp;
+ }
+ // printf("sk = %zu\n", sk);
+ // if(sk < 13) {
+ // printopt(opt, 24);
+ // printf("max = %llu\n", max);
+ // printf("sk = %zu\n", sk);
+ // }
+ // for(i = sk+1; i < 24; i++) opt[i] = NOPT-1;
+ } while(decrement(opt, 24, sk, max) != -1);
+
+ printf("(%zu) max = %llu\n", i, max);
+ tot += (i+1)*max;
+ }
+
+ printf("tot = %llu\n", tot);
+}
diff --git a/day19/uppgb.c b/day19/uppgb.c
@@ -0,0 +1,245 @@
+#include "common.h"
+
+#define PRECALCULATE_LEVELS 8
+
+#define MAX(x,y) (x<y?y:x)
+
+static inline void printopt(uint8_t* opt, size_t nopt)
+{
+ size_t i;
+ for(i = 0; i < nopt; i++) {
+ printf("%hhu ", opt[i]);
+ }
+ printf("\n");
+}
+
+static inline int affordable(size_t rtype, const blueprint* bp, state* s)
+{
+ size_t i;
+ for(i = 0; i < MTYPES; i++) {
+ if(s->nmin[i] < bp->c[rtype][i]) return 0;
+ }
+ return 1;
+}
+
+size_t try_opt(uint64_t* score, uint8_t* opt, size_t nopt, const blueprint* bp, uint64_t* pc, size_t npc)
+{
+ size_t i,j;
+ state s = start_state();
+ for(i = 0; i < nopt-PRECALCULATE_LEVELS; i++) {
+ switch(opt[i]) {
+ case DONOTHING:
+ for(j = 0; j < MTYPES; j++) s.nmin[j] += s.nrob[j];
+ break;
+ case BUILDORE:
+ if(affordable(ORE, bp, &s) == 0) return i;
+ for(j = 0; j < MTYPES; j++) {
+ s.nmin[j] += s.nrob[j];
+ s.nmin[j] -= bp->c[ORE][j];
+ }
+ s.nrob[ORE]++;
+ break;
+ case BUILDCLA:
+ if(affordable(CLA, bp, &s) == 0) return i;
+ for(j = 0; j < MTYPES; j++) {
+ s.nmin[j] += s.nrob[j];
+ s.nmin[j] -= bp->c[CLA][j];
+ }
+ s.nrob[CLA]++;
+ break;
+ case BUILDOBS:
+ if(affordable(OBS, bp, &s) == 0) return i;
+ for(j = 0; j < MTYPES; j++) {
+ s.nmin[j] += s.nrob[j];
+ s.nmin[j] -= bp->c[OBS][j];
+ }
+ s.nrob[OBS]++;
+ break;
+ case BUILDGEO:
+ if(affordable(GEO, bp, &s) == 0) return i;
+ for(j = 0; j < MTYPES; j++) {
+ s.nmin[j] += s.nrob[j];
+ s.nmin[j] -= bp->c[GEO][j];
+ }
+ s.nrob[GEO]++;
+ break;
+ default:
+ printopt(opt, nopt);
+ assert(1 == 2);
+ }
+ }
+
+ uint64_t lmax = 0;
+ for(i = 0; i < npc; i++) {
+ if(pc[i*(MTYPES+1) + 0] <= s.nmin[0] && pc[i*(MTYPES+1) + 1] <= s.nmin[1] && pc[i*(MTYPES+1) + 2] <= s.nmin[2]) {
+ lmax = MAX(lmax, pc[i*(MTYPES+1) + 4] + s.nrob[GEO]*PRECALCULATE_LEVELS);
+ }
+ }
+
+ *score = lmax;
+// printf("*score = %llu\n", *score);
+ return nopt-PRECALCULATE_LEVELS-1;
+}
+
+size_t try_min(uint8_t* opt, size_t nopt, const blueprint* bp, size_t type, uint64_t v)
+{
+ size_t i,j;
+ state s = empty_state();
+ for(i = 0; i < MTYPES; i++) s.nmin[i] = 10000000000L;
+ s.nmin[type] = v;
+
+ for(i = 0; i < nopt; i++) {
+ switch(opt[i]) {
+ case DONOTHING:
+ for(j = 0; j < MTYPES; j++) s.nmin[j] += s.nrob[j];
+ break;
+ case BUILDORE:
+ if(affordable(ORE, bp, &s) == 0) return i;
+ for(j = 0; j < MTYPES; j++) {
+ s.nmin[j] += s.nrob[j];
+ s.nmin[j] -= bp->c[ORE][j];
+ }
+ s.nrob[ORE]++;
+ break;
+ case BUILDCLA:
+ if(affordable(CLA, bp, &s) == 0) return i;
+ for(j = 0; j < MTYPES; j++) {
+ s.nmin[j] += s.nrob[j];
+ s.nmin[j] -= bp->c[CLA][j];
+ }
+ s.nrob[CLA]++;
+ break;
+ case BUILDOBS:
+ if(affordable(OBS, bp, &s) == 0) return i;
+ for(j = 0; j < MTYPES; j++) {
+ s.nmin[j] += s.nrob[j];
+ s.nmin[j] -= bp->c[OBS][j];
+ }
+ s.nrob[OBS]++;
+ break;
+ case BUILDGEO:
+ if(affordable(GEO, bp, &s) == 0) return i;
+ for(j = 0; j < MTYPES; j++) {
+ s.nmin[j] += s.nrob[j];
+ s.nmin[j] -= bp->c[GEO][j];
+ }
+ s.nrob[GEO]++;
+ break;
+ default:
+ printopt(opt, nopt);
+ assert(1 == 2);
+ }
+ }
+
+ return i;
+}
+
+
+uint64_t minimum_needed(uint8_t* opt, size_t nopt, const blueprint* bp, size_t type)
+{
+ uint64_t nd = 0;
+ while(try_min(opt, nopt, bp, type, nd) < nopt) {
+ nd++;
+ }
+ return nd;
+}
+
+void precalculate(uint64_t* pc, uint8_t* opt, size_t nopt, const blueprint* bp)
+{
+ size_t i,j;
+
+ for(i = 0; i < MTYPES; i++) {
+ pc[i] = minimum_needed(opt, nopt, bp, i);
+ }
+
+ pc[MTYPES] = 0;
+ for(i = 0; i < nopt; i++) {
+ if(opt[i] == BUILDGEO) {
+ pc[MTYPES] += nopt-1-i;
+ }
+ }
+}
+
+
+uint64_t wouldbescore(uint8_t* opt, size_t nopt)
+{
+ uint64_t r = 0;
+ uint64_t i;
+ for(i = 0; i < nopt; i++) {
+ if(opt[i] == BUILDGEO) {
+ r += (nopt-1-i);
+ }
+ }
+ return r;
+}
+
+static inline int decrement(uint8_t* opt, size_t nopt, size_t i, uint64_t max)
+{
+ do {
+ int j = i;
+ if(j == nopt) j--;
+
+ while(j >= 0 && opt[j] == 0) j--;
+ if(j < 0) return -1;
+
+ opt[j]--;
+ memset(&opt[j+1], NOPT-1, nopt-j-1);
+ } while(wouldbescore(opt, nopt) <= max);
+
+ return 0;
+}
+
+int main(int argc, char** argv)
+{
+ char** lines;
+ size_t nlines = readlines(&lines, "input");
+ printf("#lines: %lu\n", nlines);
+
+ blueprint* bps = parse(lines, nlines);
+
+ size_t i,j;
+ for(i = 0; i < 3; i++) {
+ printf("--- %zu ---\n", i);
+ print_blueprint(&bps[i]);
+ }
+
+ uint64_t tot = 1;
+
+ size_t precalculate_size = 1;
+ for(i = 0; i < PRECALCULATE_LEVELS; i++) precalculate_size *= NOPT;
+ printf("precalculate size = %zu\n", precalculate_size);
+ uint64_t pc[precalculate_size*(MTYPES+1)];
+ for(i = 0; i < precalculate_size; i++) {
+ uint64_t ti = i;
+ uint8_t opt[PRECALCULATE_LEVELS];
+ printf("precalculate\n");
+ for(j = 0; j < PRECALCULATE_LEVELS; j++) {
+ opt[j] = ti % NOPT;
+ ti /= NOPT;
+ }
+ printopt(opt, PRECALCULATE_LEVELS);
+ precalculate(&pc[i*(MTYPES+1)], opt, PRECALCULATE_LEVELS, &bps[0]);
+ printf(">> %llu %llu %llu %llu %llu\n", pc[i*(MTYPES+1)], pc[i*(MTYPES+1)+1], pc[i*(MTYPES+1)+2], pc[i*(MTYPES+1)+3], pc[i*(MTYPES+1)+4]);
+ }
+
+ for(i = 0; i < 3; i++) {
+ uint8_t opt[32];
+ memset(opt, NOPT-1, 32);
+ size_t sk = 0;
+ uint64_t max = 0;
+ uint64_t tmp = 0;
+ do {
+// printopt(opt, 24);
+ sk = try_opt(&tmp, opt, 32, &bps[i], pc, precalculate_size);
+ if(tmp > max) {
+ max = tmp;
+ printf("new max = %llu\n", max);
+ }
+ } while(decrement(opt, 32, sk, max) != -1);
+
+ printf("(%zu) max = %llu\n", i, max);
+ tot *= max;
+ }
+
+ printf("tot = %llu\n", tot);
+}
diff --git a/day2/Makefile b/day2/Makefile
@@ -0,0 +1,17 @@
+CC=clang
+UTILS=../utils/reading.o #../utils/stack_u64.o
+INCLUDES=-I../utils
+
+all: utils uppga uppgb
+
+uppga: $(UTILS) uppga.c
+ $(CC) -Wall -o uppga uppga.c $(UTILS) $(INCLUDES)
+
+uppgb: $(UTILS) uppgb.c
+ $(CC) -Wall -o uppgb uppgb.c $(UTILS) $(INCLUDES)
+
+utils:
+ make -C ../utils
+
+clean:
+ rm -rf uppga uppgb
diff --git a/day2/input b/day2/input
@@ -0,0 +1,2500 @@
+C Y
+C Y
+C Y
+B Z
+C Y
+C Z
+C Y
+C Y
+C Z
+B Y
+C Y
+C Y
+C Y
+C Y
+C Y
+B Z
+A X
+C Y
+B Y
+A X
+C Z
+C Y
+C Y
+C Y
+B Z
+B X
+C Y
+A X
+A X
+A X
+C X
+A X
+C X
+B X
+C Y
+C Y
+A X
+A Y
+C Y
+C Y
+C Y
+C Y
+B X
+A X
+B Y
+C Y
+C Y
+C Z
+A Y
+B X
+B Z
+C Z
+C Z
+A X
+A X
+B X
+C Z
+C X
+A Y
+C X
+C Y
+A X
+A X
+A X
+C Y
+C Z
+C X
+C Y
+A X
+C Y
+C Z
+C Y
+B Z
+C Y
+A X
+C Z
+C Y
+C Y
+C Y
+A X
+A X
+A X
+B X
+A Z
+A X
+C Y
+A Y
+C Y
+B X
+B Z
+B Z
+B Z
+B X
+C X
+A X
+A X
+A X
+C Z
+A Y
+C X
+C Y
+B X
+C Y
+C Y
+A X
+C Y
+C Y
+C Y
+A X
+C Y
+A X
+C Y
+A X
+C Y
+B X
+C Z
+C Y
+A X
+C Z
+B Z
+A Z
+B Z
+C Y
+B X
+A X
+C Y
+B X
+A X
+A X
+A Y
+B Z
+C Y
+A X
+C Y
+C Y
+A X
+C Y
+C Y
+A X
+C Y
+A X
+C X
+B Y
+C Z
+B Z
+C Y
+C Y
+A X
+B X
+A X
+C Y
+C Y
+A X
+B X
+C Y
+B X
+C Z
+B Z
+C Y
+C Y
+C X
+A X
+C Y
+A X
+C Y
+C Y
+C Y
+C Z
+A X
+C Y
+A X
+A X
+B X
+C Y
+C Y
+A X
+B X
+A X
+A X
+A X
+B Z
+C Y
+C Y
+C Y
+A X
+A X
+A Y
+A X
+B X
+B Z
+B Z
+C Y
+B Z
+A X
+B Z
+C Y
+C Y
+C Y
+C Y
+C Y
+A X
+A X
+A Z
+B Y
+C Y
+C Y
+C Y
+A X
+B X
+A X
+A X
+C X
+C Y
+B Z
+C Y
+C Y
+B X
+A X
+A X
+B Z
+C Y
+B Z
+C Y
+C Y
+C Y
+A X
+C Y
+C Y
+A X
+C Z
+B X
+B Z
+C Y
+C X
+C Y
+A X
+C Z
+B Z
+A X
+B X
+C X
+A X
+C Y
+C Y
+B Z
+A Z
+B X
+B X
+A X
+A X
+A X
+C Y
+C Y
+C Z
+A X
+C X
+C Y
+C Y
+A X
+B X
+A Z
+B X
+B X
+C Y
+B X
+B Y
+B Z
+A X
+B X
+B Y
+C X
+A Y
+A Y
+C Y
+A X
+C Y
+B X
+C Z
+C X
+A Z
+C Z
+C Y
+C Y
+B X
+B X
+C Y
+A X
+C Z
+C X
+C Z
+B X
+A X
+A X
+A X
+B Z
+B X
+B Z
+C Y
+C Y
+C Y
+B X
+C Z
+C Y
+A X
+C Y
+C Y
+A X
+A X
+C Y
+C Y
+C Y
+C Y
+C Y
+C Y
+A X
+C Y
+C Y
+C Y
+C Y
+C Z
+C Y
+A X
+A X
+C Y
+A Y
+B Z
+C X
+C Y
+B X
+A Y
+C Y
+C Y
+C Y
+A Y
+B X
+A X
+B Y
+C Y
+C Y
+C Z
+B Z
+C Y
+A X
+A Y
+C Y
+C Y
+C Y
+C Y
+A Y
+B Z
+A X
+C Y
+C X
+C Y
+C Y
+C Y
+C Z
+C Y
+C Y
+C Y
+B Y
+C Y
+B Z
+C Y
+A X
+C Y
+B Z
+C Y
+C Y
+A X
+A X
+B Z
+C Y
+C Y
+C X
+B X
+C Z
+A X
+A X
+B X
+C Y
+B Y
+C Y
+A Y
+C X
+A X
+C X
+C Y
+C Y
+B X
+C Y
+C Y
+B Z
+C Z
+C Y
+C Y
+A X
+C Y
+C Y
+A X
+C Y
+B X
+C Y
+C X
+A X
+C X
+A X
+C Y
+A X
+C Y
+C Y
+C Y
+C Z
+C Z
+B Z
+C Z
+C Y
+B X
+C Z
+C Y
+A X
+A X
+C Y
+C Y
+C Y
+B X
+C X
+A X
+C Y
+A X
+C Y
+A X
+C X
+B X
+A X
+C Y
+C Y
+B X
+A X
+A X
+C Z
+C X
+A X
+A X
+B X
+A Z
+A X
+C X
+C Y
+A X
+B X
+C Y
+A X
+C Y
+C Y
+B X
+C Y
+C Y
+A X
+C Z
+C Y
+B X
+C X
+B X
+C Y
+C Y
+B X
+B Z
+B Z
+C Y
+C Y
+B X
+C Y
+B Z
+C X
+A Z
+A X
+A X
+C Y
+C Y
+C Y
+C Y
+C Y
+C Y
+B Z
+B X
+C Y
+B Z
+C Y
+A X
+A X
+C Y
+A X
+A X
+C Y
+C Y
+A Z
+C Y
+A X
+C Y
+C Y
+C Y
+C Y
+C Y
+A X
+B Z
+A X
+C X
+B X
+C Y
+B Z
+C Y
+B X
+B X
+C Y
+C Y
+C X
+C Y
+C Y
+A X
+C X
+A X
+C Y
+B X
+A X
+B Y
+A X
+B X
+C Y
+C X
+C Y
+C Y
+A X
+C Y
+C Y
+A X
+C Z
+B X
+A X
+C Y
+A X
+A X
+C Y
+A X
+C X
+B X
+A X
+A X
+B X
+A X
+C X
+A Z
+B Z
+C Y
+C Y
+A X
+C Y
+C Y
+B X
+A X
+C Y
+A Y
+B X
+C Y
+C Y
+A X
+C X
+C Y
+C Y
+A X
+C X
+B Y
+C Y
+C X
+C Y
+C Y
+C Y
+C Z
+A X
+C Y
+C X
+C Y
+A Z
+A X
+C Y
+B X
+C Y
+B Z
+A X
+C Y
+C Y
+A X
+A X
+C Y
+B X
+A Z
+B Z
+C Y
+C Z
+A X
+A X
+A X
+B Z
+A Z
+C Y
+C Y
+C Y
+C Y
+C Y
+B Z
+B X
+A Y
+B X
+C Y
+A X
+C X
+A X
+A X
+C Y
+A X
+C Y
+C Y
+A X
+C Y
+C Y
+C Y
+C Y
+B Z
+B X
+C Y
+C Y
+A X
+C Y
+B X
+C Y
+C Z
+C Y
+B X
+C Y
+C Y
+B Z
+A Y
+C Z
+B X
+C Z
+C Y
+A Y
+A X
+A X
+C Y
+B X
+A X
+A Y
+C X
+A Y
+C Y
+C Y
+C X
+C Y
+C Z
+C X
+B X
+C Y
+C Z
+A X
+C Y
+A X
+C Y
+C Y
+A Z
+A X
+C Z
+B X
+C X
+B X
+B Y
+C Y
+C Y
+B Z
+C Y
+B X
+B Z
+C Y
+C Y
+C Y
+B X
+B Z
+C Y
+B Z
+B X
+A Z
+A X
+C Y
+C Y
+B X
+B Z
+A X
+C Y
+C Y
+C Z
+C Y
+C Y
+C Y
+B Z
+C Y
+C Y
+B Z
+C Y
+C Y
+C Y
+C Y
+C Y
+C Z
+C X
+C Y
+C Y
+C Z
+C Y
+B Z
+C Z
+A X
+C Y
+B X
+C Y
+A X
+C Y
+A X
+C Y
+C Y
+C Y
+C Y
+B X
+C Y
+C Y
+A X
+C Z
+A X
+A X
+C Y
+B X
+C Y
+C Y
+C Y
+A X
+A X
+C Y
+B X
+B X
+C Y
+B X
+C Y
+C Z
+C Z
+A X
+C Y
+C X
+C X
+C Z
+C X
+C Y
+A X
+C Y
+C Y
+C Y
+A X
+A X
+C X
+C Y
+C Y
+A X
+A Z
+C Z
+C Y
+C Z
+A X
+C Z
+C Y
+C Y
+A X
+C Y
+B Z
+B X
+A X
+C Y
+C Z
+A X
+C X
+C Y
+C Y
+B X
+C Y
+C Y
+C Y
+B X
+B Z
+B Z
+A X
+A X
+C Z
+C Y
+C Y
+C Y
+B Z
+A X
+C Y
+C Y
+C Z
+B X
+A X
+C Y
+B Z
+C Y
+A X
+B Z
+A X
+A X
+A X
+A Y
+C Z
+A X
+A X
+B X
+A X
+C Y
+C Y
+A X
+C Z
+A X
+A X
+C Y
+A X
+B X
+A X
+C Y
+A X
+C Y
+C Z
+C Y
+C Y
+C Z
+C Y
+C X
+A Y
+A Z
+B Z
+B X
+C Y
+C X
+B X
+A X
+A Y
+A X
+A X
+C Y
+B X
+A X
+C Y
+B Z
+C Y
+C Y
+C Y
+C Y
+A X
+B X
+C Y
+A X
+A Y
+C Y
+B X
+C Y
+B Y
+C Y
+B X
+C Y
+C Y
+C Y
+C X
+A X
+B Z
+C Y
+C Y
+B X
+C Y
+C Y
+B Z
+A X
+C Y
+C Y
+A Y
+C Y
+B Z
+C Y
+C Y
+A X
+A X
+A X
+C Z
+B X
+C X
+A X
+C Y
+C Z
+A X
+B X
+A X
+B X
+C Z
+C X
+C Y
+B X
+C Z
+C Z
+C Y
+A X
+C Y
+C X
+B X
+C Y
+C Y
+A Y
+C Y
+C Z
+C Y
+C Y
+B Z
+C Y
+C Y
+C Z
+B X
+B X
+C Y
+B Z
+C Y
+A X
+C Z
+C Z
+A X
+A X
+A X
+A X
+C Y
+C Y
+B X
+C Y
+B X
+A X
+C Y
+C Y
+C Y
+A X
+B Z
+A X
+C Y
+C Y
+C Y
+A X
+C Y
+C Y
+B Z
+B Z
+A X
+C Y
+C Y
+B Y
+C Y
+C Z
+A X
+C Y
+C Z
+A X
+A X
+C X
+C Y
+A X
+A X
+C Y
+C Y
+A X
+A X
+A X
+C Y
+C Y
+B Z
+C Y
+B X
+A X
+A X
+C Z
+C Y
+A X
+C Y
+A X
+C Y
+C Z
+C Z
+C Y
+A X
+C Y
+C X
+C Y
+B X
+C Y
+A X
+B Z
+C Z
+C Z
+C Y
+B X
+C Y
+C Y
+C Y
+A X
+A X
+A X
+C Y
+B Z
+A X
+C Y
+C Y
+C Y
+A X
+C Y
+C Y
+A X
+C Y
+C X
+A X
+C Y
+C Y
+C Z
+C Z
+C Y
+C Y
+C Y
+C Y
+C Z
+B X
+C Y
+C Y
+A Y
+C Z
+B Z
+C Y
+C Y
+A X
+B X
+A X
+C Z
+C Y
+B Y
+C Y
+A Z
+C Y
+B Z
+B Z
+C Y
+A X
+C Y
+B Z
+B X
+B Z
+A X
+B X
+A X
+C X
+A X
+B X
+A Y
+B Z
+C Z
+C Y
+A X
+A X
+C Y
+C X
+A Y
+C Z
+C Y
+C Y
+A X
+A Z
+A Y
+C Y
+B X
+A X
+C Y
+C Z
+B X
+A X
+B X
+C Y
+C Z
+B X
+C Y
+C Y
+C Y
+A X
+C Y
+C Y
+C Y
+C Y
+C Y
+C X
+C X
+C Y
+C Y
+C Y
+A Y
+C Y
+A X
+C Z
+C Z
+C Y
+C Y
+C Y
+B X
+A Z
+C Y
+C Z
+C Y
+A X
+C Y
+A Y
+A X
+C Y
+C Y
+A Z
+B X
+C Z
+B X
+C Y
+C Z
+C Y
+C Y
+C Y
+C Y
+C Y
+C Y
+B Z
+C Z
+A X
+A Z
+C Z
+B Y
+B Z
+C Z
+C Z
+A X
+B X
+B X
+C Y
+C Y
+A X
+A X
+C Y
+C Y
+A X
+C Y
+A Z
+C Z
+C Y
+A X
+C Y
+C Y
+A X
+A X
+C Y
+C Y
+B Z
+B X
+C Y
+C Y
+A Z
+C X
+C Y
+B X
+C Z
+A X
+C Z
+C Y
+A X
+B Z
+C Y
+C Y
+B X
+A Z
+C Y
+B Z
+A X
+C Y
+C X
+A X
+C Y
+C Y
+C Z
+A X
+B X
+B Z
+C X
+C Y
+C Y
+A X
+C Y
+B X
+A X
+A X
+C Y
+A X
+A X
+A X
+A Y
+A Z
+A X
+A X
+C Y
+C X
+C Z
+C Y
+C Y
+C X
+C Y
+A X
+A X
+A Y
+C Z
+C Z
+C X
+B Z
+C Y
+A X
+C Y
+B Z
+A X
+C Z
+C Y
+A Y
+A X
+B Z
+A X
+C Y
+B X
+B Z
+A X
+B X
+B X
+C Y
+C X
+C Y
+C Y
+C Y
+C Z
+B Z
+C Y
+C Y
+C Z
+C Y
+C Y
+C Y
+A X
+A X
+C Z
+A X
+C Y
+C Y
+B Z
+A X
+A Z
+C Z
+C Y
+C Y
+C Y
+C Z
+C Y
+C Y
+C Y
+C Y
+B Z
+C Y
+C Z
+C Z
+C Y
+B Z
+A X
+C Y
+B X
+C X
+A X
+A X
+B X
+C Y
+C Y
+C Y
+C X
+B Z
+C Y
+A X
+C Z
+A X
+A Z
+C Z
+C Y
+C Y
+C Y
+C X
+A X
+C Y
+A Y
+C Y
+B Z
+A Y
+C Y
+A X
+C Y
+A X
+C Y
+C Y
+C Y
+B X
+C Y
+C Y
+A X
+C Y
+C Y
+C Y
+C Y
+A X
+B Z
+B X
+A X
+C Y
+C X
+C Y
+B X
+C X
+C Y
+C Y
+A X
+A X
+C Y
+C Z
+A X
+C Y
+A X
+C Y
+C X
+C Y
+B Y
+A Y
+C Y
+C Z
+A X
+B X
+C Y
+B X
+A X
+C Y
+B X
+A Z
+C Y
+B X
+C Y
+A X
+B X
+C Z
+A X
+B X
+C Y
+A X
+A X
+B X
+C Y
+A X
+C Z
+A X
+C Y
+A X
+B X
+C Y
+C Y
+C Y
+C Y
+C Y
+A X
+A Z
+C Y
+A X
+C Y
+C Y
+B X
+C Y
+A X
+C Y
+C Z
+C Y
+C Y
+A X
+A X
+A X
+C Y
+C Y
+C Y
+C Z
+C Y
+C Y
+C Y
+C Y
+C Z
+C X
+C Y
+C Z
+C Y
+C Y
+C Y
+C Y
+A X
+B X
+C Z
+A X
+C Z
+C Y
+C Y
+C Y
+C Y
+A Z
+B X
+A X
+B Z
+C Y
+C Y
+C X
+C Y
+B Y
+B X
+C X
+C X
+A X
+C Y
+C Y
+A X
+A X
+B Z
+C Y
+C Y
+C Y
+A X
+A X
+C Y
+C X
+C Y
+A X
+C X
+B Y
+C X
+C Y
+C Y
+A X
+B Z
+C Y
+B X
+A X
+B Y
+C Y
+C Y
+C Y
+A X
+A X
+C Y
+C Y
+A X
+C Y
+C X
+C Y
+B Z
+C Y
+C Y
+A Z
+C Y
+C Z
+C Z
+C X
+C Y
+C Y
+C Y
+C Y
+C Y
+C Y
+C Y
+A X
+C Y
+B X
+C Z
+C Y
+C X
+C X
+A Y
+C Y
+A X
+A X
+B Z
+C Y
+C Y
+A X
+A Z
+B X
+C Y
+C Y
+B Y
+C Y
+C Y
+C Y
+C Y
+A X
+C Z
+C Y
+C Z
+A Y
+C Y
+A X
+A X
+C Y
+C Y
+C Y
+B X
+B X
+B Z
+A X
+C Z
+C X
+A X
+C Y
+C Y
+C Y
+C Y
+C X
+C X
+B Z
+A Z
+C Y
+B Z
+C Z
+A X
+C Z
+A X
+C Y
+A X
+C Y
+A X
+A X
+C Y
+A X
+C Y
+C Y
+C Y
+B X
+C Y
+C X
+C Y
+C Z
+C Y
+A X
+C Y
+C Y
+C Y
+B Z
+C Y
+A X
+B X
+C Y
+C Y
+B Y
+C Z
+C Z
+C Y
+A X
+C Y
+C Y
+A X
+C X
+B X
+A X
+A X
+C Y
+C Y
+C Y
+C Y
+C Y
+A X
+A X
+C Y
+C Y
+B X
+C Y
+C Y
+C X
+C Y
+C Z
+B Z
+C Z
+C Y
+B X
+C Y
+C X
+A X
+C Y
+B X
+B X
+A X
+C Y
+A X
+C Y
+A X
+C X
+C Y
+C Y
+B X
+C Y
+C Y
+C Y
+C Y
+C X
+B Z
+A X
+A X
+C X
+C X
+C Y
+A X
+C Z
+C Y
+C Z
+A X
+A X
+C X
+C X
+C Z
+B X
+A X
+C Y
+B X
+C Y
+B X
+C Y
+C Y
+C Y
+C Y
+C Y
+C Y
+C Y
+B Z
+C Z
+A Z
+B X
+C Z
+C Z
+C Y
+B Z
+C Y
+A X
+C Y
+C Y
+C Y
+B Z
+C Y
+A X
+B Z
+B Z
+C Z
+A Y
+C Z
+A X
+C Y
+C Z
+C X
+A X
+B X
+C Y
+C Y
+C Y
+A X
+A Y
+C Y
+C Y
+C Y
+A X
+C Y
+B X
+A X
+A X
+B X
+C Z
+C Y
+B Z
+C Y
+A Y
+B X
+C Z
+B Z
+B Z
+C X
+B Z
+C X
+A X
+C Y
+B X
+C Y
+A X
+C Y
+A X
+C Y
+C Y
+C Z
+C Y
+A X
+B X
+C Y
+A X
+B X
+C Y
+C X
+C Y
+C Y
+A X
+C Y
+A X
+B X
+C Y
+B X
+B X
+C Y
+A X
+C X
+C X
+B X
+B Z
+C Y
+B X
+C Y
+C Y
+B X
+A X
+C Z
+A Y
+C Y
+C Z
+A X
+A X
+C Y
+A X
+B Z
+A X
+A X
+C Y
+B Z
+B Z
+C Y
+B X
+B X
+A X
+A X
+C Y
+C Z
+C X
+C Y
+A X
+B Y
+A X
+C Y
+B Z
+B X
+A Y
+A X
+C Y
+A X
+A X
+C Y
+C Y
+C Y
+C Z
+C Z
+A X
+B Z
+A Z
+A X
+C Y
+B Z
+C X
+C Y
+C Z
+C Z
+B X
+B Z
+B X
+C Y
+B X
+B X
+C Y
+C Y
+C X
+B X
+A X
+C Z
+A X
+C Y
+A X
+A X
+C Y
+B X
+B X
+A X
+B X
+B Y
+C Y
+A X
+A X
+A X
+B X
+C Y
+B Z
+C Z
+B X
+C Y
+C Z
+A X
+C Y
+C Y
+B Z
+C Z
+C Y
+C Z
+A X
+B X
+A Z
+C Z
+B Z
+A X
+A X
+B X
+A X
+C Y
+C Y
+C Y
+C Y
+A X
+C Y
+C Z
+C Z
+B X
+A X
+A X
+B X
+B X
+B X
+C Y
+C Y
+A X
+C Y
+B Z
+C Y
+C Y
+B Z
+A Z
+C X
+C Z
+B X
+C Y
+A X
+A X
+C Y
+C Y
+C Y
+C Z
+A X
+C X
+B X
+C Y
+A X
+C Y
+C X
+A X
+A Z
+C X
+C Z
+A X
+C Y
+C Y
+C Y
+A X
+A X
+A X
+B Z
+C Z
+C Z
+A X
+B X
+B X
+A X
+C Y
+B X
+C Z
+B Y
+A X
+C Z
+A Z
+C Y
+C Y
+A X
+A X
+B X
+C Y
+B Z
+C Y
+A X
+A X
+A X
+C Y
+A X
+C Y
+C Y
+C Y
+B X
+A X
+B Z
+C Y
+A X
+A X
+A Z
+A X
+A Y
+A X
+C Y
+C Y
+B X
+A Y
+C Y
+C Y
+A X
+A Y
+C Y
+B X
+C Y
+C Y
+C Y
+C Y
+C Y
+B X
+C Y
+C Y
+C X
+C Y
+A X
+B Z
+B X
+B X
+C Y
+A X
+C Y
+C X
+C X
+C Y
+C Y
+C Z
+C Y
+A X
+C Y
+A X
+C Y
+A X
+A X
+C Y
+C Y
+B X
+B Y
+C Y
+A X
+B Z
+C Y
+C Y
+C Y
+A X
+A X
+A X
+C Z
+C Y
+C Z
+C Y
+C Y
+C Y
+A X
+C Y
+C Y
+C Y
+B X
+A X
+C Y
+C Y
+C Z
+A X
+A X
+C Y
+C Y
+B X
+A Z
+C Y
+C Y
+C Y
+C Z
+C Y
+A Y
+C Y
+C Y
+C Y
+B Z
+C Y
+B X
+C Y
+C Y
+B Z
+A X
+C X
+C Y
+A Y
+A X
+C X
+C Y
+C Y
+A Y
+B X
+A X
+A Y
+C Y
+C Y
+C Y
+A X
+A X
+A X
+B X
+A X
+C Y
+C Y
+C Z
+C Y
+C Y
+C Y
+C Y
+C Y
+C Z
+C Y
+B Z
+A X
+B X
+A X
+C Y
+A X
+C Z
+B X
+B X
+B Z
+C Y
+C Y
+C Z
+C Y
+C Z
+B Z
+C Z
+A X
+C Y
+B Z
+B Z
+C Y
+A Y
+B Z
+B Y
+C Z
+C Y
+C Y
+B X
+A X
+C Y
+B Y
+A X
+A X
+C Y
+C X
+C Y
+B Z
+A X
+C Y
+A X
+C Z
+C Y
+B Z
+C Y
+B Y
+A X
+C Y
+A X
+B X
+A Y
+C Y
+C Y
+B X
+C Y
+C Z
+A X
+C Y
+B X
+C Y
+B Z
+C Y
+B X
+B Z
+C X
+C Y
+C Z
+C Y
+C Y
+C Y
+C Y
+C Y
+C Y
+A X
+A X
+A X
+A X
+A X
+A X
+C Y
+A X
+B Z
+B X
+C Y
+C Y
+C Y
+C X
+A X
+C X
+A X
+C Y
+B X
+B X
+C Z
+C Y
+C Y
+A Y
+C Y
+C X
+A X
+B Z
+C Y
+C Z
+A X
+B Z
+B Z
+A X
+A X
+C Z
+C Y
+B Z
+A X
+B X
+A Y
+B Z
+A X
+C Z
+C X
+C Y
+C X
+C Y
+C Y
+A X
+C Y
+C Y
+C Z
+A X
+B Z
+C Y
+C Z
+A Y
+C Y
+C Y
+A Z
+C Y
+C Y
+C Z
+C Y
+C Y
+C Z
+C Z
+C Y
+A Y
+B X
+B Z
+A Y
+A X
+B X
+C Y
+C Y
+C Y
+A X
+C Y
+A X
+B X
+C Y
+C Y
+B X
+C Y
+A X
+A Z
+B Z
+B Z
+A X
+A Y
+A X
+A X
+C Y
+C Z
+A X
+B X
+C Y
+B X
+C Y
+C Z
+B X
+C Y
+C Z
+A X
+C Y
+C Y
+C Y
+B X
+C Z
+A X
+A X
+C Y
+C X
+A X
+C Y
+C Y
+C Z
+A X
+B X
+A X
+C Y
+C Y
+C Y
+C Y
+B X
+B Z
+C Z
+A X
+A X
+A X
+A X
+A X
+A X
+C Y
+C Y
+C Y
+B Z
+C Z
+C Y
+C Y
+C Y
+C Z
+A X
+C Y
+B X
+A X
+A X
+C Z
+B X
+C Z
+B Z
+C Y
+A X
+A X
+C Y
+C Y
+C Y
+C Y
+C Y
+A X
+C Y
+A X
+C Y
+A X
+C Y
+C Y
+C Y
+C Y
+A X
+A X
+C Y
+C Y
+C Y
+B X
+A X
+C Y
+C Y
+C X
+A X
+A X
+C X
+C Y
+C Y
+C Y
+C Y
+C Y
+C Y
+C Y
+C Y
+C X
+C Y
+B X
+B Z
+C Z
+C Y
+C Y
+C Y
+C Y
+B X
+C Y
+C Y
+C Y
+C Y
+B Z
+A X
+C Y
+A X
+C Y
+A X
+C Y
+C Y
+A X
+C Y
+C Y
+A X
+A Z
+A X
+C Z
+C Z
+C Y
+B X
+C X
+C Y
+C Y
+C Y
+B Z
+B Y
+A X
+B Z
+A X
+A X
+A X
+B X
+B X
+A X
+C Y
+C Z
+A X
+C Y
+C Y
+C Y
+A X
+C Y
+C Y
+C Y
+A X
+A Y
+A X
+C Y
+C Y
+C Z
+C Y
+C Y
+C X
+A X
+C Y
+A X
+A X
+A X
+C Y
+C Y
+C X
+A X
+A X
+B Z
+A X
+C Y
+A X
+B Z
+C Z
+A X
+C Y
+A X
+B X
+C Y
+C Z
+A X
+A X
+C Y
+A X
+A X
+C Z
+B X
+A X
+A X
+B X
+C Y
+B X
+C Y
+A X
+B X
+C Y
+C Y
+A X
+B X
+C Y
+C Y
+B X
+A X
+B X
+A Y
+C Y
+C Y
+C Y
+A X
+C Y
+A X
+B Z
+B X
+C Y
+B Z
+A X
+C Z
+C X
+C Y
+C Y
+A X
+A X
+A X
+C Y
+A X
+B Z
+B Z
+C Y
+B X
+C X
+C X
+B X
+C Y
+C Y
+C Y
+C Y
+B Z
+C Y
+C Y
+C Y
+A X
+C Y
+A Y
+B X
+C Y
+C Y
+B X
+A X
+B Z
+C Z
+A X
+C Y
+C Y
+C Z
+C Y
+C Y
+C Y
+C Y
+B Y
+C Z
+C Y
+C X
+A X
+A Z
+C Y
+A X
+A Y
+B X
+C X
+B X
+B X
+B X
+C X
+C Y
+C Y
+C Y
+A Z
+A X
+C Y
+C X
+A Y
+A X
diff --git a/day2/uppga.c b/day2/uppga.c
@@ -0,0 +1,43 @@
+#include <stdio.h>
+#include <stdint.h>
+#include <assert.h>
+#include <reading.h>
+#include <string.h>
+#include <stdlib.h>
+
+static uint64_t nscore[256];
+
+static inline uint64_t line_score(char* line)
+{
+ char* strs[9] = {"A X\n", "A Y\n", "A Z\n",
+ "B X\n", "B Y\n", "B Z\n",
+ "C X\n", "C Y\n", "C Z\n"};
+ uint64_t scores[9] = {3, 6, 0,
+ 0, 3, 6,
+ 6, 0, 3};
+ size_t i;
+
+ for(i = 0; i < 9; i++) {
+ if(strncmp(strs[i], line, 3) == 0)
+ return nscore[(int) line[2]] + scores[i];
+ }
+
+ // unreachable
+ perror("Non-indexed string error.");
+ exit(1);
+}
+
+int main(int argc, char** argv)
+{
+ char** lines;
+ size_t nlines = readlines(&lines, "input");
+
+ nscore['X'] = 1; nscore['Y'] = 2; nscore['Z'] = 3;
+
+ uint64_t score = 0;
+ size_t i;
+ for(i = 0; i < nlines; i++) {
+ score += line_score(lines[i]);
+ }
+ printf("score: %llu\n", score);
+}
diff --git a/day2/uppgb.c b/day2/uppgb.c
@@ -0,0 +1,37 @@
+#include <stdio.h>
+#include <stdint.h>
+#include <assert.h>
+#include <reading.h>
+#include <string.h>
+
+static inline uint64_t choose(char opp, char ldw)
+{
+ int oppi = (int) (opp - 'A');
+ int ldwi = (int) (ldw - 'X');
+ uint64_t sc[9] = {3, 1, 2, 1, 2, 3, 2, 3, 1};
+
+ assert(oppi < 3);
+ assert(0 <= oppi);
+ assert(ldwi < 3);
+ assert(0 <= ldwi);
+
+ return sc[oppi + 3*ldwi] + (3*ldwi);
+}
+
+static inline uint64_t line_score(char* line)
+{
+ return choose(line[0], line[2]);
+}
+
+int main(int argc, char** argv)
+{
+ char** lines;
+ size_t nlines = readlines(&lines, "input");
+
+ uint64_t score = 0;
+ size_t i;
+ for(i = 0; i < nlines; i++) {
+ score += line_score(lines[i]);
+ }
+ printf("score: %llu\n", score);
+}
diff --git a/day20/Makefile b/day20/Makefile
@@ -0,0 +1,20 @@
+CC=clang
+UTILS=../utils/reading.o
+INCLUDES=-I../utils
+
+all: utils common.o uppga uppgb
+
+common.o: common.c common.h
+ $(CC) $(CFLAGS) -c common.c $(INCLUDES)
+
+uppga: $(UTILS) common.o uppga.c
+ $(CC) -Wall -o uppga uppga.c common.o $(UTILS) $(INCLUDES)
+
+uppgb: $(UTILS) common.o uppgb.c
+ $(CC) -Wall -o uppgb uppgb.c common.o $(UTILS) $(INCLUDES)
+
+utils:
+ make -C ../utils
+
+clean:
+ rm -rf common.o uppga uppgb
diff --git a/day20/common.c b/day20/common.c
@@ -0,0 +1,16 @@
+#include "common.h"
+
+void parse(int64_t* d, char** lines, size_t nlines)
+{
+ uint64_t tmp;
+ int64_t tmpl;
+ size_t i;
+ for(i = 0; i < nlines; i++) {
+ sread_next_u64(&tmp, lines[i]);
+ tmpl = (int64_t) tmp;
+ if(lines[i][0] == '-') {
+ tmpl = -tmpl;
+ }
+ d[i] = tmpl;
+ }
+}
diff --git a/day20/common.h b/day20/common.h
@@ -0,0 +1,11 @@
+#ifndef COMMON_H_
+#define COMMON_H_
+
+#include <stdio.h>
+#include <stdint.h>
+#include <assert.h>
+#include <reading.h>
+
+void parse(int64_t* v, char** lines, size_t nlines);
+
+#endif
diff --git a/day20/einput b/day20/einput
@@ -0,0 +1,7 @@
+1
+2
+-3
+3
+-2
+0
+4
diff --git a/day20/input b/day20/input
@@ -0,0 +1,5000 @@
+-2312
+5492
+793
+-773
+5453
+-2076
+-1728
+-7702
+4318
+8316
+-3366
+-3814
+9182
+-673
+-8201
+7847
+9691
+4044
+802
+-8114
+8944
+-2438
+-3460
+-6923
+-4847
+-7341
+2063
+-9848
+6702
+2560
+6058
+-7669
+7315
+-6427
+5165
+3147
+-1320
+4789
+6296
+-806
+1185
+-1445
+-982
+2759
+-8506
+-5959
+5683
+-6623
+-8571
+-5834
+-9022
+8729
+-7420
+-9812
+-9162
+-240
+7302
+2221
+-4352
+-4248
+5177
+9037
+-6880
+-2117
+9569
+-1037
+726
+2866
+-4587
+3384
+998
+9665
+3982
+3169
+4547
+612
+2857
+-2601
+-982
+-4267
+-740
+2817
+-818
+-8005
+-3697
+497
+-8039
+-116
+8438
+-8460
+2609
+709
+3590
+1323
+2202
+-1246
+-736
+-3992
+7811
+127
+-2609
+8314
+-5668
+-6449
+-6512
+3972
+-5998
+-7462
+4542
+-6350
+8424
+5046
+-3554
+6481
+-4521
+1307
+-172
+-7391
+79
+-179
+-7320
+9750
+-5916
+8531
+5522
+5133
+-1506
+4151
+-2793
+5448
+-2267
+998
+-6216
+3894
+-1297
+7112
+8486
+-6030
+-1815
+-1451
+4165
+828
+8678
+-1751
+-9528
+5056
+-9702
+9288
+8683
+-1924
+-6171
+-7050
+-9968
+-3909
+-9834
+-8325
+-2528
+-2247
+-1075
+6684
+6038
+-6309
+-3562
+2333
+3593
+-18
+-9857
+-4318
+6923
+-5266
+1408
+-7781
+2037
+-519
+4085
+7054
+-4111
+2817
+-5375
+870
+-8252
+4142
+3500
+-9371
+-2040
+-7381
+6216
+7143
+-6814
+673
+3104
+-1693
+6050
+-2416
+7112
+4114
+5367
+4566
+2560
+4361
+4131
+4337
+7876
+-3000
+-8724
+-2088
+6785
+-5326
+-7107
+3739
+-302
+9519
+-5331
+8759
+6867
+-9267
+4816
+-749
+-1980
+1830
+9715
+1634
+-6922
+-288
+4436
+63
+-156
+1185
+-5004
+-9093
+-8661
+8447
+233
+-854
+3154
+-5589
+-5490
+2321
+-1006
+3688
+6313
+4704
+6598
+430
+-7073
+-6571
+-3768
+6203
+8453
+8735
+-4070
+8059
+-4734
+-1827
+1330
+586
+-8858
+1938
+1366
+6031
+3744
+-7191
+8032
+3586
+-3196
+-460
+3032
+2387
+450
+1391
+-3905
+-2774
+6690
+-9103
+8220
+-6594
+8834
+-3559
+-9337
+2199
+-9026
+2904
+-8552
+499
+7727
+6519
+-17
+-3625
+-302
+4611
+9129
+9756
+6869
+-2262
+-4677
+3533
+19
+5877
+5224
+3783
+5992
+-2218
+-5097
+3956
+9335
+-5586
+-9441
+3252
+-4307
+-1111
+6509
+-116
+-4926
+-7394
+1270
+-1773
+6658
+3317
+-8704
+-3692
+6482
+2451
+7241
+-350
+-5042
+-9182
+2602
+9752
+-8475
+-5018
+-267
+-9360
+599
+917
+5210
+4388
+909
+-1063
+8311
+1831
+8235
+-9129
+-7420
+-284
+-1940
+4079
+-7284
+-4893
+4913
+-8602
+-59
+6105
+-4934
+1196
+-6947
+-1508
+-8961
+2112
+-6739
+-8401
+9750
+-3697
+85
+2240
+-5882
+-1900
+3783
+5747
+4388
+5225
+6858
+-3799
+6119
+8592
+-3328
+4716
+-6391
+-7721
+4813
+3223
+6303
+8780
+4400
+-7964
+8810
+8247
+8776
+-5738
+-2655
+-2036
+9906
+-6834
+92
+6695
+1740
+29
+-9758
+-7016
+-8170
+-7780
+4243
+-3391
+2989
+-7678
+2154
+-4515
+4475
+8011
+-3785
+-3518
+5532
+8387
+806
+-9546
+655
+804
+-5420
+4138
+8495
+8975
+-2559
+8202
+8268
+-6923
+1671
+-9892
+6337
+6205
+6024
+6038
+-3289
+4626
+4356
+-3104
+7633
+9404
+-3630
+-4041
+106
+-4493
+3651
+6983
+-5958
+819
+6105
+1910
+4645
+-1293
+-8747
+8655
+-6928
+9025
+1984
+-9959
+-9290
+-7834
+3588
+2967
+3048
+4730
+-8653
+-4434
+6105
+8028
+-4909
+-7865
+-6832
+-1267
+8129
+4131
+-9615
+-7137
+3956
+464
+-588
+5260
+2181
+-3581
+649
+8992
+-6427
+-3292
+-5641
+-8274
+-2283
+-3455
+1417
+7054
+3937
+-1797
+-615
+-2526
+6210
+6222
+-6007
+-3764
+-1743
+-3123
+9495
+8269
+3675
+1085
+-1859
+8578
+-1240
+-4734
+1196
+1332
+-3507
+-6268
+3380
+-6530
+3264
+-4958
+-7533
+8869
+2666
+-6780
+7739
+-4128
+-8229
+9624
+-8005
+-1897
+-9773
+8000
+-419
+269
+5048
+-5962
+4319
+6834
+-9624
+-5247
+-2683
+-9050
+-5335
+5244
+-3052
+929
+-3922
+-4806
+-7085
+4186
+-5127
+7790
+527
+-222
+4043
+9900
+4630
+5056
+-9425
+-2369
+-1442
+-7949
+5228
+7449
+3945
+726
+-1722
+-3439
+-1037
+-4998
+-5130
+5158
+-227
+-8075
+3917
+5228
+9382
+-7582
+787
+-2895
+-7385
+9750
+-8872
+-1263
+5877
+4398
+9200
+4061
+8059
+9960
+5756
+-3241
+-2283
+9568
+-5852
+-3630
+-2336
+-3596
+4649
+-7203
+4473
+-8025
+-9991
+-8721
+1307
+-5487
+4632
+1799
+2468
+2834
+2571
+-3894
+7319
+8466
+-7831
+-7428
+5475
+6296
+9191
+6193
+-843
+8566
+9398
+7317
+-3984
+-1886
+-5012
+4014
+-3554
+6002
+-5254
+8412
+-4059
+7761
+-7363
+9025
+-1960
+1905
+-304
+-2877
+7707
+-3120
+8969
+-545
+-9237
+885
+3830
+7085
+-8779
+9198
+4123
+517
+480
+-6380
+9713
+-2029
+-947
+-5205
+-9126
+-4653
+5254
+3153
+2067
+7872
+-3545
+1864
+9068
+4516
+6440
+-9167
+4281
+4859
+-6318
+-3155
+8699
+-5310
+-38
+-4889
+-1805
+-9405
+-1235
+3285
+1579
+1265
+-850
+259
+1513
+-1490
+7916
+-9000
+-7515
+2756
+831
+2387
+-6922
+-6299
+8992
+3336
+4473
+1728
+1366
+-2893
+-8891
+7818
+-3140
+2972
+1088
+2718
+9495
+64
+7527
+8638
+-8670
+6740
+-2971
+1849
+5365
+7997
+2941
+5528
+8065
+6973
+-5858
+1355
+6359
+-7757
+-3968
+-1985
+-3194
+1425
+-6928
+4616
+-1912
+-5892
+-9337
+-4007
+-1299
+5042
+3825
+-5517
+5056
+-9180
+-4646
+-843
+6038
+7750
+-7705
+1294
+8809
+6888
+-1634
+-8823
+-2995
+-7983
+-7333
+-7315
+2240
+-4881
+497
+-4026
+-6921
+714
+4513
+-2134
+-4600
+-4863
+7388
+-6344
+-8589
+9381
+-7674
+-9967
+-9237
+2679
+-8598
+-6741
+7739
+-7720
+-1899
+-5265
+-5665
+-2580
+-8820
+8550
+9121
+-1218
+8832
+-1776
+-4814
+-1570
+-7969
+-6529
+8232
+-4867
+-638
+-1263
+3918
+8720
+-6378
+-7501
+3894
+-663
+3894
+1264
+555
+-1139
+9538
+-7029
+4909
+1751
+-6800
+7761
+6810
+6708
+-3571
+7994
+9707
+5187
+-3084
+5458
+-5274
+-8246
+5730
+2425
+7931
+-6800
+-6008
+-2705
+-5151
+-6268
+-1054
+6176
+-6809
+7683
+-4342
+-7797
+-6430
+4127
+-3148
+7294
+6188
+8729
+3463
+3375
+5648
+788
+3996
+7650
+8952
+-7078
+-8155
+-6166
+-3726
+-2742
+3845
+1103
+-5164
+6507
+-2219
+4131
+9421
+-8277
+7068
+-8046
+833
+-684
+-6160
+-8604
+-6384
+-2081
+940
+3239
+1962
+3502
+3576
+-3320
+-335
+5644
+-200
+823
+8320
+-7803
+6209
+-7565
+1042
+769
+-5705
+7494
+-4419
+5726
+5198
+-6879
+3377
+-6890
+-6072
+-3633
+-100
+-8584
+2961
+-5839
+8191
+9055
+-5330
+-3082
+-8589
+-7126
+-9861
+7624
+8486
+-272
+-1092
+-3047
+9349
+6014
+8554
+-2986
+1425
+-2615
+-1855
+5442
+-8509
+9775
+-8855
+6313
+-8060
+-102
+8809
+2374
+5400
+7789
+-6100
+-1473
+-916
+-6715
+-1828
+-5649
+6314
+-1946
+-895
+8774
+5894
+-8284
+3825
+8737
+500
+-1468
+2542
+-7925
+7775
+9221
+-2916
+-9878
+-6427
+9800
+-468
+-8699
+9798
+9424
+8910
+8582
+-8806
+-4157
+8620
+-5136
+-952
+-9019
+-6947
+-601
+-5789
+-9535
+6028
+-8930
+8466
+-5689
+3254
+-4709
+4394
+2281
+3362
+2813
+-5808
+3420
+6002
+-9398
+9653
+5728
+9204
+-4846
+-7691
+-8087
+6772
+-451
+-2286
+2826
+5945
+-7702
+9713
+5468
+4660
+672
+-1854
+-3970
+1905
+3685
+6425
+5102
+-7462
+1913
+6360
+-8581
+6604
+9384
+9117
+2574
+4436
+-6263
+8516
+-2059
+6378
+-6492
+4242
+-9681
+-6126
+436
+5520
+9528
+3885
+1227
+-8501
+1230
+-6933
+-5230
+-9432
+-1313
+-2136
+-1379
+1439
+-2864
+2839
+3340
+-226
+-4206
+9121
+-9572
+8567
+-8298
+7244
+9526
+-8506
+-7922
+-901
+-523
+-6310
+2811
+2324
+-7384
+8812
+-916
+2580
+-2966
+9885
+-3400
+-6277
+-5818
+-663
+-7179
+7344
+6022
+2865
+-676
+1375
+8622
+1965
+-9990
+-4255
+5796
+-3903
+8008
+-78
+-4997
+-460
+8437
+-6563
+-5517
+-1827
+6257
+-5413
+-6169
+6869
+5890
+9791
+5425
+-7310
+7249
+1175
+4417
+-527
+4115
+-834
+9427
+6924
+731
+-1537
+-4632
+-1218
+3677
+-8488
+-946
+-5430
+580
+4976
+5132
+8448
+-3109
+4014
+-4493
+-5671
+6507
+3688
+-9214
+-2641
+3508
+7581
+-9640
+-2308
+3598
+4940
+-3843
+-7364
+-1693
+2367
+2589
+9435
+-7914
+-5655
+7388
+379
+6022
+1899
+2607
+-6226
+8992
+1231
+-8751
+-4158
+1888
+-2145
+-5874
+-5713
+-9526
+1060
+-3324
+-834
+8534
+-1807
+9906
+1217
+9946
+1892
+8556
+6182
+-2868
+7988
+-1555
+-9400
+2212
+1311
+6349
+-9405
+3703
+9120
+5284
+4672
+-8397
+-7984
+-5319
+-7955
+-1570
+6475
+-2479
+266
+-3865
+3550
+1313
+5476
+3052
+9659
+2696
+-8760
+6568
+-5512
+-4938
+7835
+-6933
+1821
+5033
+3504
+7070
+-2016
+1147
+-2652
+-4622
+-4126
+-9118
+6462
+1563
+3285
+8275
+-8593
+-4833
+-1318
+-6620
+-2818
+4893
+5076
+356
+-4435
+6210
+9037
+6929
+-6950
+-6710
+-1735
+3541
+-5278
+-1451
+8176
+885
+-9108
+-2591
+-1165
+660
+2387
+1829
+3490
+3048
+7244
+-6423
+3571
+-5055
+-1272
+-84
+6388
+2320
+-4569
+2382
+5900
+-7482
+7915
+5668
+9089
+9963
+-6007
+6337
+-5863
+-6139
+-1803
+-1863
+8283
+-8654
+-7952
+-6938
+-5541
+484
+-8487
+-3356
+-2433
+-9859
+-1960
+7112
+8010
+-7200
+9261
+5926
+-2610
+-7854
+6988
+-4258
+-9209
+-3029
+6578
+-1779
+-6575
+9899
+4561
+7564
+-6399
+-7750
+-1276
+-1242
+9793
+-1650
+400
+-4830
+-9533
+6806
+2157
+-5517
+-9506
+-1925
+-519
+5650
+-8327
+4683
+788
+7457
+-4476
+6695
+-4255
+7292
+760
+-8423
+1603
+-4258
+6097
+-567
+5582
+1323
+-3113
+9303
+-3025
+-8242
+6039
+8692
+2309
+-5558
+-916
+-7193
+5906
+-9774
+8231
+491
+8404
+-9325
+-9261
+4790
+-5419
+4394
+-2174
+-8130
+6327
+7412
+6495
+-5814
+6741
+-6791
+9147
+-828
+-619
+1841
+1120
+-9057
+123
+430
+-3828
+6360
+5831
+-5059
+-7599
+-6946
+-9640
+4733
+2834
+524
+-5316
+8832
+-1566
+-5477
+-4370
+1991
+6716
+8755
+-3455
+7821
+-90
+-8899
+-7101
+1785
+-2925
+1299
+9571
+-8319
+8304
+-1690
+-6509
+-5792
+4825
+6801
+-1638
+-4783
+4784
+-5668
+4170
+7228
+-2326
+9793
+-4041
+-9295
+7134
+-4845
+528
+3199
+-1632
+3372
+-5856
+-2582
+7039
+-7775
+-6401
+5747
+-6986
+2608
+5091
+-8261
+-8431
+-1591
+-6165
+4835
+6467
+312
+9873
+-6425
+-9224
+1633
+8856
+5961
+-4968
+8583
+-268
+-6396
+6791
+8721
+-2141
+-2248
+-9119
+4338
+-9103
+-3693
+-706
+-975
+3854
+-1136
+8930
+6511
+-445
+917
+-1024
+-3782
+8406
+2624
+-9544
+-4830
+-5255
+-9561
+-2948
+-1011
+9056
+8291
+3320
+-5316
+1148
+-8261
+1330
+-2145
+-9226
+-1257
+1905
+-3227
+-6728
+-6107
+7278
+-9645
+879
+-3758
+4980
+-7956
+6640
+4053
+-7842
+-6749
+363
+-6904
+-3055
+-768
+7220
+-5118
+6750
+7737
+-3422
+6328
+4844
+-2690
+1113
+-7072
+3528
+-4331
+-5164
+-4056
+-4821
+-982
+2502
+7885
+-8553
+9740
+5105
+-5824
+2693
+5459
+2462
+-3001
+9783
+6766
+-9286
+-6516
+2307
+-908
+-1325
+904
+-84
+-1526
+278
+7384
+655
+-4468
+1264
+4952
+-5002
+5700
+-9261
+-966
+-438
+-466
+-3756
+-9867
+-2088
+4125
+1930
+9294
+-1243
+-5604
+-2422
+-2385
+9296
+9426
+6767
+-6467
+8846
+-1315
+7568
+4391
+85
+-2167
+-9427
+-6613
+-2586
+2008
+4540
+9421
+-7046
+8466
+-2939
+6699
+-8174
+3384
+-2700
+3199
+-4011
+-8991
+-1129
+2216
+8273
+7977
+-3962
+-2334
+-2747
+7765
+1765
+-4471
+1863
+-6768
+-7752
+-5945
+8593
+-2225
+2550
+9650
+8842
+465
+6133
+-952
+7479
+5645
+4520
+-8873
+4429
+9857
+-4567
+-124
+6193
+-7916
+-1299
+1811
+-5195
+8974
+-8604
+6126
+-7579
+-7828
+8882
+-5002
+-6102
+3891
+-589
+-5697
+7519
+-1335
+-311
+-6777
+5704
+1962
+-4950
+9814
+5400
+610
+-2093
+7898
+-6492
+-1165
+-1063
+1658
+-7184
+-3384
+5101
+4733
+1231
+9255
+-712
+4122
+4402
+5443
+3877
+7541
+4473
+-3633
+-9959
+9260
+9177
+1788
+-5986
+-5165
+8969
+6031
+741
+-7417
+7002
+6992
+-4374
+-8995
+2832
+2250
+2221
+-2791
+-2287
+-9125
+-1692
+4930
+-443
+4349
+-8602
+3553
+9117
+8304
+209
+6650
+745
+1058
+-3994
+-7437
+8476
+-7390
+-6864
+2467
+1798
+-292
+-6487
+2954
+-3029
+1192
+-1955
+4256
+5615
+4335
+7948
+-7963
+-831
+8499
+-1778
+5063
+2069
+610
+6032
+1447
+6898
+2154
+-6397
+7996
+-7809
+-3279
+6789
+7245
+8794
+-7078
+-1434
+-3953
+-3029
+7262
+-4640
+4742
+-1063
+7790
+2320
+-1721
+6128
+-4219
+7482
+3385
+-2949
+-6830
+-1522
+-3530
+-9002
+-4798
+7347
+7847
+-8651
+9432
+1612
+-5705
+-9216
+-5384
+-2064
+7739
+7113
+6250
+7192
+2927
+7901
+-2990
+-736
+3892
+-2641
+7870
+5061
+4500
+278
+3569
+5059
+-8721
+9991
+1219
+-1289
+-6273
+-8618
+-9085
+6235
+-7551
+-2850
+-7188
+-9828
+2381
+-1298
+-5671
+-2114
+-3312
+-5589
+-394
+8484
+-4008
+3378
+-9841
+-3357
+6888
+4421
+-5959
+-2719
+-5031
+1945
+5058
+1732
+8774
+-9907
+9240
+3189
+-8103
+8526
+-7588
+6113
+-9506
+1096
+-7420
+5688
+-3131
+-8204
+4321
+1860
+-3439
+5902
+5484
+-7310
+7544
+-9184
+3579
+-8311
+9400
+-2046
+3613
+2834
+-3828
+4483
+-3687
+2474
+9175
+5682
+2134
+8178
+4669
+-8999
+4089
+3745
+6187
+-3255
+4496
+-4086
+-5667
+-4719
+-9530
+57
+-5557
+-1809
+4683
+-6874
+9649
+238
+-5274
+2548
+-1610
+2406
+6760
+3829
+-6658
+-7076
+-8907
+-8252
+4473
+-6559
+9751
+9946
+-1815
+-4719
+6440
+-3154
+-4584
+-8861
+5988
+-6730
+5975
+-6449
+3127
+6406
+7501
+-4504
+-5805
+-8832
+3352
+-3961
+-3453
+9800
+-8757
+-9250
+5575
+-1894
+-1130
+2529
+2060
+819
+8152
+-6329
+-6967
+-451
+-3261
+1670
+4090
+-6879
+-638
+-5435
+2187
+3891
+5504
+4337
+3137
+-9570
+2350
+9955
+5628
+8522
+-165
+-7442
+-5330
+8494
+-8458
+5667
+-3922
+-5440
+-7066
+7265
+-8704
+490
+-5609
+-768
+1537
+-7702
+5884
+-1198
+4784
+1935
+-9959
+3985
+-1213
+-518
+-7078
+-9683
+-4973
+-2189
+9598
+-4616
+7220
+3335
+8211
+7294
+-5295
+4813
+-3329
+2697
+5383
+-2611
+4052
+-9056
+5442
+-5822
+8230
+2860
+2797
+2893
+1320
+7805
+9598
+-6575
+1307
+-3383
+7434
+7853
+-6166
+2096
+-2921
+-8558
+2689
+-2719
+9225
+-2812
+-7176
+6243
+-7995
+-7186
+8770
+-953
+-3986
+9430
+-9280
+5951
+254
+9268
+1664
+6491
+8121
+-6876
+2805
+-265
+8954
+5634
+-4938
+-6880
+7449
+-9839
+6036
+4772
+-5325
+3763
+-3455
+-8766
+1458
+-605
+-6746
+7846
+-8180
+8340
+9269
+7054
+-5084
+-98
+9491
+2893
+-8571
+3179
+2972
+-9473
+1502
+9398
+-621
+1562
+-1657
+1670
+9896
+7344
+-9187
+-2085
+-2781
+342
+-9159
+6214
+802
+-2429
+-7600
+4489
+-7485
+-4674
+2709
+-446
+-8240
+9394
+8159
+-4058
+5910
+-1281
+9760
+-6626
+5440
+4697
+-5100
+6509
+4256
+-4904
+244
+1154
+-7067
+-4251
+-4759
+5617
+-8546
+8747
+5770
+-4909
+1447
+612
+-8622
+2866
+-2947
+-1800
+-8985
+-3800
+-6839
+-1256
+-8119
+6427
+8187
+-4392
+-2980
+-7103
+-2337
+5830
+-3644
+4052
+4591
+-2181
+6072
+6905
+5783
+-3905
+-9064
+-3083
+4615
+-3437
+1133
+3153
+-1922
+-4065
+-8069
+-6436
+7889
+4440
+-7021
+-638
+-5127
+8977
+2839
+6777
+7054
+-5443
+3666
+-9640
+-1863
+-2244
+-8397
+6744
+9748
+5783
+7727
+-6548
+7052
+-4846
+-7240
+8565
+-6165
+-9038
+2975
+-6850
+-8567
+-7842
+4297
+-474
+-5606
+-4723
+-203
+-4902
+6313
+92
+-784
+-5997
+-2915
+-6920
+-8873
+-5885
+85
+-3035
+8715
+3763
+-4255
+6210
+5214
+3284
+-5662
+-585
+2621
+3569
+8826
+-9532
+-9323
+1430
+159
+-1831
+-373
+-5837
+-6559
+2129
+-6731
+2932
+-9463
+7930
+-5585
+9567
+2601
+-6215
+-4804
+9927
+-8269
+-9660
+6692
+7859
+855
+-3444
+-545
+-1924
+3776
+6273
+7774
+400
+5129
+6999
+-8423
+-243
+8011
+7236
+-555
+9279
+2752
+4931
+4728
+8293
+6421
+4497
+3458
+-8929
+9792
+-1333
+-4216
+1379
+-6254
+8851
+9346
+8174
+5712
+1899
+4115
+4437
+-7151
+6917
+9104
+-5838
+-1454
+779
+8637
+7494
+-7076
+7365
+3931
+-2719
+8075
+-5323
+-7745
+9761
+-5792
+5746
+5575
+9704
+-9334
+-8704
+9364
+-4196
+4914
+3552
+-6741
+-7272
+3199
+6427
+-3097
+-2195
+-3535
+-5885
+-7161
+-4290
+-5912
+5957
+9337
+-6472
+9037
+5573
+2384
+2474
+5497
+5889
+-9663
+-5332
+5913
+-48
+3398
+6039
+-1025
+4567
+-1689
+-7643
+8403
+6422
+2666
+4681
+7571
+9306
+-4140
+8668
+5961
+1728
+9600
+4567
+-9947
+7947
+2311
+7683
+4036
+-9118
+-1440
+7701
+-718
+7252
+-5748
+8074
+9077
+1430
+309
+7223
+7241
+6924
+-1726
+2580
+323
+9592
+-147
+9734
+-6509
+-2141
+9899
+8912
+-9095
+-1534
+-1722
+-6731
+-4674
+-5668
+9543
+2181
+-5971
+-4285
+-5435
+8785
+6022
+3483
+3442
+-4311
+-9718
+491
+-234
+-6505
+-2233
+1054
+1843
+-8170
+3725
+9367
+-9708
+2884
+575
+1466
+-4904
+-7163
+-6509
+-9898
+-1035
+4218
+-3782
+-7972
+4094
+-4022
+7344
+3528
+6745
+-8677
+-564
+599
+-1588
+-638
+-2547
+7384
+-3223
+-8978
+-3131
+2367
+38
+4294
+2227
+-4687
+-8416
+-7749
+-901
+5156
+5381
+7208
+9451
+-1072
+-6165
+4274
+-9330
+-5692
+-976
+8507
+-4214
+3267
+-693
+4016
+-4859
+4131
+2624
+-2195
+-5747
+-3433
+-5309
+4909
+-1789
+1970
+1113
+6654
+9294
+580
+2701
+-3072
+-1058
+-450
+-3553
+8842
+-6902
+5849
+-8210
+3129
+-4568
+7319
+9289
+1953
+-2772
+3176
+7831
+-5215
+-7078
+-269
+-9613
+-5990
+140
+-3349
+-1868
+-6378
+7029
+3786
+9495
+4946
+-3908
+5746
+7246
+6543
+3375
+-6525
+3179
+4829
+-5690
+-4458
+-5067
+3563
+-9505
+8886
+-6046
+8975
+-9892
+4232
+-3386
+6748
+5560
+-5068
+-4307
+8256
+-4803
+6559
+-726
+7262
+3603
+-6032
+-1753
+1072
+-3515
+1160
+-4265
+8809
+7319
+-2341
+-4621
+-5593
+4672
+-7252
+7876
+-2824
+-2708
+151
+6484
+2609
+2708
+-9044
+-7454
+4473
+-3075
+-5664
+1659
+9212
+-8951
+-3382
+8762
+7569
+-2142
+-3045
+-7361
+110
+6810
+1104
+-373
+-4500
+-9051
+-3242
+2221
+5025
+-4297
+-6710
+7853
+-6452
+7998
+-9213
+-7520
+-6727
+5334
+1096
+678
+-4395
+7679
+-4022
+6257
+-3939
+9591
+8016
+-4342
+8010
+5402
+1423
+8834
+6389
+9001
+5102
+3868
+-7905
+8265
+-2083
+6772
+-8806
+-1136
+-5612
+-5127
+-7981
+-5655
+480
+-3419
+368
+-2090
+5293
+7052
+4686
+3386
+-708
+3991
+-684
+-2381
+4228
+-9954
+-9993
+4285
+-6467
+6787
+-3366
+-4653
+-3731
+-4257
+-1246
+3925
+2320
+1536
+-3196
+-1374
+-5465
+-7690
+-716
+1929
+859
+3442
+3500
+-6460
+7761
+5628
+-4119
+4069
+9037
+105
+9498
+8235
+-2437
+3472
+-5420
+-6518
+3972
+-7627
+-8503
+6050
+4393
+-8440
+1986
+2187
+-5589
+2686
+3888
+-9356
+-543
+2822
+5302
+-7034
+-7778
+9334
+-5462
+-267
+-6891
+-2707
+7407
+8805
+7388
+6184
+3346
+6847
+-5971
+-417
+-3326
+-1592
+5544
+-6800
+7034
+-5441
+-9441
+-6987
+1815
+5783
+6926
+-4314
+-9892
+-1500
+2904
+-1946
+-9074
+-7659
+-4333
+-3553
+-916
+3237
+-7151
+-6030
+-8337
+418
+-9384
+1192
+2558
+7496
+-7729
+8273
+9305
+3827
+7519
+2133
+1879
+1001
+258
+-3963
+119
+4186
+5239
+-7204
+7704
+9534
+-8682
+-4772
+-7978
+5929
+6107
+506
+1760
+5782
+5895
+-3687
+-78
+-7125
+-534
+-4774
+6218
+9585
+8200
+-5340
+-9302
+3559
+8846
+3552
+1671
+-5477
+-9118
+7790
+-3757
+8365
+7394
+8465
+7245
+3956
+-592
+2205
+-5882
+6476
+-5732
+-6477
+6713
+4709
+4714
+7356
+-1080
+-983
+-9975
+-8190
+-7574
+828
+-6316
+3515
+451
+1098
+5400
+238
+480
+-5998
+-4376
+1974
+9915
+-7151
+-128
+-5130
+-4423
+8491
+3122
+7110
+-9930
+-7341
+-1882
+-3439
+8231
+1407
+-6444
+-4772
+-8872
+-2853
+8031
+6313
+-9629
+4347
+-5487
+-1799
+-1225
+8026
+6920
+4427
+3467
+-2158
+909
+8977
+-5982
+3825
+-718
+7908
+4464
+-1220
+693
+8293
+-8873
+5243
+3511
+8604
+-5990
+-4492
+-4091
+5688
+1240
+664
+3712
+3048
+-9240
+-5267
+247
+-2010
+5327
+-2030
+8030
+-5240
+-3302
+480
+4323
+-8323
+-4590
+2769
+8506
+-1556
+-1827
+-6216
+-4879
+-156
+-1447
+5967
+-1840
+-5838
+7409
+8444
+-5008
+-7949
+6069
+284
+-9103
+-8612
+797
+5615
+-2375
+-9861
+2789
+5978
+-59
+4821
+7116
+4054
+2816
+-8543
+-1099
+9062
+5718
+9635
+6353
+-3312
+1227
+2144
+5770
+9824
+-2918
+-7958
+4640
+1036
+7693
+-951
+5293
+-4364
+6883
+-4395
+7615
+1097
+8269
+-9907
+5813
+-5369
+4001
+-4965
+-4567
+8939
+-145
+3003
+-6977
+8293
+1299
+9247
+-2988
+7170
+6638
+431
+-8887
+3279
+-946
+-4148
+6039
+2067
+-282
+-71
+8031
+425
+-6890
+878
+-1532
+820
+-8918
+-5336
+1989
+-7692
+-1915
+-684
+7818
+254
+7294
+7865
+4192
+-6782
+-6593
+-9534
+-6708
+7805
+-6548
+-5502
+-6471
+-3453
+-736
+-60
+450
+-2995
+4978
+3135
+1408
+7241
+-4262
+-1352
+1200
+5332
+-3276
+-8900
+3210
+317
+1659
+-8895
+-68
+1728
+7241
+-5572
+8605
+2181
+7379
+5184
+3720
+-7081
+-906
+8125
+-4793
+-387
+-9056
+-6572
+5129
+9554
+-206
+3680
+-1500
+8300
+9128
+-6752
+1001
+8338
+-2893
+3567
+314
+4180
+-7983
+5575
+4745
+-302
+5910
+5877
+9130
+-4624
+490
+-6477
+508
+-2262
+5063
+9995
+5492
+-8571
+-2076
+-7245
+7531
+-4395
+5668
+-8525
+9198
+5457
+5282
+-9627
+-8023
+-4275
+-6099
+-9415
+5771
+3678
+-6865
+417
+-1681
+-9044
+8269
+610
+-7461
+-7621
+-4022
+5225
+-4529
+9988
+-2569
+9810
+1996
+1283
+9364
+-7877
+6015
+-7076
+-352
+-9273
+-3114
+-9044
+8524
+1634
+6057
+-5687
+1947
+4940
+2461
+-5043
+-4571
+-5986
+4391
+-9838
+6912
+-5398
+-318
+-5024
+1465
+3817
+8656
+4389
+-4034
+4052
+7988
+-8598
+9693
+7317
+4356
+783
+-5211
+-1854
+3219
+-3521
+-6814
+-4709
+6055
+1394
+-10
+3384
+403
+9590
+4927
+1524
+1098
+-9975
+9585
+6222
+499
+148
+-5770
+-4801
+-8148
+-7928
+3359
+-7612
+3226
+-4709
+1527
+-2568
+-5296
+3739
+-9003
+-806
+1984
+2059
+7955
+7818
+5364
+793
+6822
+3946
+151
+-9630
+9630
+2324
+662
+3333
+-8448
+6754
+437
+-2029
+-4255
+6568
+8500
+-3622
+810
+9004
+8653
+1164
+-8115
+-1858
+-2642
+611
+-7246
+-8085
+-6299
+-4599
+5226
+-4384
+-1024
+-4938
+-1431
+-6083
+2496
+6922
+4660
+1912
+-8991
+-8297
+-6895
+-9607
+1696
+6072
+-3326
+-5078
+1355
+7649
+1118
+-3072
+-5738
+-4741
+3892
+-647
+-6566
+-2195
+3768
+-1397
+-4046
+-3118
+-8531
+4909
+-6367
+5292
+-3083
+151
+-591
+3367
+-8325
+6439
+-6505
+-7330
+2456
+8503
+-5579
+5852
+-7902
+-667
+-3492
+-6341
+7979
+8307
+-29
+-8265
+-2614
+-4590
+-7186
+-3785
+-3744
+3300
+5701
+3678
+-2580
+527
+-120
+-7978
+-5319
+7443
+-5475
+-1506
+-7191
+-9281
+-7356
+-2628
+7251
+-1997
+3924
+-5266
+-8651
+9217
+5305
+9111
+-2939
+7519
+-8554
+-5596
+-3718
+-9826
+5615
+-3270
+7568
+-901
+-7112
+-7598
+7930
+-1075
+2380
+-9192
+-9157
+-9773
+-9061
+-4003
+2896
+4243
+7496
+3191
+4741
+9293
+-8230
+9568
+5013
+-7046
+-9040
+-3302
+2822
+-3767
+-6571
+2286
+9978
+-5369
+-3987
+321
+-9841
+-9334
+-4786
+1332
+2154
+350
+-1841
+-397
+238
+-1815
+-8499
+-4930
+8627
+3968
+1148
+-2153
+-4273
+279
+119
+-3390
+-4077
+-7011
+-2595
+140
+7960
+-6277
+6223
+4957
+-3939
+6988
+-5028
+-9901
+1603
+-5892
+-775
+-9280
+3171
+-1522
+5108
+4891
+3685
+4661
+-7643
+-552
+8337
+-5832
+8644
+3003
+-9386
+6223
+8612
+787
+-3622
+9641
+3003
+-9341
+-7802
+9602
+-3767
+-8598
+7949
+723
+-4998
+-6073
+-5646
+4880
+-2046
+7167
+1100
+6188
+-2993
+5320
+-4615
+-5113
+2264
+6658
+1364
+8910
+-8873
+-9623
+-1256
+5575
+7718
+-8815
+-8254
+4073
+2488
+-7385
+-9406
+-1283
+-2330
+439
+-2260
+-3460
+-1411
+1800
+-1868
+8900
+2905
+-7883
+-8724
+-6531
+7876
+6834
+9389
+8247
+-1522
+-2524
+7145
+-8339
+5056
+7401
+-8273
+3776
+-6665
+8064
+8148
+2243
+-7815
+1924
+-3212
+-6806
+4323
+904
+-4695
+9209
+-6907
+1291
+1529
+-4561
+-7375
+-1211
+2558
+-2141
+5043
+6989
+-5202
+-2176
+-5916
+2884
+-6187
+-3430
+-2237
+-1213
+5977
+-6300
+3245
+8531
+-4257
+-9381
+802
+-78
+-4860
+7008
+-4722
+1110
+9955
+3907
+1910
+8930
+-2195
+-3785
+5610
+5135
+3491
+7948
+3403
+-338
+1694
+-8961
+-3504
+-8033
+-9811
+6823
+6748
+8362
+-5673
+5260
+5914
+-809
+4578
+-2719
+2755
+-42
+1258
+1601
+767
+-347
+7552
+4349
+5549
+-9012
+-4066
+-3864
+6657
+-4258
+7015
+5905
+3870
+-7769
+3896
+3956
+1996
+8506
+-1060
+-5314
+6853
+-7459
+-5834
+-9179
+9981
+-5594
+3705
+-799
+1788
+6874
+-4405
+2345
+-5994
+-9878
+425
+3474
+323
+-4786
+-7819
+-5507
+-8999
+1683
+-5020
+-8423
+-9015
+-1037
+909
+-1304
+9494
+-4815
+7341
+2170
+4724
+-9026
+-5085
+-4041
+-4282
+8747
+2902
+5352
+3576
+-8931
+1536
+-8880
+376
+6995
+1446
+2811
+4310
+9204
+-6879
+-9143
+-78
+-2334
+5345
+3317
+-9839
+-8793
+-833
+4699
+-2420
+-3265
+-8066
+3885
+-7660
+-7341
+13
+8711
+-2510
+-8420
+-3856
+9808
+1921
+-2644
+-6183
+-6786
+7739
+4036
+-5541
+-9182
+4427
+7008
+-4938
+-228
+-3505
+7569
+1683
+5763
+-728
+2236
+-943
+5351
+-8467
+101
+-7916
+-9075
+1983
+-8025
+5674
+9528
+-2621
+6098
+8770
+4600
+6519
+-8724
+-3047
+6462
+5293
+-9484
+8464
+106
+-2368
+-2455
+9659
+-3489
+8326
+7198
+5617
+-1513
+-2437
+3380
+7835
+-517
+-4778
+-6895
+-7224
+3200
+2324
+4704
+-7740
+4029
+-4071
+723
+3889
+-5732
+-1338
+-7655
+9258
+-4148
+-8233
+4544
+804
+9968
+-6880
+5772
+-6405
+3637
+2752
+-5041
+6317
+1884
+-2007
+-2908
+-8629
+-5600
+9867
+-421
+-6378
+-5810
+7684
+3456
+-7571
+-9877
+-5828
+-2763
+9288
+491
+8692
+-5648
+4501
+-4434
+-569
+-3339
+1118
+-961
+516
+5412
+-9462
+8219
+2882
+7319
+-4920
+-7027
+-3528
+1097
+4900
+8282
+4135
+4658
+8008
+-8843
+9656
+7044
+-3992
+-5136
+-3968
+-4330
+-3265
+9567
+-2542
+497
+-5318
+-18
+-6056
+-3651
+9104
+-6477
+-2719
+5268
+5570
+703
+8809
+-4719
+7949
+-2175
+3009
+6939
+9709
+4264
+-7758
+5746
+-9630
+4579
+4909
+3571
+8199
+8743
+6349
+-5785
+1889
+1893
+4256
+-2987
+4089
+2112
+-4104
+1333
+-3443
+-7134
+77
+4963
+4908
+-9050
+-7842
+7564
+-9229
+-6378
+2975
+-7823
+6418
+269
+522
+-6300
+6174
+7005
+-5378
+-7981
+-9356
+-9072
+2569
+8999
+-6390
+-5935
+-5057
+2360
+-8700
+-3348
+-90
+3191
+1789
+-8654
+7768
+-6404
+-8873
+-6821
+4562
+1085
+4429
+-9579
+-7957
+7294
+-427
+-7934
+2968
+1508
+-6905
+-5993
+-1688
+-8417
+1780
+9540
+-4450
+1536
+5184
+8111
+9877
+3466
+2279
+-5254
+-6850
+6936
+-5318
+-7691
+-6390
+5400
+6108
+8351
+-9275
+-6229
+-5441
+-9950
+-5475
+1480
+5686
+-8082
+-128
+9648
+5982
+9904
+1974
+-4077
+-9764
+-4525
+-5834
+6285
+6559
+-6806
+1577
+-7459
+7276
+839
+9633
+-7440
+9191
+4709
+-7421
+-5043
+-2217
+-5419
+8031
+9873
+4658
+-2961
+-3223
+3226
+2189
+6134
+1939
+-4390
+-1323
+-240
+-8850
+6122
+7885
+1991
+2271
+6261
+-8012
+-6213
+-3041
+4125
+6966
+-5882
+-6915
+-5345
+-3925
+709
+978
+6321
+7461
+2433
+7315
+-4675
+-656
+-8237
+-7938
+-340
+-5314
+-4571
+1699
+1525
+-6613
+-2064
+4562
+6285
+4192
+-173
+7710
+-7469
+-3785
+-2248
+4375
+8399
+-833
+-427
+5295
+-7999
+7236
+-5517
+-5989
+-6017
+965
+-3883
+-7937
+7707
+-1892
+-2085
+8111
+-7516
+9569
+8043
+532
+-1663
+8001
+-1162
+9170
+-7059
+-8235
+-6865
+-9272
+6119
+-3662
+3870
+1339
+6589
+-4588
+-4322
+1549
+-9520
+6393
+7102
+621
+9389
+-4111
+5768
+-3700
+3018
+-5154
+-8234
+8634
+-2928
+-6425
+1709
+3657
+-9595
+-8276
+-844
+-4257
+770
+-4722
+-3718
+5091
+-8724
+7964
+5288
+8921
+-4719
+527
+-6946
+5186
+3598
+5259
+4359
+4147
+9435
+5992
+-6929
+1058
+-9752
+-4909
+4756
+-1902
+837
+6293
+6326
+7847
+-8692
+-9016
+8851
+8842
+8743
+1989
+-3991
+-6232
+-9571
+425
+2666
+9009
+4745
+-1197
+2866
+-2479
+8453
+-6310
+9490
+-1892
+-1313
+-2941
+-5062
+-4521
+-4219
+6337
+-2011
+7727
+-205
+2094
+2780
+6791
+3547
+-9513
+7262
+-9526
+-1306
+8873
+342
+6483
+376
+1897
+9068
+-5133
+1822
+-6727
+-3922
+-2009
+3515
+4391
+-3029
+2778
+7117
+8232
+6898
+-1425
+7289
+1346
+462
+-5431
+3643
+-7627
+8974
+-5687
+-7501
+5783
+132
+1799
+-6425
+-8416
+-8904
+8380
+-6216
+-6391
+-5792
+-5770
+4126
+-9622
+8842
+-2096
+2929
+-1438
+-3156
+-2796
+-7415
+1924
+6898
+6991
+-4968
+-8032
+998
+-3780
+1969
+8453
+2515
+-1596
+-6004
+3195
+-5012
+4594
+141
+1449
+2834
+-5076
+5824
+34
+3463
+-736
+-5096
+691
+3876
+5463
+6703
+-1072
+3853
+-7937
+-8593
+9037
+-2492
+1952
+2293
+-4422
+-2151
+5214
+5234
+5988
+-8011
+4501
+8970
+8678
+8386
+4525
+8340
+-7246
+-2570
+-5829
+2271
+-6614
+-8375
+-4515
+9674
+-2724
+-7871
+3973
+594
+3875
+1614
+-8339
+1879
+-7555
+5093
+6353
+-5309
+-9118
+-7390
+0
+-7598
+-4177
+8634
+7534
+1556
+349
+-9441
+3579
+-4653
+-2416
+-2194
+-4484
+-6483
+-5383
+-78
+-5205
+-1242
+813
+3590
+6240
+-3736
+-7390
+-7632
+5321
+-6299
+-4615
+-2210
+6188
+2372
+7060
+-5986
+-1632
+3032
+-5612
+-5336
+-8543
+3502
+1695
+4391
+2387
+4547
+1110
+-3353
+-545
+804
+-1809
+-5353
+7904
+8120
+5855
+1657
+-6626
+-6422
+-4870
+-1404
+-6229
+-3968
+2585
+2060
+-1821
+1577
+810
+-8408
+-7540
+7897
+279
+6039
+6656
+-9330
+2591
+8567
+-5495
+7354
+7443
+8697
+-9959
+925
+3180
+-6647
+8556
+-1018
+-1293
+9569
+-2128
+-1431
+7483
+-3984
+-649
+-8978
+4285
+262
+-5191
+-2759
+4835
+-5834
+1294
+-3856
+3084
+-8885
+-2708
+-1693
+-8948
+-6021
+1629
+3961
+2760
+2861
+-6797
+5184
+8419
+-9162
+6810
+-8473
+9899
+9844
+-2044
+-9103
+-3183
+-8697
+5303
+7412
+8344
+5003
+5957
+6327
+-8799
+2425
+-5159
+1732
+7934
+5728
+-7328
+-605
+-8552
+-6232
+-9200
+-3586
+6145
+8498
+-2780
+649
+5957
+3744
+-9775
+7645
+7354
+1335
+4195
+-5747
+6484
+8567
+7851
+1910
+8259
+-3384
+-9657
+2189
+-7643
+-5612
+-3674
+-6521
+-4128
+2187
+-3000
+-9708
+3052
+6262
+-4863
+8010
+3371
+5220
+-38
+3744
+-3828
+-6773
+-2962
+2887
+497
+425
+7873
+4140
+8657
+2461
+-7654
+8640
+6365
+4225
+6829
+4186
+2301
+-2793
+-6554
+7241
+-7102
+659
+-7999
+9335
+-1223
+-7090
+6542
+-2019
+-873
+-9624
+6293
+6039
+-6108
+8204
+2860
+5098
+-7132
+9694
+-1973
+-1217
+-3264
+-7112
+8296
+-8850
+4014
+-1837
+480
+-7667
+8005
+4750
+1059
+-4798
+-187
+4728
+7007
+-2369
+505
+-590
+-1827
+9692
+-6294
+9115
+9756
+2380
+4533
+-8557
+6450
+9019
+9514
+-6594
+7060
+2477
+2259
+-5578
+-85
+7356
+6055
+7649
+-2742
+29
+-5146
+-7621
+-2829
+-2427
+-3827
+6197
+9143
+-9622
+-4062
+-6232
+-1470
+2591
+7104
+-206
+9517
+-8918
+4658
+-7199
+-48
+2662
+6782
+-4705
+-9459
+-3950
+-9057
+-2526
+4866
+5611
+-7128
+4238
+1706
+-9179
+-6611
+5615
+-3148
+5074
+-9463
+-4435
+266
+4733
+-1242
+4407
+5334
+-2856
+-3600
+2666
+9396
+-1224
+-7132
+1957
+-3651
+-8843
+-8699
+-6879
+-9957
+-648
+-8212
+6511
+-2657
+5351
+7541
+8556
+7344
+-3734
+-4679
+-9580
+8416
+-8
+3976
+-8397
+-2827
+3666
+-3230
+-9044
+-9821
+-3836
+-8100
+-1502
+-4011
+-4569
+9761
+-8261
+4533
+9424
+-9374
+-6630
+4941
+2496
+-1902
+1491
+-9374
+3398
+2018
+-9983
+-6165
+1750
+-5885
+-383
+-2319
+9426
+5058
+8016
+-8079
+-576
+7192
+5003
+-5885
+-414
+-6455
+2511
+662
+-2997
+9240
+2670
+6145
+-6745
+-3414
+-6450
+-2425
+-335
+2475
+3671
+-4809
+-5888
+-3508
+4522
+-2626
+2970
+9659
+4590
+-4730
+-4722
+-5018
+-916
+4268
+-7102
+-2070
+-5414
+3533
+-6170
+-2247
+-6590
+-7211
+5153
+1360
+-2995
+-9954
+-7684
+-2668
+-335
+9352
+-698
+-133
+-3571
+-3419
+-4821
+-4222
+1603
+-4835
+-2259
+1547
+-2244
+8811
+-151
+-1201
+1008
+2212
+-739
+-9308
+-3766
+8964
+-240
+4044
+8368
+1944
+6672
+7953
+3481
+-4273
+-3961
+-6222
+-9274
+5345
+5834
+-4737
+9009
+-7920
+1128
+8227
+6031
+-4925
+-1714
+-6649
+-460
+183
+9207
+-6046
+2196
+-5435
+2797
+9783
+5909
+1103
+-6800
+9507
+-9967
+7643
+-7489
+4104
+-8978
+8732
+8582
+8013
+-2724
+-9453
+645
+-5489
+-3939
+-5242
+3400
+6392
+3355
+-2111
+-6056
+-8164
+-3053
+-6399
+1921
+-9171
+-68
+-4051
+-5292
+-2462
+-4215
+4733
+-1397
+47
+-5508
+425
+-1883
+-4273
+-8058
+-3972
+7223
+5112
+2154
+-5770
+7949
+8859
+-6140
+876
+7153
+4082
+-1025
+4462
+3629
+7006
+-1790
+2221
+-4133
+-5881
+259
+720
+-6333
+-953
+-749
+1092
+-1037
+4657
+8842
+4075
+-163
+9342
+558
+-5932
+-2319
+-5168
+-8259
+4266
+1592
+2389
+6351
+8556
+6039
+-248
+-6163
+-116
+7369
+-5998
+-2572
+-5181
+-8613
+372
+-8880
+-9597
+4453
+-9775
+-2547
+9640
+-1404
+9001
+8351
+5364
+3377
+-5316
+7518
+1801
+7070
+-4133
+5740
+1146
+-5307
+-9975
+-3460
+7818
+-1809
+-6152
+-1204
+3292
+3734
+-7803
+4001
+-5202
+5747
+1526
+-3045
+-5540
+6697
+2618
+7086
+4230
+1282
+2755
+-5638
+-5562
+-108
+2600
+-4321
+-2492
+-9473
+5957
+-1133
+-892
+5765
+3675
+-6046
+5497
+-773
+7607
+1526
+-9037
+1789
+1944
+-4342
+-5042
+-7299
+-9663
+-472
+-6905
+-4902
+7109
+-6946
+-9443
+1957
+-1247
+3834
+1904
+4014
+9367
+-5834
+4013
+-3265
+-9544
+7826
+-5557
+3747
+1848
+-2747
+1763
+7110
+9740
+-6326
+1550
+-8806
+886
+-1692
+621
+-2318
+-2134
+8851
+-9455
+6829
+6212
+4231
+-9032
+5475
+1265
+-266
+-266
+-7812
+831
+6041
+-787
+178
+7112
+-753
+1676
+6785
+-3034
+-7140
+-6678
+1425
+3896
+-8604
+-4845
+-3478
+6291
+70
+8512
+-1011
+-6948
+4547
+8822
+9089
+-3883
+8273
+6755
+2170
+-7420
+8031
+-1800
+837
+-485
+-8679
+-3348
+5730
+9397
+-2344
+3651
+5514
+1688
+-5743
+8640
+-8667
+-9101
+372
+-2657
+-3782
+7262
+6058
+-7034
+-7193
+6004
+-1135
+-2223
+-7027
+-4662
+-1242
+2456
+-6222
+6197
+6695
+4025
+-7363
+3533
+9713
+-6273
+-7379
+1355
+-383
+-1882
+-9203
+7521
+-8303
+-4640
+-240
+4398
+-3756
+5300
+2396
+9107
+6837
+9589
+-8655
+-3455
+7931
+5288
+6212
+8644
+-4086
+-5556
+-3605
+6591
+8482
+-7391
+7898
+821
+-9683
+-2569
+-7078
+4879
+9921
+-9772
+-1675
+5588
+1058
+-860
+-7392
+-3218
+5499
+6216
+4473
+6210
+-5278
+132
+-1231
+2585
+-7112
+-3865
+4741
+1892
+4073
+4142
+3887
+-8210
+4239
+-3057
+-1247
+-197
+-8115
+-1883
+2029
+6337
+-5321
+-798
+7434
+2029
+-4894
+-7469
+5746
+3214
+-2885
+9598
+-3215
+-4772
+4645
+5263
+6055
+3744
+7774
+3461
+-4734
+6680
+-5585
+1891
+1542
+-7905
+-2908
+-425
+9432
+1695
+-8178
+3503
+-1293
+2028
+-9261
+-8178
+-8058
+8489
+-7812
+-3736
+-3056
+-6157
+8653
+-5405
+1096
+-333
+-9319
+3339
+1335
+4123
+4547
+-4432
+4946
+-3545
+3156
+2462
+9946
+51
+-1134
+6576
+-3436
+5617
+-6425
+-1506
+3201
+2905
+4238
+-5132
+5409
+6349
+2760
+491
+6999
+-6552
+4265
+-9103
+6039
+-9163
+-9496
+7860
+-3785
+13
+8842
+-4772
+-9622
+3261
+271
+-7660
+4662
+5858
+-8431
+-8779
+-559
+9284
+9303
+8780
+3892
+-7479
+8794
+-4622
+-5606
+3466
+-4134
+7344
+-2691
+3375
+-1133
+-2429
+-448
+3443
+-8201
+-3057
+6113
+-5562
+2311
+6427
+-5692
+403
+7459
+1549
+-1563
+1954
+-9166
+-5462
+2189
+853
+8443
+-9894
+-4630
+-2070
+-7034
+-2206
+723
+-1228
+-2484
+2467
+7607
+5293
+870
+-2064
+2329
+-873
+9483
+-6800
+353
+2028
+8549
+8964
+9408
+9007
+-8406
+-2484
+3870
+9519
+-5874
+5176
+-919
+-5452
+-1890
+-9887
+3275
+2816
+7647
+-1376
+742
+5574
+2305
+-9003
+9633
diff --git a/day20/uppga.c b/day20/uppga.c
@@ -0,0 +1,95 @@
+#include "common.h"
+
+#define NINDICES 3
+
+void printv(const uint16_t* v, const size_t n)
+{
+ size_t i;
+ for(i = 0; i < n; i++) {
+ printf("\t%u", v[i]);
+ }
+}
+
+static inline int64_t mod(int64_t a, int64_t b)
+{
+ int64_t r = a % b;
+ return r < 0 ? r + b : r;
+}
+
+void compute_next(uint16_t* nxt, const uint16_t* prev,
+ const int64_t* d, const size_t i, const size_t n)
+{
+ assert(i < n);
+
+ if(d[i] == 0) {
+ memcpy(nxt, prev, n * sizeof(*prev));
+ } else {
+ int64_t ti = mod(((int64_t) prev[i]) + d[i], (int64_t) (n-1));
+ int64_t tip = ti == 0 ? n-1 : ti;
+
+ size_t j;
+ for(j = 0; j < n; j++) {
+ if(j == i) {
+ nxt[j] = tip;
+ } else if(tip <= prev[j] && prev[j] < prev[i]) {
+ nxt[j] = prev[j] + 1;
+ } else if(prev[i] < prev[j] && prev[j] <= tip) {
+ assert(prev[j] > 0);
+ nxt[j] = prev[j] - 1;
+ } else {
+ nxt[j] = prev[j];
+ }
+ }
+ }
+}
+
+size_t index_of(const uint16_t value, const uint16_t* v, const size_t n)
+{
+ size_t i;
+ for(i = 0; i < n; i++) {
+ if(v[i] == value) return i;
+ }
+ return SIZE_MAX;
+}
+
+static inline void compute_first(uint16_t* out, const int64_t* d,
+ const size_t n)
+{
+ size_t i = 0;
+ while(d[i] != 0) {
+ i++;
+ }
+
+ size_t j;
+ for(j = 0; j < n; j++) {
+ out[(i + j) % n] = j;
+ }
+}
+
+int main(int argc, char** argv)
+{
+ char** lines;
+ size_t n = readlines(&lines, "input");
+ printf("#lines: %lu\n", n);
+
+ int64_t d[n];
+ parse(d, lines, n);
+
+ uint16_t v[2*n];
+ compute_first(v, d, n);
+
+ size_t i,j;
+ for(i = 0; i < n; i++) {
+ compute_next(&v[((i+1) % 2)*n], &v[(i % 2)*n], d, i, n);
+ }
+
+ size_t ind[3] = {1000 % n, 2000 % n, 3000 % n};
+
+ int64_t sum = 0;
+ for(j = 0; j < NINDICES; j++) {
+ sum += d[index_of(ind[j], &v[(i % 2)*n], n)];
+ }
+
+ printf("%lld\n", sum);
+
+}
diff --git a/day20/uppgb.c b/day20/uppgb.c
@@ -0,0 +1,100 @@
+#include "common.h"
+
+#define NINDICES 3
+
+void printv(const uint16_t* v, const size_t n)
+{
+ size_t i;
+ for(i = 0; i < n; i++) {
+ printf("\t%u", v[i]);
+ }
+}
+
+static inline int64_t mod(int64_t a, int64_t b)
+{
+ int64_t r = a % b;
+ return r < 0 ? r + b : r;
+}
+
+void compute_next(uint16_t* nxt, const uint16_t* prev,
+ const int64_t* d, const size_t i, const size_t n)
+{
+ assert(i < n);
+
+ if(d[i] == 0) {
+ memcpy(nxt, prev, n * sizeof(*prev));
+ } else {
+ int64_t ti = mod(((int64_t) prev[i]) + d[i], (int64_t) (n-1));
+ int64_t tip = ti == 0 ? n-1 : ti;
+
+ size_t j;
+ for(j = 0; j < n; j++) {
+ if(j == i) {
+ nxt[j] = tip;
+ } else if(tip <= prev[j] && prev[j] < prev[i]) {
+ nxt[j] = prev[j] + 1;
+ } else if(prev[i] < prev[j] && prev[j] <= tip) {
+ assert(prev[j] > 0);
+ nxt[j] = prev[j] - 1;
+ } else {
+ nxt[j] = prev[j];
+ }
+ }
+ }
+}
+
+size_t index_of(const uint16_t value, const uint16_t* v, const size_t n)
+{
+ size_t i;
+ for(i = 0; i < n; i++) {
+ if(v[i] == value) return i;
+ }
+ return SIZE_MAX;
+}
+
+static inline void compute_first(uint16_t* out, const int64_t* d,
+ const size_t n)
+{
+ size_t i = 0;
+ while(d[i] != 0) {
+ i++;
+ }
+
+ size_t j;
+ for(j = 0; j < n; j++) {
+ out[(i + j) % n] = j;
+ }
+}
+
+int main(int argc, char** argv)
+{
+ char** lines;
+ size_t n = readlines(&lines, "input");
+ printf("#lines: %lu\n", n);
+
+ int64_t d[n];
+ parse(d, lines, n);
+
+ size_t i,j;
+
+ for(i = 0; i < n; i++) {
+ d[i] *= 811589153;
+ }
+
+ uint16_t v[2*n];
+ compute_first(v, d, n);
+
+ for(i = 0; i < 10*n; i++) {
+ compute_next(&v[((i+1) % 2)*n], &v[(i % 2)*n], d, i % n, n);
+ }
+
+ size_t ind[3] = {1000 % n, 2000 % n, 3000 % n};
+
+ int64_t sum = 0;
+ for(j = 0; j < NINDICES; j++) {
+ sum += d[index_of(ind[j], &v[(i % 2)*n], n)];
+ }
+
+ printf("%lld\n", sum);
+
+}
diff --git a/day21/Makefile b/day21/Makefile
@@ -0,0 +1,25 @@
+CC=clang
+UTILS=../utils/reading.o
+INCLUDES=-I../utils
+CFLAGS=-Wall
+#CFLAGS=-O3
+
+all: utils common.o uppga uppgb bbrute
+
+common.o: common.c common.h
+ $(CC) $(CFLAGS) -c common.c $(INCLUDES)
+
+uppga: $(UTILS) common.o uppga.c
+ $(CC) $(CFLAGS) -o uppga uppga.c common.o $(UTILS) $(INCLUDES)
+
+uppgb: $(UTILS) common.o uppgb.c
+ $(CC) $(CFLAGS) -o uppgb uppgb.c common.o $(UTILS) $(INCLUDES)
+
+bbrute: $(UTILS) common.o bbrute.c
+ $(CC) $(CFLAGS) -o bbrute bbrute.c common.o $(UTILS) $(INCLUDES)
+
+utils:
+ make -C ../utils
+
+clean:
+ rm -rf common.o uppga uppgb bbrute
diff --git a/day21/bbrute.c b/day21/bbrute.c
@@ -0,0 +1,29 @@
+#include "common.h"
+
+int main(int argc, char** argv)
+{
+ char** lines;
+ size_t nlines = readlines(&lines, "input");
+ printf("#lines: %lu\n", nlines);
+
+ monki* m = parse(lines, nlines);
+
+ int64_t brute = 1;
+ int64_t v1 = 1, v2 = 0;
+ m[monkindex("humn")].op = '\0';
+ do {
+ m[monkindex("humn")].v = brute;
+ v1 = mcompute(monkindex("zhfp"), m);
+ v2 = mcompute(monkindex("hghd"), m);
+ if(brute > 0) {
+ if(brute % 10000000 == 0) printf("> %lld\n", brute);
+ brute = -brute;
+ } else {
+ brute = (-brute) + 1;
+ }
+ } while(v1 != v2);
+
+ printf("%lld\n", brute);
+
+ free(m);
+}
diff --git a/day21/bruteb b/day21/bruteb
Binary files differ.
diff --git a/day21/common.c b/day21/common.c
@@ -0,0 +1,128 @@
+#include "common.h"
+
+#define ALPHABET_SIZE ('z'-'a'+1)
+
+size_t monkindex(char* name)
+{
+ size_t r = 0;
+
+ size_t i;
+ for(i = 0; i < 4; i++) {
+ r *= ALPHABET_SIZE;
+ r += (size_t) (name[i] - 'a');
+ }
+
+ return r;
+}
+
+monki* parse(char** lines, size_t nlines)
+{
+ monki* m = malloc(ALPHABET_SIZE * ALPHABET_SIZE * ALPHABET_SIZE * ALPHABET_SIZE * sizeof(*m));
+
+ size_t i;
+ for(i = 0; i < nlines; i++) {
+ char* line = lines[i];
+ size_t idx = monkindex(line);
+ uint64_t tmp;
+ if(sread_next_u64(&tmp, line) != NULL) {
+ m[idx].v = (int64_t) tmp;
+ m[idx].op = '\0';
+ m[idx].opl = SIZE_MAX;
+ m[idx].opl = SIZE_MAX;
+ } else {
+ m[idx].v = 0;
+ m[idx].op = line[11];
+ m[idx].opl = monkindex(&line[6]);
+ m[idx].opr = monkindex(&line[13]);
+ }
+ }
+
+ return m;
+}
+
+size_t left_tree_root(const monki* m)
+{
+ size_t ri = monkindex("root");
+ return m[ri].opl;
+}
+
+size_t right_tree_root(const monki* m)
+{
+ size_t ri = monkindex("root");
+ return m[ri].opr;
+}
+
+int humn_subtree(const size_t start, const monki* m)
+{
+ if(start == monkindex("humn"))
+ return 1;
+ if(m[start].op == '\0')
+ return 0;
+ return humn_subtree(m[start].opl, m) || humn_subtree(m[start].opr, m);
+}
+
+int64_t mcompute(const size_t start, const monki* m)
+{
+ if(m[start].op == '\0') {
+ return m[start].v;
+ } else {
+ int64_t opera = mcompute(m[start].opl, m);
+ int64_t operb = mcompute(m[start].opr, m);
+ switch(m[start].op) {
+ case '+':
+ return opera + operb;
+ case '-':
+ return opera - operb;
+ case '*':
+ return opera * operb;
+ case '/':
+ return opera / operb;
+ default:
+ fprintf(stderr, "ERROR! Bad operation %c\n", m[start].op);
+ exit(1);
+ }
+ }
+}
+
+int64_t reverse(const size_t start, const monki* m, const int64_t desired)
+{
+ if(start == monkindex("humn")) return desired;
+
+ if(m[start].op == '\0') {
+ fprintf(stderr, "ERROR! Reverse searching in leaf %zu\n", start);
+ exit(1);
+ }
+
+ size_t h_subtree = m[start].opl;
+ size_t n_subtree = m[start].opr;
+ int humn_left = 1;
+ if(!humn_subtree(h_subtree, m)) {
+ h_subtree = m[start].opr;
+ n_subtree = m[start].opl;
+ humn_left = 0;
+ }
+
+ int64_t opv = mcompute(n_subtree, m);
+
+ switch(m[start].op) {
+ case '+':
+ return reverse(h_subtree, m, desired - opv);
+ case '*':
+ return reverse(h_subtree, m, desired / opv);
+ case '/':
+ if(humn_left) {
+ return reverse(h_subtree, m, desired * opv);
+ }
+ return reverse(h_subtree, m, opv / desired);
+ case '-':
+ if(humn_left) {
+ return reverse(h_subtree, m, desired + opv);
+ }
+ return reverse(h_subtree, m, opv - desired);
+ default:
+ fprintf(stderr, "ERROR! Reversing with unknown operation %c\n", m[start].op);
+ exit(1);
+ }
+
+ return INT64_MAX;
+}
diff --git a/day21/common.h b/day21/common.h
@@ -0,0 +1,26 @@
+#ifndef COMMON_H_
+#define COMMON_H_
+
+#include <stdio.h>
+#include <stdint.h>
+#include <assert.h>
+#include <reading.h>
+
+#define ALPHABET_SIZE ('z'-'a'+1)
+
+typedef struct {
+ int64_t v;
+ char op;
+ size_t opl;
+ size_t opr;
+} monki;
+
+size_t monkindex(char* name);
+size_t left_tree_root(const monki* m);
+size_t right_tree_root(const monki* m);
+monki* parse(char** lines, size_t nlines);
+int64_t mcompute(const size_t start, const monki* m);
+int humn_subtree(const size_t start, const monki* m);
+int64_t reverse(const size_t start, const monki* m, const int64_t desired);
+
+#endif
diff --git a/day21/einput b/day21/einput
@@ -0,0 +1,15 @@
+root: pppw + sjmn
+dbpl: 5
+cczh: sllz + lgvd
+zczc: 2
+ptdq: humn - dvpt
+dvpt: 3
+lfqf: 4
+humn: 5
+ljgn: 2
+sjmn: drzm * dbpl
+sllz: 4
+pppw: cczh / lfqf
+lgvd: ljgn * ptdq
+drzm: hmdt - zczc
+hmdt: 32
diff --git a/day21/input b/day21/input
@@ -0,0 +1,2397 @@
+vbfg: 2
+dwgb: 3
+ctlr: 3
+rzwt: fdqz + hpqd
+qwlr: 3
+hgbz: 2
+mbqp: cfmj + gqrj
+tmrn: 3
+hbvn: rnrm * brjj
+pjjr: bvpg + tfqn
+fdnr: 10
+vgcz: jngf * mgzw
+zzvb: 2
+cgnn: 5
+jqqq: fmvt * vhzd
+wlgc: 3
+qmjl: 2
+pjsd: gzgp * vnsp
+vtsq: hctt / lmqf
+blgq: 1
+nrch: 13
+lvjf: tjzh * ffsc
+jczs: 5
+rfrs: 3
+vjwh: mwdw * bhnw
+wpvc: jlzw * mfvr
+rgbh: 2
+htzb: mttr + mqmv
+bwbl: pmhf * lfsd
+zfdj: 1
+pjzf: tppt * ftnh
+wzfg: hhjv * dlph
+lddf: qjnr / ffvl
+jtfj: 17
+vqhs: 5
+tlrl: 4
+httg: hhjb * zhzb
+dbrq: hfgs * qlwz
+qgjz: hqmg * jchz
+jfbw: 2
+swmc: rldn + cdgs
+jpms: 2
+jmmr: 5
+lfjw: qngl + tbhl
+lstl: 5
+gfrz: 2
+hldd: 11
+mdrm: 19
+bnqb: 8
+stbv: dwsv + bvhp
+glwg: jpzc + djqc
+qdcm: lgsd + fjwr
+sfgh: 2
+bdsr: phdn - gpmn
+hldm: mjsp * djsm
+wlqt: 6
+rftc: twcq * fgnd
+qrcn: rntw + gcdg
+nntn: 2
+vljq: bbnn * gprr
+mstq: 2
+rbhz: schl + jwtq
+mdwj: zhbj + qrfp
+cfgp: pnhq - zfdj
+nwnh: 7
+dvgv: 2
+wmrl: wjrw + llvf
+ldzp: mlwd + mqcz
+cnvf: jqfj / nmdl
+qqbg: njsw + dvnc
+mzmm: 3
+ncwm: 2
+wrmh: dprw / jjsd
+qrht: zprs * jsqg
+znlm: cmgv * lqpm
+jlsn: 6
+fjfv: ljql + fppt
+ffjf: 5
+gzsp: 5
+ptrh: 13
+vfsw: dvvp + gjvc
+slgm: 3
+lpcg: dsnq + btnn
+rhlb: zhrc + jcjv
+chfc: 10
+dptd: 2
+mlhh: cpwr / nbsf
+sfqb: 2
+zvtn: cbsp * zwsm
+bbcc: tmtp + prfm
+jwwb: nfdz * zhdj
+zhdt: jdfz + fhpp
+sdwq: 3
+pwcz: vmgn * gwlt
+lfcz: 2
+pzfh: hjmt / zpfg
+hctt: nfwb * wgrs
+msgl: 6
+lqlw: vnfc + qlwn
+lddp: mchv * htwg
+zrtc: pwjc + nrpb
+nsmp: 2
+nrwj: 2
+rhhp: cnvf + rjrf
+lltr: qbzq + jszc
+qrfp: 4
+fbtv: nvql + fsrg
+nhqr: 3
+hghw: pmsr / mmsw
+wldw: 3
+hfvw: vqjf + wfgc
+cmpc: 2
+wrst: 2
+ntzz: 5
+ccvh: 2
+fftf: gfpp + cfmn
+sfcf: vtsq - dzwb
+pltq: 3
+lljs: 2
+pqfd: 3
+wtbg: 5
+mhpf: 3
+mccg: wbhc * grrr
+mfrl: zcvd / chld
+rnfh: wqgg * dfrr
+fscc: 4
+sfrv: 7
+frtg: 2
+hnmn: 3
+hhzv: 2
+rstc: rwwl * ftjl
+qtdr: vnch + ntbv
+jmcf: 5
+mgsh: tmbg * lswz
+rqsh: 11
+blmh: tbhz - vhbg
+vwgj: nzvn * gfrz
+qclt: nnvb / cmpc
+jhrh: 3
+lbqs: 4
+zbwc: ntsp + rnfh
+ndvz: zsfr + ftzh
+rwdr: fdpq * pccw
+qzlq: gfbc - vtnb
+hwfd: ftmf / gjdb
+hcfd: 17
+hbdp: 3
+vzhw: nhqw * tmlc
+gpzt: lglv + hldd
+dtns: 8
+ttbq: 3
+cnnw: hdnh + bhlv
+vmcn: 4
+ddgb: 3
+cdrj: 4
+jqfl: 2
+lnfg: 4
+hcgp: 6
+pfjs: 3
+frdt: bhfn + vqdw
+mpgn: 3
+hgvp: 2
+przl: 5
+ptqz: 2
+zzvh: qntv * cbsb
+gfdw: ctlm * rctr
+nhsd: 3
+nrld: rjww * wsns
+bjng: gldg * zpcv
+crwm: jttb + bwbl
+cdnl: hjwh / hgrg
+mjvl: 2
+mhjs: lcqf / drlq
+sglg: 3
+hchl: wbzs / wjwc
+nnwg: 8
+hghd: rwdw * cmmf
+lnlh: mddj * vrzs
+sjpp: dwlz + qnwt
+hdcw: vszc * cgzl
+hlbd: qrht + lnlh
+lzlg: vmpw * bvqq
+thlv: clnz * qvcb
+hlnl: 2
+tjwc: 3
+fzmp: htvj / fszn
+fvfj: 2
+wphb: hlcj * mwcc
+qtgr: 2
+bjvp: fsjv * zsjb
+gfvf: 5
+chjr: nntt * gplc
+hwls: rsgc * slwr
+rmcv: 14
+lrhw: 3
+pnhq: ljts + gbhr
+lwqq: bccm * wjlz
+cqlp: cgjf + gfvf
+nfgv: hwcq * qvdd
+prlb: 12
+tdcr: zbdn + tfzl
+spbs: fbtv + zcvh
+dfnv: 1
+tmjj: 7
+mjsp: tbtc * hdqf
+hbjl: glqm * crss
+dbfs: 2
+jfqs: 3
+spww: zppb * mrmc
+msvh: tfmq + hrzl
+rbvb: ljnn * pftv
+lzpw: clll + slzl
+tfcs: 4
+bgwg: 3
+mgpj: pnwt + pbrt
+zhrh: fcvq * rnwn
+zlwg: 9
+ncgt: 3
+hvlv: 2
+gcdg: hnwb - zbmj
+tpww: 5
+qsqw: wldw * zlhb
+lfdm: 3
+bbtq: 2
+ghch: 2
+bjqp: ssgw * nchg
+qzrv: pcdv + mwzc
+mbgb: mhvg + drft
+gzbc: 5
+ncrd: qqwf * phjw
+hpzf: 2
+rntw: cnzm / nrpt
+tllp: 2
+wrff: vjmp - zpfh
+llcq: 14
+lfdd: 5
+blcm: rjzv * phrq
+htbc: 13
+hqnl: 5
+mbjt: 2
+mldp: 12
+lgnh: rbvd - gvrm
+cfmg: 10
+fgsd: 2
+sgws: zwcl * tqrl
+lgcw: 20
+cmzt: fmvz * zjlh
+fssb: bgcs * rrvs
+ntzh: 2
+rfpp: 2
+jgfg: 2
+ppvj: 4
+bcvc: gtpb + wjvz
+spfg: 4
+csvr: hlbd / vrqz
+rphf: 2
+hdnh: 16
+fjwr: fjvf * nwlt
+hlqg: ccmz + hzfj
+hpdp: qlhd + jwwb
+hmgd: 5
+zbdh: rmvv * bggc
+hpcn: cdnl + zltq
+dnhd: vjbn * bhtd
+mlnf: 12
+hnzz: 20
+zlsq: mhpf * htnm
+jqcj: 4
+mlct: 5
+nzmv: bttg * vshr
+jwdq: zhzl * hsgn
+crww: 3
+lzcp: dhtg * pltq
+hggn: 2
+qdfs: 3
+rqlv: sfss + mqpr
+lbcq: drrb * gvld
+jqtj: 3
+fsqs: 5
+wjrw: jzps * ptjz
+lgpw: jjcq * fgfg
+rzzz: 15
+fmwb: 19
+mmtb: 3
+cgfp: 2
+chmm: 3
+ljgz: csvr + lppw
+vqfq: hfhc + ngml
+ldmt: 4
+zhhm: 9
+fzpt: 3
+ssdr: 13
+fwnf: pjpr * gtvw
+bbqf: bjng - msgl
+bbjt: 7
+fdpp: 14
+nntt: 2
+dpst: 2
+gnmt: 15
+wngv: 4
+vzjm: jdzc * cwtn
+jfpl: njls + gdgj
+cqfh: vcmt + qglp
+dzwb: 2
+mvwr: hbml + dbsd
+zsbm: qnsj * mwjn
+lfqf: 2
+vqdw: zrwd + hppn
+rrvs: 10
+rsbb: 2
+crzd: flnb - pshd
+cgzl: 2
+zvrn: mvzw + wmrl
+ftmf: wzcw - vssf
+pjpr: 5
+hswl: gczz / nnth
+vnww: 5
+dbsd: 3
+tghv: zgsm * hcfm
+ttzb: phzt + ntnq
+ppmn: hrwm * rjhr
+ndmn: 5
+zhvq: mgfs - bnfw
+zqfw: 3
+hwmd: 7
+hlmh: 3
+ndlp: 13
+vbgt: 14
+vqsz: ccpw * wqsm
+ldsz: 3
+wdqs: 1
+zwsm: 4
+ldfp: lzcp + nfgv
+ffdv: gwqq + wpqr
+crmv: 2
+fwlf: hfcg / jsbq
+dqvm: bvbt / nrvs
+qwhg: hnng / tdrs
+rnqm: btjz + zvfv
+rhqg: nzzq + sbqt
+vwmm: mrwm * zdbn
+zbfs: 2
+thnm: swtb * whdm
+qvpm: bcvh * hnjc
+pjdr: 2
+qvzl: 5
+ppjb: 2
+cmbj: ccpc + qfpd
+hhjb: 2
+wpcs: jswt * zcnh
+jqhd: pmvv + jdvv
+nsln: 3
+fshs: 5
+vrpw: 2
+sqgq: 7
+pmhf: rhln + frbr
+hcrj: jwhp - jnwm
+mswg: hrcv + fqlc
+gtnp: hvpg * qsfc
+vsbz: ljfn + sjpp
+ssqs: 2
+lqqg: 4
+bhlv: gtmz * sjlw
+lnvg: rldv * fhmj
+rwwl: gslb * svzn
+fmql: vwfn + bzcd
+tnqc: chbz * nrbv
+cqhd: gdvb / swsc
+vgqb: wnfn - wldl
+vhbg: 5
+pmcp: 13
+pflz: tjnh * wcwl
+dvnp: lqzn * jmdr
+lsgf: vpmd + tggg
+sszs: ndhf * jncv
+qqnq: gmnc * gmbp
+lcmt: cdrj + gdmt
+wsmp: fstv * zvrn
+rhvw: psbw * lfgf
+htdr: spbs - pdrt
+mtrz: rmjp * glfz
+mzvv: hzbh + qmjl
+pmvv: mljh / dwfs
+bjnm: fdsj + dwlf
+jjrr: 19
+dqch: 2
+rmnr: 8
+qtnb: cbwc * mdzm
+dwzg: 16
+nggz: 6
+zsmn: 4
+hnng: rqtc * cbph
+qjbg: tjcz * thwh
+fqtt: humn - jvzc
+gwqq: zffv / jwmg
+wqqh: 3
+slzl: frhj * nsjn
+mljb: 4
+wcrr: mhnh + tgzm
+fgnd: 5
+ndps: wjdd * hgbz
+rjqv: 7
+cftz: 2
+thdb: gqpf * ccrg
+zffv: tddq + qpdb
+jqmv: dhpt + nfvw
+mjmc: 17
+hwvn: 19
+bngh: 2
+pnrp: 4
+jtjc: 2
+glzn: 13
+bbmz: 7
+hjwt: dhtw * tpjh
+prlg: gdcz * ljsb
+jlbt: 3
+wmwq: 4
+fqwr: 3
+qzvd: vtff - lpcb
+bjhf: 5
+tllg: vpqs + dcfb
+gnht: 5
+qpwh: qlmp * gcvh
+zcvd: svrv * bwsq
+wbzs: ntzh * rhvw
+hrqs: jhqr * vhhr
+hpfc: 2
+bqtt: 4
+nchg: jznm - zzlw
+gpwn: 3
+hcwt: 7
+wcvv: bfcn + vmcn
+rwfm: 2
+mgmr: gnvg + fshs
+dvnc: nhfw + nrzh
+tddg: chpw * wfqb
+djlv: 2
+nbrv: 17
+vpth: 15
+ccrg: nggz * prht
+cjbz: gswq + ppcg
+gbdg: 6
+bnfw: 16
+dlpb: nmpj * dnpd
+qvgz: 11
+swsc: 3
+sctw: 2
+fjrq: 3
+hblv: 5
+qpvf: hgqf * zrtc
+cmms: jsjd - tbth
+tstv: dplp / nnjb
+pgzc: rnds * qtrs
+scwc: cwsc + ppmn
+nwcn: 12
+nzpn: 13
+vssf: ncwm * rzwt
+ljsh: nggd * htjn
+jdgt: pgzc * gnht
+scmj: 3
+lgdd: 3
+pwgf: 3
+btml: mtjr * hwmd
+msvj: 1
+rmpc: qmfm + rrws
+qccw: 9
+nvqd: 2
+cvpw: bbtq * smzb
+rjvr: hzcg - tgtp
+ctlm: 2
+nrzh: btsl * lgqq
+mnmq: jqtr * qzct
+jdzs: 2
+pbff: 2
+zhzc: gcfc + nmfc
+bwwz: mztz * zgfb
+wldl: jdfv * wjwp
+brns: 8
+zsfr: 1
+lccj: qjbg - mzbz
+lnbv: 5
+qbzq: nnws * hlvd
+hlwz: dvhc * ngdf
+stbf: 5
+hvgv: 3
+dqjb: 3
+zpfg: 2
+wmzn: 2
+ssdb: 3
+sdsg: cccn + msqr
+jdzc: 11
+blsf: pnmj * bngh
+dcpd: 3
+ptmd: 3
+wlch: rgdw - nlqt
+tsdf: dvcz * mglc
+jmjw: dzdf / lpcg
+prvw: 3
+mcdz: bqtt + wpfb
+mrfv: 12
+zqvt: 5
+dlph: 12
+wdpv: 5
+wpfw: 3
+wwwc: qvds * ztjs
+rjfs: 5
+jvdd: 15
+tjvl: dhvd - wfqq
+fppj: 12
+mgzw: dfmg + mlnf
+cnrn: nswf * mstq
+mhsd: 2
+bzdd: srzw * srlt
+wgjt: hrvl + gznh
+zbmj: jtjc * rvdz
+gldg: 7
+vgsr: vwmp * mvvj
+grqv: qpls * hchl
+vcgw: 2
+ddcb: 10
+nwhj: zzlq * lzdj
+fndj: ppdj * hbtv
+cwcv: 5
+qzzs: zzmg - djgj
+qntv: 2
+rhln: lqvp * mmgv
+zpwf: nqfw * tmjj
+plvm: 2
+hcmb: 5
+wgwv: jfpl * wlhm
+cmbf: spzt * lhcn
+drdc: 5
+swnc: dsnd - tnvf
+zvrs: 2
+bvhp: mgds * gqbq
+rchm: 3
+clll: tmmz + thqn
+gplr: 11
+gwww: jcmg + ccvh
+tzlt: zvgj + phdc
+zhgr: 2
+wpfb: stcj * tfqj
+lcqs: mmzw + dpvw
+jctj: flhq * wclf
+zfdf: 3
+wssf: vgft + zgvh
+wjrm: 10
+vncm: 4
+lttb: gpwn * hdpf
+zlph: smbf - hcmb
+mjpl: 2
+fwgr: hvlv + bzdd
+chvp: 4
+rptg: 7
+zpcv: 5
+tzfp: bjnf / sfgh
+pmzj: fwhp + wcvw
+jmdn: 3
+nzjg: 11
+cjzn: 5
+lzbf: 3
+ltsn: hqqp + zbfs
+hlwv: rbfv * wtnt
+dvvp: 5
+mzpf: 2
+rrmg: 5
+hqqq: 5
+wjwp: jdzs * hsrq
+mlqm: 8
+sntl: 5
+phdc: wgjt * bqcb
+vhgq: 4
+vcbv: wqtw + qdfm
+qvnj: vcmg * nsrm
+mwzc: thdb + scjj
+nslr: 4
+zqvd: 3
+wqsm: 6
+tbzv: zzvh * ghch
+swtb: pbhn * hhqv
+hcvh: 16
+tczg: 2
+mnfg: 7
+qnrt: mtml * tjjs
+vnwg: rslr + pflz
+fbnl: 3
+wdng: 2
+tqdf: 11
+wgfd: 8
+jbwv: hzjv * fphs
+rmvv: 5
+nqvq: 3
+gcld: 10
+slbf: 5
+rhwv: hrnv * qvtp
+rwdw: dgvf * dbhl
+hqfv: 15
+hnmz: tqpv * hjdd
+smjz: 3
+ztvv: 10
+tscq: zjwz - jjjt
+zchz: qbjd * rzzz
+bpns: wgrt - brfg
+ljbd: gfhl + pmzj
+tfqn: cczl * ztvv
+ndpn: 3
+btbn: wlqt + wdpv
+cbsp: 4
+rlfn: mslj / jlsg
+srgf: 2
+gcww: cqhd / nvqd
+dshb: tppn * jrmg
+cnjr: fnwv / tqrq
+fstv: 5
+nvgq: sdfm * fbwc
+cmrt: chht + wncd
+pncc: hpnn * nwqw
+gfsb: jqfl * qszr
+hlng: lszc + hjrd
+nldc: 20
+wsdr: 9
+dvfp: 5
+ffqv: hcdc * prdt
+hjwh: gbsl * mjpl
+dtpf: wphb + tblh
+bdww: 12
+hcrm: 5
+vzfc: 6
+rvjc: rwjl * ntzw
+sjqq: 13
+lrvl: 2
+bszg: zhgr + wnnf
+plzr: 19
+bcpv: bgzj * dfbh
+qjjd: 16
+csjp: glgt + hqjf
+bgtp: rtnm * hbdh
+ctqr: 2
+hqsp: 2
+rjww: 2
+fnpj: 17
+lwfm: 2
+msff: vlgf - qjgt
+mgds: 3
+vrzs: brng * rpnq
+qwph: rgfh + msfq
+prjh: 2
+bsqc: hlng / tntr
+zcwc: 2
+fhpw: rmnr + srcq
+dplp: ncvh * mjvl
+mdgl: bqht + lztt
+tdch: 6
+ngvh: 10
+cbsb: 11
+ndtc: 3
+ngsm: qgqp * pnzq
+gbfm: 4
+humn: 1953
+jlsg: 2
+cmmf: gbtc * rhqb
+zbtz: 3
+bqhf: zvcw + vqfq
+czsf: ddll * hlmh
+vdvd: 4
+dzgh: 11
+jqhr: ssdr * vfbf
+fmvz: gvgb + cclh
+dhtw: hfrz * mclw
+gtvw: pqdc * dqch
+tgzm: 11
+tqrl: 3
+wmwn: tfrr + mhjs
+lvpq: 1
+tqrq: 2
+mcsc: 4
+lszc: bpll / lnfg
+hwwm: 18
+jqmz: trpm * lstl
+phlw: npgp * rjqv
+nsvt: 3
+tgtp: ctvm * vpjw
+jjzc: lmqm + jmcf
+qvjs: spzc + jrdq
+qzph: 2
+pnzl: 2
+nfdz: 7
+mzgg: 10
+srrv: 13
+nnjz: 5
+nfhv: 2
+rdgt: 3
+tfmq: gvwq * grtl
+cjrd: bgtg * hswl
+wtnp: fqbr + hggn
+bvlv: 2
+qdsg: 7
+cnjg: zsrs * gtfc
+ffvl: 4
+zpmq: 3
+mbmg: 5
+rfbv: 10
+hcqj: 5
+sqzv: 4
+lsbv: wrff * jvdd
+htvj: mtzp + wrmh
+ddfm: 5
+qmfm: mjzd / spct
+spcc: 17
+fvcn: 20
+fbgz: nqmm + pwcz
+sfzn: 6
+vjnd: grnb * ffqv
+tpjh: 2
+frbr: dbht + rgpc
+nhtr: 3
+dtvr: 8
+cpwr: zhrs - tcbz
+dsnq: 4
+jshl: rvjc * jhdc
+ljpg: zzdv - lbsd
+tmmr: 9
+fdpq: 2
+hdqf: 5
+jqtr: 2
+bpct: 3
+ggzj: ctqr * wssf
+gcpq: tlzg + wdqs
+vqrn: mwgz + bjqp
+bppf: hddh + sqgq
+vdmp: qrhv * mpgw
+mwqn: pbfj / mzvv
+fgfg: 3
+hhjv: 17
+dhbb: jfbw * wlzg
+nbsf: 5
+rslm: 13
+dvss: 19
+dwsv: 3
+fsrg: 16
+prvm: 2
+hblr: jbvr * jqts
+wdcn: 13
+bmfs: pnbv + rnls
+mnms: sfqw * sfrv
+phnv: vnft + pprw
+tfmw: dsll + hwjm
+brwh: sntl * mtrw
+zgsr: 2
+qwhh: 3
+tlpz: tmvc * sdlv
+wbwv: zhmn + hdvc
+jwzn: 7
+sfwf: 3
+mgmb: ndtc * pbgc
+ngsf: 4
+vwfn: qvlz + ghcl
+hcdp: gfsb + qzph
+qvtp: 2
+qglg: mczm * wwhh
+lssr: jthc * dbrt
+gcwt: 3
+jzbm: dghp * tscd
+ltft: gwtl - cmzt
+bzcd: stnh * mzhm
+nfpn: gjhd * jztm
+mlnn: 2
+fqft: 8
+gfpp: 8
+flmd: sfwf * smjz
+zcvh: 3
+bmnn: grqv + rmcv
+qnsj: scmj * mppn
+tbjg: 4
+njdw: mgjp + mjpf
+vccs: lnbd + lvjf
+zdfz: 3
+pbhn: 17
+fmjd: 10
+mjcn: vrvs * qvlq
+zwqv: zqvd * jzln
+bhfj: 4
+mjgm: rfmd - nqmg
+rnrm: 2
+brzn: 2
+hjnl: 5
+dzhp: wzhv - qjcn
+vjbn: fstb + rjmh
+vlst: qnlg + fjfv
+dmzf: mmzm * tnnr
+qwvn: 3
+mclw: 2
+dhtf: 2
+wrgb: zvpl + lltr
+ssvs: zjrg + tbsd
+rcwr: gvwh * nchp
+cpcd: 3
+prfm: 4
+vhhz: gmpz * clws
+gtzp: 8
+fbwc: 7
+dctr: 3
+tgqm: 7
+qmtr: mjzm + qpvf
+qbjd: 2
+ngtq: rprp - cmwp
+zrtf: 2
+ssbq: 2
+dpvw: 15
+rbgz: wtbg + mrfv
+svvz: 2
+ccvp: 4
+fmbs: hglh * qzwb
+ljtq: 3
+cbwc: 4
+srsg: tqqv * zcwq
+zqjl: lzpw + zbwc
+zdhv: flmd + mmgp
+npbs: 10
+mhnh: 2
+tscd: nsln * hzrz
+pbhd: 4
+ldrw: btrt / wpmm
+zlbn: dtvr + hgsr
+pwjc: rgfm * rfpp
+rvtm: 2
+zpqr: dhtf + wfbv
+glqm: zpqr / fqwr
+hlcj: 4
+wzvg: jmgz / zqtb
+cjpm: ndpt * wqfv
+pvcw: fsbz * tzlt
+mnwm: dvpw * zhhm
+clws: ptvc * lhrm
+zvgj: svzm * hrmm
+fvsc: 13
+fmzw: zjnr * csrz
+dzrf: jtnc * hqsp
+zlwh: 3
+pwmd: 2
+flft: shzs * bjnm
+tqfv: ptvl * jfld
+bgtg: zmgl * hqnl
+qlhd: ldzp * cnnz
+zwwq: 1
+jjpm: 14
+wzhv: tpgr + pttl
+vlgf: tssl * lmvt
+gnfg: cggn * pmpn
+sffq: 8
+fbqz: zqdc + nbjm
+vhng: 13
+zzwt: 2
+qzgd: zlsq * frjt
+gzmq: vzhw + qwqr
+fvrq: 19
+gctq: nrch * ctgl
+rdzh: jthv * shsv
+mqbv: jdgt - wbrs
+vmbr: fvsc * cqgf
+fppt: 10
+pzzm: nwnh * fsgd
+lchq: 4
+fbws: 1
+qfpd: 8
+srzw: 11
+cwsc: rjzw + hszg
+nfwb: lnvg - zwmh
+nwrd: 2
+jrjs: 2
+gjvn: fvcc * lfcz
+tmzr: pbqh * fzvm
+cbdp: wzvg * msdv
+zlgw: qwhh * jcjq
+nvnh: 14
+rrbn: 3
+pjlf: jmmr * mbqp
+qngd: 5
+nmhz: pncc + drpt
+bljd: 5
+fqlc: nzpg + qvpm
+whhj: bzjj + qfms
+hfvl: 11
+pnbv: cnjr + hlnh
+bgrg: lssr / fvfj
+vcss: 2
+gnvg: 1
+vgts: 1
+bpjh: 3
+dhht: vdds + tlbr
+whdm: 5
+tjcz: 7
+gjvc: 2
+vflg: 3
+dtwp: nvgq + pjzf
+gwtl: hbph + ngtq
+zwds: djjg / wwwt
+bfsf: 11
+gvwq: 3
+rdgj: 5
+pprw: vzlr * stbf
+gmzl: 20
+scmn: 2
+tncz: vqhz + nfcq
+sfsl: 5
+hmhn: 3
+zvfv: hltv - pjdr
+phdn: zlts * rjpw
+nrhb: ddjw * tjdh
+nqmg: 6
+nsjn: bdsr + vmbr
+bnmd: chfc + phnv
+djsm: 7
+lztt: dnlg * mmtb
+qjgt: rdzh * rcss
+dbhl: 20
+zzlq: 2
+btrj: 7
+prdm: mhbb * vrzv
+wjwl: zspq + cmrt
+pwtr: 2
+tsnb: zwqv - ghwp
+rwtt: 5
+nzvn: qqnq + gzsp
+ffwm: 3
+lnwn: 2
+nnws: 3
+bpqn: 3
+cbph: pvcw - qpwh
+mgfs: wcvv * dnsj
+tbrq: spcc * rjmz
+jgls: 3
+pllq: lbpv + dhgh
+rnls: msvh * cchj
+qfht: 9
+dwsq: mtzt + mjcn
+hltv: jqtj + dbrq
+mqpr: rsbb * tbrq
+tpwt: 2
+fqbr: 5
+dsnd: dwsq / tpww
+hjdv: hdcw / dpst
+rtnm: 3
+tqqv: jzbm - gmzl
+lgfn: hbjl * qjhj
+wjqd: 11
+vpvv: 5
+btcn: rnqm + svwm
+hwbc: qfmj * szcb
+vrbp: 2
+rldv: 4
+jznm: fflq * nlvv
+rzsf: ndps * vsjp
+crss: 2
+vsmj: bvrr - mmrf
+bwbm: sqtr + vttq
+ptjz: bnqb + vzfh
+qqfq: 3
+jrmg: 5
+chld: 2
+cchj: 7
+jcws: lwqq / jwdq
+nzpg: tmrn * clzb
+jcjq: 7
+hppn: 16
+ngpp: ngtf + zdhv
+jstz: bbcc + bdww
+htnm: mzmm * ssdb
+drhd: jrpn * rhgt
+jncv: 4
+pbqh: vnwg + trgv
+fdsj: swnc / zlwh
+pqgn: rcdg + tgqm
+qfms: bwbm + bqhf
+jthv: jwzn * mvwr
+ldcd: 13
+hcfm: pzdm * vrpw
+tmvc: dqjb * fwpn
+qpdb: dbrv * cmbj
+dwqf: 2
+lcvr: ssqs * nmcr
+blww: hcgp * nznl
+ghcl: rphf * ldzq
+dhgh: cftz * jpjc
+zzfj: wnvb * svvz
+ptmg: 3
+dvbb: qwgc * dzhp
+wjvz: crvz * mgrb
+dhpt: 17
+jsqn: 4
+phdb: 10
+zzlw: 1
+llcd: ztjw * rnlc
+crld: sdsg * fpdc
+jfnt: rqlv + hlqg
+dbsp: rzlh + jsqn
+wzdj: 5
+szcs: bglw * cnsh
+wwqm: bbdm * tlwp
+dnrs: 5
+mdgb: 6
+mmzm: ggzj + gwww
+cphp: 5
+wbrs: jqmv + pzdl
+qvnp: 2
+wpqr: 15
+ccmz: wncw * nzpn
+frtq: 5
+dpqn: 2
+grnb: 3
+brjj: lfjp * clfq
+hjbn: ndpn * qwvn
+msfq: gctq + blgq
+wtpm: 2
+gbsw: 3
+mfvr: llcq + slgm
+jcmg: cwhp + fjnj
+tfzl: 19
+spcz: 9
+cqpp: tpzb * sjld
+qqhb: 2
+nhst: cjpm - gghd
+ztjw: 2
+wwsn: 4
+dfcc: mwnz * pnbt
+zjsh: 5
+ppfp: 2
+rcss: qbqs * fqtd
+dcmv: 9
+njfv: tfmw + zbdh
+bvqq: bwhh * nlhz
+jswt: 5
+jpzc: 4
+zltq: 1
+pshd: lqlw - mdgb
+sgnm: 2
+gbbq: 5
+zmgl: 5
+ddll: 2
+vstm: 14
+tjdh: hvbp * hfmn
+pgfv: 3
+pdrt: ltvh / pnzl
+vpvf: 2
+jbdd: 2
+zwqn: ldnq - hcvv
+sgwj: vmhg - dwpl
+wjdd: 3
+qwdv: 2
+zbdn: qqfq * llcd
+cclh: nntn * vzgp
+cwlg: lmcq * pnbm
+bpwc: wgqm + rhlb
+jzpf: lbcq * dppz
+fstb: 3
+mczm: 2
+mttr: vhgq * qljl
+mmsw: 2
+wqtt: ndmc * jngv
+mbdz: 8
+mdgh: 8
+zhrc: phdb * pwnl
+wjlw: dwhf + dtns
+pbvr: ldrb * dnvq
+gdvb: rcns * pfjs
+ptvl: 2
+wqtw: 4
+zjnr: 3
+nqnn: fcvf * gbdg
+vhvp: bgnn + jcsh
+rqtc: 6
+wzcw: ldfp * jjbt
+ssgw: 2
+jhbf: 4
+ndmc: 7
+pvvz: 2
+zhmn: dfcc + tmvl
+nswf: fjms - wsmp
+mtjr: gdvg - qbsm
+zgbb: 3
+vpqm: jqqw + bwnj
+pqfg: 2
+bwcz: 5
+prht: 4
+qtrs: 5
+rslz: 3
+njls: tmmr * sctw
+tbqc: qtnb + twjg
+ntbv: 1
+dpvt: 6
+shhr: wncg * scgw
+nmfc: 2
+wmdt: 16
+hgqf: mgsh / pbff
+hnjc: 2
+hsgn: 4
+hgwl: vgsr + ttzb
+qmvr: 2
+gcvh: 3
+fhpp: 3
+jwsj: 2
+mjjf: cjsd / bvmw
+vgcg: lgcw + jtfj
+tthn: jcws + qdsg
+tfqj: 5
+mrjs: 3
+dcsb: 2
+prnv: 3
+dsqj: tsdf + wphl
+npst: 12
+gglj: 2
+htlq: 5
+sjjl: 20
+pnzq: tfnn * scpz
+ztwq: gtjp + wzfg
+zvbt: 3
+hrnz: 5
+bggc: sfsl + dpvt
+ssvq: 9
+jldh: hcqj * cqnp
+slmj: qvbl + npst
+dqgq: 17
+zthw: 2
+wnfn: jthn + lrsg
+nwpb: mmjw / dgll
+lpjr: whhj + tddn
+bpnb: ngsm - wrgb
+cdvw: lpjr * dmnw
+njgs: fpgc + ndff
+grrr: tfts * ljgz
+tmvl: ljvj * svgf
+nfmp: 3
+qchv: jbwv + mccg
+zjwz: qvhf * ghsz
+gvwl: cqpp + wltv
+mhvg: qnrt + ndjs
+gvld: 2
+gtwm: mdfq * qdfb
+wsgm: fddr * cqqs
+vnws: lhbs + thnm
+mvwj: 2
+dgzv: dbsp * bfhf
+tlzg: zpnf * pwmd
+brcq: 5
+ptmf: dwgb * wngv
+tbvd: mcbz * wmwn
+cqgf: ctlv * fppj
+vwjh: mmgs * rwdr
+qjnr: pzdz * wjpv
+cwhp: zqmp * zlwg
+fjtm: bmnn / ptqz
+dgls: wpvc - mgtj
+ltfj: 7
+bzfd: 3
+gzrg: 2
+hpnn: tzfp * nhsd
+hwcq: 2
+tbth: 7
+jsqg: 3
+qcql: lqvb * mrjs
+djgc: 2
+chbz: 3
+jwmg: 2
+wdfp: 5
+qvdd: ggdj + dmvg
+mlwd: rvmp * rvss
+dmnw: 3
+gdcr: 4
+pcvc: 9
+frjt: 3
+shdm: 5
+zcnh: 3
+wlhm: 3
+nnds: crwm + nwpb
+btjz: rdvt * pbvr
+ptvc: 2
+hhrr: 2
+tbhz: 16
+jdfc: bwpv * ncgt
+pwnl: qnsp + tqdf
+rlbl: wpcs * jqtg
+gzgp: 2
+mzhm: 4
+hdpf: lfdd * dbrj
+qvds: 5
+tdqv: 5
+pbnc: flft - dgwl
+mdfq: qvnp * wdms
+lqvb: 3
+nlhz: zbtz + mvnl
+vvlc: 2
+vpmd: 11
+glpb: 7
+vrzv: 2
+ppcg: bjhf * mrmn
+gprr: 2
+cddq: fqms * stcs
+lswz: rbhb + rstc
+bfcn: splb + cnhh
+mrmc: 3
+crvz: vnww + ztzz
+wqfv: vhcc + vsbz
+frzw: 7
+plft: 2
+svzm: dsfh * qhgn
+lcqf: lfqr + nwmw
+mzmr: 10
+nhtg: bnmd / zgbb
+vszc: qzgd - gjvn
+zfdl: 6
+hjrd: ldsg + cnrn
+mtzp: qzrv + tslf
+wsmb: rmpc * lgdd
+lhzr: 5
+szgj: 2
+qvbl: 1
+dwrj: twqp * ncrs
+fzlc: tscz * wjrm
+vrqz: 6
+rfmd: hwgg + brmm
+mslj: lfhs + nrst
+dzdf: vstl * bgrg
+jchz: 2
+dgwl: mbrc + jshl
+jdnv: 2
+wfbn: 4
+dbrj: 5
+tqpv: fzbj * vtdn
+bvrr: ffwm * gtzz
+svwm: 6
+tddq: vvfq * tbjg
+jsjd: wjlw * fqrr
+clpf: 5
+vbsd: hjwt / cgfp
+pszc: swmc + vqsz
+jqts: 6
+tssl: htvm + vjmf
+jrpn: 5
+qftr: 2
+zgvh: dctr * cjbz
+vzfh: sdwq + rgnv
+jvzc: jqhd * gwgn
+hfcs: 2
+hhvd: btbr * jjdn
+qdfb: 3
+dhvd: cphp * crld
+rwbw: 13
+nggd: 3
+cvpf: chvp * hflv
+ctgl: 2
+tvhs: 4
+gmpz: 4
+gjnm: frzw * qvgz
+qfwr: 2
+nwft: 5
+jszc: srsg + ffdv
+tdlf: 5
+qnwt: ddjh - dsqj
+wzvl: dvfp + msvj
+djfb: wnfr - bbmz
+ltcm: 2
+ddqm: 10
+zppb: 12
+hflv: 17
+vzmq: scmn * ddns
+scpz: 3
+nmpj: nhtg * vcss
+vtff: qszg / ztvq
+dnrb: 3
+mrlh: 2
+stcj: 5
+lmcr: 17
+sbhb: 1
+zrvl: 3
+rctr: 17
+cgjf: vgfd / fnzr
+hlnh: hwvn + wfbn
+hrzl: 10
+lfsd: 2
+hrcv: 20
+rhqb: 2
+qrhw: 12
+lmqf: 2
+gfbc: qngd * rrmg
+hlgt: 2
+phjw: cdvw * vljq
+rrws: 1
+gghd: jrgw * fmql
+frtl: 10
+rcdg: 12
+fjvf: crzd + lddf
+ggdj: wlgc * ljlw
+fmvt: 2
+pnmj: 3
+rcns: qfwr * rvrj
+zqmp: 3
+bsmz: 2
+rjzw: lgjm * vhng
+jdvv: hrtr * pnrp
+mbtd: nlpl + wtnp
+qjqs: 2
+tlfd: 4
+hvlb: 3
+ntsp: hjbn * mplg
+tlbr: 3
+flld: 5
+twcq: 5
+ggtc: pqqz * zcpn
+tscz: 3
+zhzl: 2
+shzs: 10
+mrwm: 4
+zlts: 14
+lwjz: 4
+lqvp: 9
+lgqq: 2
+gjhd: 3
+vqhz: mbdz * hrnz
+vqjf: jftm * vfsw
+dwpl: 5
+flnb: rjff + mjmc
+cnzm: hrgh * hfhn
+spzc: czsf * zvsm
+hzbh: 5
+ljlw: qtdr * zcwc
+vmpw: 5
+cwmm: tczg * gjnm
+nbjm: zsmn * jbmg
+dbmt: vjtq * vbfg
+wdtp: bwcz * btbn
+tjnh: fnqw + vstm
+phrq: 13
+ncjl: 7
+pcdv: fftf - ddqm
+ftrr: 3
+hrvl: 2
+cqnp: tdlf + hcrj
+nmcr: 3
+zmzt: sbhb + vjnd
+srfg: 5
+htvm: 18
+dnvd: zmfh * nqwb
+wfqq: prlb * nfpn
+smmb: gtzp * hqmp
+ftnh: ddst + ppvw
+wlth: 5
+psmd: 4
+nchp: 3
+splb: ddsl - lzpm
+flhq: nqnn * tfhp
+snmh: ccvp * plft
+zzmg: dwzg + grml
+lfqr: zvjs + dwnf
+mwcc: 5
+ldrb: 3
+zbfl: 2
+wjpv: 4
+hhqv: rgpp / qdnm
+wdwj: nldc / nwrd
+bncz: 3
+gjws: 12
+gvtw: zpwf - jhwt
+wlsr: wdtp * tglj
+dfjd: 3
+pjqj: 20
+qcdj: jbqm * hblv
+wjlz: 16
+njdb: tddg - glwg
+qwqr: vgsn * vvmv
+ztvq: 3
+gpgm: 2
+tddn: hpsd * qqhj
+bfvc: 2
+dnng: 2
+rjpw: hlgt * jlsn
+trdt: qclt + qzzs
+mljh: gbph * mwqn
+mjst: njcd + lcmg
+dvpw: 3
+lgjm: 2
+ncvh: vhhz + lzlg
+vmjm: brtb + mbgb
+hfhn: ssvs + ddcb
+wltv: wwlv * hfvw
+hcnw: 7
+lctq: 5
+jhfp: gjws + bmsg
+jzjb: 2
+dbrt: 2
+jngv: lgnh + wsgm
+gnfl: hvfd - lrlp
+qdcs: 4
+zpnf: 3
+fsjv: 2
+bvpg: 3
+zhbj: 3
+nwlt: chtn + sdfs
+pqqz: 5
+qwws: rpwc + pdzc
+lbpv: zqwh + fssb
+cfrc: lljs * ndlp
+gzrc: 2
+gvgb: 1
+hzrz: 3
+jltf: blcm + lptn
+jhqr: 3
+lbsd: qmzb / clpf
+zqnj: 18
+ftws: 19
+zvjs: fpjl + jptg
+fvml: vqhs + lvpq
+fzbj: 2
+gtjp: 1
+njcd: fqft + lqgq
+tmmz: nnds * qtwf
+pnbm: 4
+hwjm: bwmp * tbcf
+wphl: mzmr + qdjf
+hlhh: 2
+dgvf: 12
+dfzs: hqqq + ssgn
+hlbq: tvhs * vccs
+vbng: spqh * pwvm
+pbfj: wbwv + mzfm
+bfhf: cnnw + plmd
+zbbv: 12
+zczp: 17
+wwhh: rlbl + fsbf
+gbtc: hlwv + hlwz
+tpsm: 2
+pdbt: pjlf + srhs
+jqtg: 2
+fbcb: nfmp * tphz
+vvfq: qhnc + jldh
+spct: 8
+nhqw: jqqq / bsmz
+pvps: 2
+tggg: 12
+rjrf: htbc + frdt
+mzbz: 6
+dfbh: 3
+hsjh: lzfr / lqrj
+wqsg: hpzf * zlph
+rgdw: ntwd + pvps
+bqcz: 5
+gdmt: btml - rslm
+ndpt: 2
+mppn: 19
+shsv: 7
+gswq: 1
+rjzv: 5
+zhdj: jhrh * zhzc
+grml: pqfd + fdnr
+vqjn: 10
+wdnj: sgcw + cgcn
+dsdj: mbsv + mjjf
+ssnl: 11
+mddj: 5
+rmjp: vpvv * ppfp
+rvdz: 7
+vjmb: 2
+ljts: hpfc * hsjh
+lmqm: 1
+bhfn: dvct * fbcb
+ftzh: vqjn * crww
+hwgg: 2
+cqqs: 3
+hjgj: 2
+jztm: 13
+ghbc: 6
+wncg: 3
+rjmz: 2
+htbv: 11
+ndnp: 5
+rfzz: 3
+wfgc: dpqn + tlpz
+dvcz: 3
+qwmt: rrbn * zthb
+hwcm: 4
+mptj: zfdf * rptg
+tbcf: hbvn + zhvq
+sbqt: vfnm * pdjp
+tphz: 3
+pnbt: bszg + gnmt
+wnvb: gpfh + cmbf
+qbqs: hnfp + wjqd
+vshl: rbvb + pjvn
+jrpc: nrqq + hblr
+zcpn: 5
+fnzr: cvnq + tfcs
+vmfl: ctlr + qjjd
+dhhf: 5
+ndhf: cvpw / plrw
+zvcw: 6
+fjms: vsmj / lhzr
+bhtd: fnpj * dptd
+vfnm: 14
+hvfd: hpdp + mgpj
+twcs: tdrv * hvls
+tmlc: 3
+dsll: hgwl * vncm
+vcmt: vjcb * snbr
+bjnf: srgf * ftts
+scsh: 13
+qrpr: dbmt + zbbv
+llvf: 13
+dfpr: 7
+gvgd: 1
+lqpl: 4
+ngdf: nbrv * wwwc
+hbtv: 2
+lfrj: 2
+mbrc: tbzv - ptmf
+bhnw: qqbg + vwmm
+gcfc: 7
+bmfr: wflc * gzgr
+wbrc: lnwn * cjzn
+dgll: 2
+ddsl: 17
+vzgp: 5
+cwmp: 4
+ddns: rrph + zchz
+znfh: fgsd * hcss
+mvnl: 4
+mwjn: 2
+vwds: mpcm + blww
+brtb: 7
+zwls: 7
+hhpm: 3
+gtmz: 5
+pgcb: qdpl * dnrb
+tcrn: qwmt * lchq
+qzhb: frtq * drdc
+prcm: wjwl / czhc
+mtzt: fjvj * gjfs
+fdqz: brwh + chjr
+plrw: 2
+gqhb: mpgn * rvjs
+qtjc: 18
+hrtr: 4
+mwgz: 17
+snbr: 2
+dnsj: 3
+rrcs: qccw * ptmd
+rnds: 5
+nbdr: smmb / vjnm
+gczz: wjwd * jwsj
+hqmg: 17
+zzdv: nnjz * sfzn
+fhph: 3
+qwgc: 2
+dvhl: bpjh * rrpl
+rpwc: lqgf + stbv
+gntr: 2
+wwwt: 5
+jdcc: 1
+bmsg: 1
+blqg: vshl + dwrj
+vssd: nsmp * wgfd
+dfrr: zwqn / wwld
+vpqs: rgjv * hpcn
+wsns: 7
+thwh: prcm - spqb
+ndzs: qwhg + pqwf
+jfjm: 3
+hjdd: 2
+wwld: 6
+tgzr: ljtq + lvwj
+hvls: 4
+mdzm: 3
+fmjw: dphm * wmzn
+lbrm: dplt + ndvz
+vzlr: 3
+tlch: ljbd - fndj
+vcmg: cbdp + dvnp
+ncjj: lfrj * fbgz
+ssgn: fpvg * qdcs
+hbdh: sfqb * btcn
+stcs: mdwj + shhr
+mqzv: wzbf * rslz
+sjlw: 3
+smzb: zwnh + wmdt
+gpch: gwdq + zlgw
+lglv: 2
+wflc: tdch + zwds
+lpnz: 14
+svgf: 11
+thpp: pglz + hcrm
+ncsb: ljlz + jmdn
+tstt: 4
+cpcs: bbjt * hcwt
+pwhq: rqbs + nmzd
+tglj: jrjs * pjjr
+tlpg: zdfz * nmrr
+jjjt: 16
+gfhl: tdqv + cvpf
+ntzw: 2
+hcss: 3
+wlzg: 3
+zwnh: 7
+rrph: sqqt / brzn
+vstl: mrlh + dhhf
+bbdm: 2
+vdds: hwbc / jgjd
+tppt: 5
+ljnn: nczc + fvml
+nfcq: srfg * pvhj
+qnsp: 2
+drlq: 2
+qszg: vgcz + hwfd
+fzvm: 2
+rqhj: ptmg * wcrr
+vnch: mbtd * htlq
+lzpm: 4
+jptg: rwch * bhfj
+hdtm: 4
+jcjv: rhhp * cpcd
+wncw: nsvt + vwwf
+mgtj: 2
+wpjd: pszc * dhpr
+twjg: 11
+gjfs: 14
+hnfp: ldcd * wqns
+jmdr: scwc * wwsn
+lbng: hjnl + rzsf
+zprs: bjbz + nwft
+plmd: zzwt * gvwl
+mmgv: hhzv + lpnz
+ppwp: jhbf * qgjz
+zjrg: nbdr * tllp
+nrpb: fdbz * bmfs
+vnft: 14
+nbjv: 6
+lpcb: hjdv * mlgf
+bbnn: 3
+fjnj: 2
+fmmj: 6
+zthb: 5
+lqpm: 3
+lhcn: 4
+rnlc: 5
+sjld: 7
+ztzz: 1
+bcvh: 3
+lrlp: rqhj * bpct
+jjdn: 13
+tdrs: 2
+thqn: ffsg + fbqz
+tvwz: 3
+ltvh: 12
+vwwf: 4
+mrmn: 2
+cnnz: 2
+ffsc: 4
+mgrb: 2
+mcbz: 2
+gwdq: djgc * gbfm
+rrgm: zwls + snmh
+dtmn: 6
+tpzb: 3
+mpcm: sfcf * jpms
+dnpd: 2
+dqgt: tlsg * pdtt
+tnjc: bvlv + tbqc
+qvmf: ncsb + mgmb
+jppv: fmjd + fmzw
+lptn: lrhw * rbgz
+cjsd: cjrd + ngjn
+clfq: 3
+jtbh: dzjc * mnms
+dbht: pdbt + fcjn
+vtlz: mtpf + ccjz
+csjz: jqhz * qmvr
+nqfw: 5
+wtnt: qwph * dvbb
+rvnn: 3
+nfvw: 2
+zwmh: 5
+hqqp: nzmv / rwlz
+wcwl: 4
+dhtg: nqvq * blsh
+chht: mqzh * jmnq
+gdcz: vwgj - cqlp
+grtl: 3
+dzvt: sjjl + vvlc
+pbgc: 3
+bwjq: qjqs * bncz
+jhwt: 6
+dfmg: gcpq + jstz
+rrpl: bgtp / tnqc
+cppm: 3
+qlwz: 5
+pccw: 4
+qpls: 2
+dcfb: rjfs * rllj
+llqz: bljd * ssnl
+hvqw: nwcn * ldsz
+dwfs: 5
+qzwb: 12
+mtzq: 3
+gqpt: vzfc + tbpt
+qtwf: 3
+ngjn: qzlq + tghv
+htwg: 2
+zrdq: nvnh * lrvl
+djjg: ptfh * hmgd
+dzjc: 3
+djgj: 6
+mglc: 5
+fpgc: nfhv * cwlg
+brmm: dvhl / qhdp
+cnsh: 2
+lqzn: ccbp * swnz
+gwgn: vdps + phgf
+msnl: vwds / hfcs
+chpw: 5
+sgpg: 10
+lhrm: lwjz + fvrq
+mftq: 2
+tslf: hhvd * ddfm
+wncd: bpns + wqtt
+nwmw: bpnb * mzpf
+jmgz: rdgt * cfwv
+gbfc: 7
+vjtq: 4
+lsft: tncz - gpzt
+gpmn: jszb * brcq
+nczc: 5
+dnvq: 2
+fcvf: 2
+glhl: 1
+qgqp: tstv + mlhh
+vmqz: 3
+tlwp: 11
+ddst: 5
+gjqh: 2
+nmdl: 3
+qrhv: przl * gbbq
+lvwj: 16
+clnz: lsft * wqsg
+zfbf: fqtt / jppn
+rwfc: 2
+jbmg: nlsz / mlnn
+psbw: 7
+ljql: 13
+cvmv: jffp * szgj
+bwnj: mqzv + cvmv
+wwlv: 2
+qglp: 1
+qjhj: 2
+jzps: 2
+ffsg: tqlc - fjhp
+qjcn: tlch + qrcn
+fjhp: glzn * cmms
+rlpn: hnmz - qtfs
+szcb: cqfh + gnfr
+zqwg: gnfg * lqqg
+lrpn: 2
+sqqt: lvlm * trdt
+bvmw: 2
+zpvw: 5
+rwlz: 2
+schl: gcwt + nrcl
+drpt: lhzq * qmtr
+bqsb: dnfc - vlst
+jdfz: 5
+nlvv: 4
+rjmh: lctq * lfqf
+dwlz: cwmm + nwhj
+dvct: 3
+tcbz: rjvr / prjh
+tcfq: 4
+qvcb: hwls / hpcs
+mwhs: 16
+gznh: 5
+swnz: 3
+thcn: srrv * jdnv
+tmbg: 2
+ljsb: 16
+qnnz: ldmt * hhrr
+qdfm: mwhs * bfvc
+vgfd: qsqw * nhtr
+cvcc: mzrm * lmbd
+hzjv: mcdz * prnv
+zhfp: vrpd * wdnj
+mlgf: 14
+nmzd: rgbh * bpqn
+cmwp: wfjz * gjqh
+tfhp: 3
+root: zhfp + hghd
+vtnb: nrwj + rhwv
+ltpp: vcgw * hqdl
+wbhc: zgtr + scrb
+wzzh: 8
+ccpw: mhsd * zmzt
+mtgn: 16
+drgf: 13
+rnwm: 16
+hfhc: nwvr * zjsh
+tfts: 4
+tjjs: mcqw + fsqs
+glfz: 2
+ldzq: zzgp + nbjv
+cdgs: bldp + dtwp
+zlhb: 4
+wclf: dcmv * gdcr
+hszg: fcwq + htzb
+cwzd: 2
+jbgd: 5
+jbvr: 13
+vtdn: 7
+dppz: 2
+ldsg: gqpt + njgs
+tfrr: vpth * fmmj
+vvmr: 4
+ztjs: cvcc - gtnp
+jszb: 5
+tbpt: srhg + tblr
+fpvg: 2
+fdbd: 12
+ljlz: 19
+lnbd: lntr + ptrh
+twqp: zqnj + rqsh
+mhbb: hlnl * vbsd
+nzsq: 1
+rdvt: 2
+ppvw: 7
+ddjw: hlbq - vwjh
+wgrt: vdmp + lttb
+mvzw: plvm * qfht
+fszn: 7
+mchv: 5
+bwmp: 2
+drft: 4
+bgqp: 7
+trgv: tbvp - qzmc
+nwqw: vtlz * qchv
+ntwd: llqz / rdgj
+jfld: 7
+tblr: tlrl * rwbw
+dmvg: bqsb / jbdd
+nqwb: 3
+tnnr: 2
+hzcg: wmwz * nnwg
+fcjn: 12
+lcmg: 8
+cczl: qrpr + jgfg
+rgfm: vqrn + dzrf
+fpdc: 7
+pqdc: 5
+rdml: 1
+nttj: 3
+qszr: 7
+qmzb: qvzl * bgqp
+pwsb: 2
+lzdj: 19
+bldp: dvss * jhfp
+ljvj: rwtt + prvm
+vgsn: tcrn - ftws
+ngtf: 10
+wzbf: 2
+pvhj: 2
+fvdm: 14
+mmjw: gvtw * dlpb
+jlzw: 2
+qhnc: zczp * gzrc
+thvj: 4
+mgjp: 1
+qgnb: 3
+nmrr: 3
+bqht: pvvz * fppf
+fqtd: lcqs + jllt
+nznl: nslr + qlpn
+qlpn: 2
+rgjv: sqzv + hbdp
+mcqw: 6
+nnvb: ltfj * hcvh
+sdfs: 10
+mdmt: 2
+zhrs: jrcb * ndzs
+rgpc: qvql * dnng
+jllt: 7
+pzdm: gtwm / mrhp
+pzdz: ztwq + qglg
+czhc: 7
+jffp: 17
+mbqh: vtzz / zvzw
+hfmn: 2
+srlt: 2
+cmgv: lrwv + zgsr
+wdms: 7
+rvrj: 11
+lczw: ftrr * gbfc
+ncvt: sgpg + rrcs
+vttq: 6
+hcdc: 2
+vzbv: lfqp * qtgr
+wgqm: fdpp + dgls
+fnqw: 3
+lfhs: gpch * hpbj
+wfqw: spww - mlqm
+hqvl: cddq / qwvp
+fppf: jtbh + dqgt
+rjff: pdvb * fnrn
+bsvl: 10
+mtml: 3
+hrgh: 7
+ptfh: sgws / bgwg
+ndjs: drgf + pbhd
+gvrm: 4
+btsl: 4
+zqdc: rbhz * nnph
+fpjl: wtlp + dfjd
+cnqb: 2
+hsjv: hndr + jrtn
+nqmm: qgnb + wzvl
+fzzd: rchm * lswh
+qlmp: qtjc + dfnv
+nrzl: drhd * bcvc
+cfmn: lsbv / hlhh
+mtrw: 5
+rzlh: lzbf * jfzc
+gplc: vgcg + zvtn
+qvlz: mjgm + ghbc
+gnfr: 1
+spqh: 5
+csrz: jfjm + lqpl
+rwch: wtpm * dbgl
+hmsc: vmfl * cfgp
+rwdh: zpmq * mqfb
+vjnm: ppvj * ltcm
+lmlt: cwmp * cnqb
+ccjz: vqmg + pllq
+mqfb: wfqw + hhpm
+vsjp: 3
+lntr: 2
+zwcl: 17
+rpqc: hfvl * mbqh
+fcwq: hwwm * lfdm
+bttg: rlpn + ctvz
+lqrj: 2
+djqc: 5
+nrst: bppf * hcnw
+wfbv: dshb + ngpp
+svrv: 2
+zgtr: 5
+rzbs: bgwp * pwhq
+jzln: 3
+jnwm: 1
+lqgf: psmd * pqgn
+zjlh: 2
+lfqp: 3
+vbbs: mtzq * rfrs
+smbf: lbrm * dbfs
+jcsh: 11
+sdlv: 5
+lwjh: fwnf + jfqs
+tdlm: 19
+mzfm: tsjf * cwcv
+cfmj: wdng * ngsf
+gtzz: hhvv + ldrw
+phgf: 2
+ldtq: 5
+wfqb: scsh - mtrj
+jpmr: 2
+dvhc: hvlb * bdlr
+rwjl: ncjl - qtzz
+vsrz: 2
+ctlv: 3
+zdsb: 1
+ctvm: 8
+lswh: frtg * mdgh
+hpbj: vhvp - jbfp
+jbqm: 2
+bbjh: 4
+vdps: 7
+zqwh: njdw + vqsp
+drrb: phlw + jjrr
+mtrj: 2
+qdnm: 2
+fsbf: dtmn + qzhb
+fvcc: 11
+jstj: mdrm + zqwg
+hrwm: thcn + mnwm
+srhs: rdml + fmjw
+bzjj: vmqz * wqqh
+jwhp: vgts + bwwz
+zzgp: 5
+lfjp: 3
+bpll: djlv * fzmp
+qbsm: 2
+qqwz: lgpw - jjzc
+hqmp: dqgq - qwlr
+lfgf: 3
+tjzh: 2
+wqsn: zdcw * vmjm
+nhfw: pwtr * dfzs
+zrwd: 3
+pjvn: nqpj + twcs
+ntnq: 7
+qngl: tlpg + rfbv
+jmnq: zfbf + nrzl
+jjsp: 2
+jpjc: tthn - zvrs
+msqr: nzjg * zrvl
+fshf: 2
+jqhh: wlsr + vjvh
+ctwp: 2
+nrvs: 2
+cglc: 3
+zsjb: 5
+pbrt: fmbs + cpcs
+zmfh: mqbv + dhht
+glgt: hhqf + njnt
+pwvm: hwvg + ncjj
+vjcb: 3
+vjmf: tcfq * lnbv
+wgrs: 2
+vdbd: 2
+gtfc: tjwc + qcdj
+htjn: ltft * tllg
+hqdl: swvg - mcsc
+rvss: 16
+lqgq: 15
+bccm: czgc - gvgd
+bwsq: rwdh - cfrc
+vrpd: 8
+jjbs: 4
+gslb: fbws + rnwm
+vshr: 2
+mjzm: gzmq * tlfd
+grfl: 3
+jqhc: 3
+zvzw: 2
+prdt: glhl + hqvl
+rslr: hsjv * tdlm
+rldn: vzjm * jgls
+vwmp: brns + lczw
+wjwc: 2
+rgnv: 3
+gggz: 6
+bgzj: 5
+qfmj: qmql + jpmr
+hfrz: 13
+jjcq: 15
+dbgl: 5
+gmnc: 7
+rgfh: lrpn * htdr
+gtrl: 17
+fqms: 4
+lvlm: 2
+hqjf: tqfv * jjpm
+jdfv: gpff * tstt
+nsrm: 2
+dphm: 3
+fdbz: 3
+stnh: hnfd * fjrq
+nnph: 13
+lmcq: 8
+zfcc: 20
+tdrv: 7
+ngml: 2
+lzfr: cwzd * fmwb
+ghsz: zzvb * mbts
+svjq: mjst * hnmn
+tnrg: 6
+hvpg: qdfs + fvcn
+dbqh: 2
+mmgp: 2
+qsfc: mzgg + sjqq
+hhqf: dnhd + jbth
+vfbf: thlv - msff
+qhrs: nhst / zhfg
+brfg: tqpw * fhpw
+tpgr: zvbt * dtpf
+jjbt: 2
+dqbp: vjwh / jjsp
+scgw: 5
+phzt: gbsw * vrbp
+mwdw: 2
+ptls: 12
+jrcb: 2
+bgnn: htbv * fshf
+wnnf: bcpv - zqcf
+vnsp: qrhw + gzbc
+gbhr: nrld * blmh
+jfzc: 3
+mplg: vpqm + tcfl
+tppn: 2
+jtbp: nmhz - bsqc
+srcq: 3
+pttl: rfzz * dnvd
+jttb: zqvt * pcvc
+fnrn: 6
+vhpz: 7
+npgp: nhqr * rwfc
+cnhh: 2
+nlpl: 1
+wjmt: vflg * hmsc
+brng: 3
+mbts: lddp + nzsq
+qljl: vzbv + mbjt
+rhgt: mdwp * vpvf
+fwpn: 2
+mdwp: 3
+rvmp: 2
+zqtb: 3
+ncrs: 2
+mmrf: dmzf + rpqc
+zspq: jzpf * tpwt
+dsfh: 3
+mpgw: 5
+btrt: tbvd - prlg
+jbfp: lmlt + mvwj
+hgsr: 3
+rllj: 2
+wqgg: hrqs + rpgq
+nrcl: slmj + gvgp
+hpsd: 3
+qqwf: ncvt * bpwc
+tlsg: 5
+hfcg: frpb * jstj
+wmwz: jdfc + tmsb
+bglw: mptj + hhtm
+tdvc: tjvl * gglj
+tcfl: wlnb * fbnl
+njnt: sqrh + cjjr
+fjvj: ldtq + rvtm
+jqqw: hnzz * gplr
+lmvt: zqjl + wjmt
+cggn: 3
+gvgp: 11
+gpff: 3
+jngf: mnfg + cfmg
+jrgw: 4
+qzmc: zhrh + tdcr
+dghz: 4
+zhzb: fzlc + btrj
+mrhp: 7
+jthc: dhbb + zwwq
+jgjd: 4
+cgcn: fbmv + lcvr
+nnjb: 2
+ttsv: 13
+gdvg: 10
+mmgs: 3
+hbml: 4
+jppn: 4
+spzt: mswg * qqhb
+gbph: 5
+cfgt: gfdw - bfsf
+hwvg: dcpd * hqfv
+bwhh: 5
+lmgz: shdm * vdvd
+zhfg: 4
+jsbq: 2
+hdvc: dghz * wbrc
+vmgn: 5
+ddjh: jqmz + rzbs
+vnfc: qftr * wmwq
+hddh: zfcc * hjgj
+tqlc: crmv * sdlz
+lrsg: jctj - fwlf
+qqhj: spcz * ssvq
+ftts: qvnj / hgvp
+hpqd: thpp + hldm
+cfwv: dqvm - dgzv
+tmtp: 6
+rbvd: dzgh * jqhc
+bwpv: jcgd + vssd
+hzfj: wlch * bjvp
+hfgs: 2
+rbhb: rvnn * pmcp
+gzgr: 3
+ljfn: lmcr * pjqj
+gmbp: 3
+cvnq: 2
+ldnq: lcmt * njdb
+btbr: gtrl + lwfm
+qwvp: 4
+zpfh: 3
+tbhl: 2
+vjmp: ndnp + lbqs
+mbmd: 5
+hndr: 5
+qtzz: 1
+pftv: tsnb + mljb
+mjpf: gcww * ctwp
+srtz: 2
+dnlg: nsgc + lwjh
+cccn: rdhq * cfgt
+vpjw: qvjs / srtz
+nrqq: ggtc + tnrg
+hrnv: 3
+rjhr: 2
+fqrr: 4
+pdzc: rcwr * vdbd
+qvhf: 4
+gwlt: 2
+tmsb: fvdm * wdwj
+jthn: wgwv * wzdj
+sfqw: 2
+vhzd: pgcb - nrhb
+vvmv: mfrl * zbfl
+vrvs: 2
+tnvf: vzmq * vjmb
+rprp: znlm * tvwz
+vtzz: fwgr + frtl
+sdfm: 3
+dghp: 7
+qdpl: tdvc / dcsb
+hcvv: hcfd * thvj
+msdv: ntzz * zpvw
+spqb: dsdj * sgnm
+svzn: 2
+sdlz: csjp * cppm
+zsrs: 2
+dhpr: 5
+mwnz: 5
+gpfh: 9
+rnwn: ndmn * flld
+mqcz: 15
+jcgd: 1
+pzdl: 4
+dprw: wqsn + ljsh
+hhtm: mftq * rhqg
+trpm: 5
+nwvr: 3
+blsh: 4
+vhcc: qzvd * fdbd
+nlsz: dvgv * njfv
+vgft: 20
+mjzd: qnnz * glhz
+ppdj: 5
+scrb: mtgn + cnjg
+jtnc: 20
+rvjs: 3
+qnlg: gcld * ddgb
+jftm: 2
+sfss: ppwp / qwdv
+vqsp: gnfl + gntr
+mztz: 3
+zvpl: qqwz + pjsd
+dbrv: 14
+nzzq: 3
+tfnn: 3
+hjmt: 12
+nrbv: 2
+mqmv: sffq + zqfw
+wpmm: 5
+wqns: 2
+wlnb: 11
+fsgd: 3
+mbsv: dzvt + wsmb
+glhz: csjz + fsvs
+pdjp: ngvh - wpfw
+lrwv: 9
+jrdq: 16
+qhgn: 5
+gqbq: bsvl - grfl
+cwtn: znfh + tnjc
+qhdp: 3
+pmsr: pzfh + hcdp
+gbsl: sglg * gpgm
+rbfv: qdcm * sgwj
+jbth: msnl * hdtm
+rqbs: slbf * mbmg
+wjwd: vvmr * wdcn
+hbph: 2
+zpbn: prdm + tscq
+ghwp: 2
+swvg: cgnn + mldp
+vmhg: 18
+hpcs: 2
+frpb: 2
+jhdc: jdcc + vcbv
+pqwf: pbnc / ssbq
+qvql: ltpp + prvw
+fcvq: 5
+gqrj: 4
+qmql: lgfn / jjbs
+hlvd: 4
+sgcw: jtbp / spfg
+tqpw: 4
+hsrq: npbs + qcql
+nljr: dqbp * nttj
+mvvj: 2
+zdcw: fzzd + jppv
+gdgj: 5
+zcwq: 5
+jrtn: 2
+dplt: 16
+ccbp: httg + lsgf
+tsjf: 6
+bgcs: 6
+vgls: 19
+rsgc: 2
+vhhr: pwgf + gggz
+btnn: 3
+rpgq: 4
+dwhf: vhpz * fhph
+nqpj: 19
+njsw: 5
+czgc: hwcm + hvgv
+fsvs: jlbt * tpsm
+cjjr: 18
+ddmt: 3
+tntr: 2
+bdlr: wpjd + jqhh
+zgfb: 2
+fnwv: hghw * zrtf
+scjj: mlct * ttsv
+fflq: 2
+nlqt: 4
+hpnh: qvmf * bbqf
+qzct: 5
+tbtc: 3
+wfjz: ppjb * ffjf
+mzrm: plzr * rwfm
+hvbp: 7
+fwhp: lfjw * bqcz
+wtlp: lmgz + qwws
+zgsm: 2
+nvql: bbjh + blsf
+sqrh: 19
+gvwh: 3
+mtpf: mdgl - svjq
+gjdb: wqmg * pgfv
+sqtr: wdfp * mgmr
+zfnh: 2
+bjbz: chmm * dbqh
+hglh: 5
+bqcb: jczs + pqfg
+bvbt: rlfn * zpbn
+jqfj: zfdl * vgls
+tbvp: jfnt * dwqf
+wnfr: zzfj / zfnh
+ctvz: 8
+lgsd: vgqb * bzfd
+pdtt: pzzm + gzrg
+tbsd: fzpt * lbng
+lhbs: lccj * jzjb
+rdhq: 2
+rpnq: 3
+jjsd: 2
+jwtq: wwqm * pwsb
+rgpp: glpb + rrgm
+pnwt: 3
+frhj: 5
+fddr: 14
+slwr: szcs + nljr
+lmbd: hvqw + rftc
+gqpf: ptls + ljpg
+srhg: cglc * jmjw
+nsgc: ltsn + jbgd
+lppw: 4
+qvlq: qhrs - hpnh
+hgrg: 2
+vjvh: bmfr * blqg
+dwnf: tmzr / zthw
+clzb: 5
+pglz: zhdt * gqhb
+qdjf: hmhn * mdmt
+pdvb: vbgt + bwjq
+vqmg: jqcj * fjtm
+hnfd: dnrs + vsrz
+wqmg: 2
+chtn: 1
+ccpc: 4
+qlwn: mnmq + tgzr
+ftjl: 2
+fphs: 3
+lhzq: ncrd + jqhr
+hhvv: zsbm + jltf
+mmzw: 15
+hhsl: zrdq * zlbn
+pmpn: 7
+dwlf: sszs * dfpr
+mqzh: mtrz * mbmd
+ndff: 4
+jqhz: 20
+dnfc: vnws / ttbq
+zdbn: wsdr + zdsb
+zqcf: 4
+fbmv: 11
+fsbz: 2
+nnth: fscc * wrst
+bgwp: 4
+nrpt: 7
+hnwb: vbbs * wlth
+wcvw: djfb + jrpc
+gtpb: wzzh + ddmt
+zvsm: 11
+hrmm: 3
+qtfs: 5
+fhmj: 12
+tblh: vbng + hhsl
diff --git a/day21/uppga.c b/day21/uppga.c
@@ -0,0 +1,15 @@
+#include "common.h"
+
+int main(int argc, char** argv)
+{
+ char** lines;
+ size_t nlines = readlines(&lines, "input");
+ printf("#lines: %lu\n", nlines);
+
+ monki* m = parse(lines, nlines);
+
+ int64_t v = mcompute(monkindex("root"), m);
+ printf("%lld\n", v);
+
+ free(m);
+}
diff --git a/day21/uppgb.c b/day21/uppgb.c
@@ -0,0 +1,32 @@
+#include "common.h"
+
+int main(int argc, char** argv)
+{
+ char** lines;
+ size_t nlines = readlines(&lines, "input");
+ printf("#lines: %lu\n", nlines);
+
+ monki* m = parse(lines, nlines);
+
+ size_t l_root = left_tree_root(m);
+ size_t r_root = right_tree_root(m);
+ printf("l_root = %zu, r_root = %zu\n", l_root, r_root);
+
+ size_t h_root = l_root;
+ size_t n_root = r_root;
+ if(humn_subtree(l_root, m)) {
+ printf("> humn in left\n");
+ } else {
+ printf("> humn in right\n");
+ h_root = r_root;
+ n_root = l_root;
+ }
+
+ int64_t match = mcompute(n_root, m);
+ printf("> want to match %lld\n", match);
+
+ int64_t revd = reverse(h_root, m, match);
+ printf("%lld\n", revd);
+
+ free(m);
+}
diff --git a/day22/Makefile b/day22/Makefile
@@ -0,0 +1,20 @@
+CC=clang
+UTILS=../utils/reading.o
+INCLUDES=-I../utils
+
+all: utils common.o uppga uppgb
+
+common.o: common.c common.h
+ $(CC) $(CFLAGS) -c common.c $(INCLUDES)
+
+uppga: $(UTILS) common.o uppga.c
+ $(CC) -Wall -o uppga uppga.c common.o $(UTILS) $(INCLUDES)
+
+uppgb: $(UTILS) common.o uppgb.c
+ $(CC) -Wall -o uppgb uppgb.c common.o $(UTILS) $(INCLUDES)
+
+utils:
+ make -C ../utils
+
+clean:
+ rm -rf common.o uppga uppgb
diff --git a/day22/common.c b/day22/common.c
@@ -0,0 +1,433 @@
+#include "common.h"
+
+static inline size_t get_maxwidth(const char** lines, const size_t nlines)
+{
+ size_t i;
+ size_t max = 0;
+ for(i = 0; i < nlines-2; i++) {
+ size_t ll = strlen(lines[i])-1;
+ if(max < ll) max = ll;
+ }
+ return max;
+}
+
+board new_board(const size_t h, const size_t w)
+{
+ board b;
+ b.h = h;
+ b.w = w;
+ b.data = calloc(h * w, sizeof(*b.data));
+
+ return b;
+}
+
+static inline void set_board(board* b, const char** lines, const size_t n)
+{
+ size_t i,j;
+ for(i = 0; i < n; i++) {
+ size_t ll = strlen(lines[i])-1;
+ for(j = 0; j < ll; j++) {
+ if(lines[i][j] == '.') {
+ b->data[i * b->w + j] = FRE;
+ } else if(lines[i][j] == '#') {
+ b->data[i * b->w + j] = STP;
+ }
+ }
+ }
+}
+
+static inline pos initial_pos(const board* b)
+{
+ pos r;
+ r.dir = EAST;
+ r.y = 0;
+
+ size_t i;
+ for(i = 0; i < b->w; i++) {
+ if(b->data[i] == FRE) {
+ r.x = i;
+ return r;
+ }
+ }
+
+ fprintf(stderr, "ERROR! No initial positon found\n");
+ exit(1);
+ return r;
+}
+
+static inline void print_board(const board* b)
+{
+ size_t i,j;
+ for(i = 0; i < b->h; i++) {
+ for(j = 0; j < b->w; j++) {
+ switch(b->data[i * b->w + j]) {
+ case NON:
+ printf(" ");
+ break;
+ case STP:
+ printf("#");
+ break;
+ case FRE:
+ printf(".");
+ break;
+ default:
+ printf("?");
+ }
+ }
+ printf("\n");
+ }
+}
+
+static inline void print_board_with_pos(const board* b, pos* p)
+{
+ size_t i,j;
+ for(i = 0; i < b->h; i++) {
+ for(j = 0; j < b->w; j++) {
+ if(p->x != j || p->y != i) {
+ switch(b->data[i * b->w + j]) {
+ case NON:
+ printf(" ");
+ break;
+ case STP:
+ printf("#");
+ break;
+ case FRE:
+ printf(".");
+ break;
+ default:
+ printf("?");
+ }
+ } else {
+ switch(p->dir) {
+ case NORTH:
+ printf("^");
+ break;
+ case EAST:
+ printf(">");
+ break;
+ case SOUTH:
+ printf("v");
+ break;
+ case WEST:
+ printf("<");
+ break;
+ default:
+ printf("?");
+ }
+ }
+ }
+ printf("\n");
+ }
+}
+
+move* get_moves(size_t* nmoves, const char* line)
+{
+ size_t ll = strlen(line);
+ move tmpm[ll];
+
+ //x assumes that line starts and ends with numbers
+
+ size_t i = 0;
+ uint64_t tmp;
+ while((line = sread_next_u64(&tmp, (char*) line)) != NULL) {
+ tmpm[i].n = tmp;
+ tmpm[i].turn = '\0';
+ i++;
+ if(line != NULL && line[0] != '\n') {
+ tmpm[i].turn = line[0];
+ tmpm[i].n = UINT64_MAX;
+ line++;
+ i++;
+ }
+ }
+
+ move* r = malloc(i * sizeof(*r));
+ memcpy(r, tmpm, i * sizeof(*r));
+
+ *nmoves = i;
+
+ return r;
+}
+
+void make_move(pos* p, const board* b, move m)
+{
+ if(m.n == UINT64_MAX) {
+ assert(m.turn == 'R' || m.turn == 'L');
+ if(m.turn == 'R') {
+ p->dir = (p->dir + 1) % NDIR;
+ } else {
+ if(p->dir == 0) {
+ p->dir = NDIR-1;
+ } else {
+ p->dir = p->dir - 1;
+ }
+ }
+ } else {
+ size_t oldx = SIZE_MAX, oldy = SIZE_MAX;
+ size_t steps = 0;
+ switch(p->dir) {
+ case NORTH:
+ do {
+ oldy = p->y;
+ if(p->y > 0 && b->data[(p->y-1) * b->w + p->x] == FRE) {
+ p->y--;
+ } else if(p->y == 0 || b->data[(p->y-1) * b->w + p->x] == NON) {
+ size_t y = b->h-1;
+ while(b->data[y * b->w + p->x] == NON) {
+ y--;
+ }
+ if(b->data[y * b->w + p->x] == FRE) p->y = y;
+ }
+ steps++;
+ } while(oldy != p->y && steps < m.n);
+ break;
+ case EAST:
+ do {
+ oldx = p->x;
+ if(p->x < b->w-1 && b->data[p->y * b->w + p->x + 1] == FRE) {
+ p->x++;
+ } else if(p->x == b->w-1 || b->data[p->y * b->w + p->x + 1] == NON) {
+ size_t x = 0;
+ while(b->data[p->y * b->w + x] == NON) {
+ x++;
+ }
+ if(b->data[p->y * b->w + x] == FRE) p->x = x;
+ }
+ steps++;
+ } while(oldx != p->x && steps < m.n);
+ break;
+ case SOUTH:
+ do {
+ oldy = p->y;
+ if(p->y < b->h-1 && b->data[(p->y+1) * b->w + p->x] == FRE) {
+ p->y++;
+ } else if(p->y == b->h-1 || b->data[(p->y+1) * b->w + p->x] == NON) {
+ size_t y = 0;
+ while(b->data[y * b->w + p->x] == NON) {
+ y++;
+ }
+ if(b->data[y * b->w + p->x] == FRE) p->y = y;
+ }
+ steps++;
+ } while(oldy != p->y && steps < m.n);
+ break;
+ case WEST:
+ do {
+ oldx = p->x;
+ if(p->x > 0 && b->data[p->y * b->w + p->x - 1] == FRE) {
+ p->x--;
+ } else if(p->x == 0 || b->data[p->y * b->w + p->x - 1] == NON) {
+ size_t x = b->w-1;
+ while(b->data[p->y * b->w + x] == NON) {
+ x--;
+ }
+ if(b->data[p->y * b->w + x] == FRE) p->x = x;
+ }
+ steps++;
+ } while(oldx != p->x && steps < m.n);
+ break;
+ default:
+ fprintf(stderr, "ERROR! Unknown direction encountered\n");
+ exit(1);
+ }
+ }
+}
+
+int64_t score_pos(pos* p)
+{
+ int64_t dirscore;
+ switch(p->dir) {
+ case EAST:
+ dirscore = 0;
+ break;
+ case SOUTH:
+ dirscore = 1;
+ break;
+ case WEST:
+ dirscore = 2;
+ break;
+ case NORTH:
+ dirscore = 3;
+ break;
+ default:
+ fprintf(stderr, "ERROR! Code 404\n");
+ exit(1);
+ }
+
+ assert(dirscore < 4);
+ assert(dirscore >= 0);
+
+ int64_t row = (int64_t) p->y+1;
+ int64_t col = (int64_t) p->x+1;
+
+ return 1000 * row + 4 * col + dirscore;
+}
+
+size_t parse(board* b, pos* p, move** m, const char** lines, const size_t nlines)
+{
+ size_t maxw = get_maxwidth(lines, nlines);
+
+ *b = new_board(nlines-2, maxw);
+ set_board(b, lines, nlines-2);
+
+ *p = initial_pos(b);
+
+ size_t nmoves;
+ *m = get_moves(&nmoves, lines[nlines-1]);
+
+ return nmoves;
+}
+
+pos map_offboard(int64_t x, int64_t y, pos* p)
+{
+ pos r;
+ if(y == -1 && 50 <= x && x <= 99) { /* a,1 */
+ r.x = (size_t) 0;
+ r.y = (size_t) (x + 100);
+ assert(p->dir == NORTH);
+ r.dir = EAST;
+ } else if(x == -1 && 150 <= y && y <= 199) { /* a,2 */
+ r.y = (size_t) 0;
+ r.x = (size_t) (y - 100);
+ assert(p->dir == WEST);
+ r.dir = SOUTH;
+ } else if(x == 49 && 0 <= y && y <= 49) { /* b,1 */
+ r.x = (size_t) 0;
+ r.y = (size_t) (149-y);
+ assert(p->dir == WEST);
+ r.dir = EAST;
+ } else if(x == -1 && 100 <= y && y <= 149) { /* b,2 */
+ r.x = (size_t) 50;
+ r.y = (size_t) (149 - y);
+ assert(p->dir == WEST);
+ r.dir = EAST;
+ } else if(x == 49 && 50 <= y && y <= 99) { /* c,1 */
+ r.y = (size_t) 100;
+ r.x = (size_t) (y - 50);
+ assert(p->dir == WEST);
+ r.dir = SOUTH;
+ } else if(y == 99 && 0 <= x && x <= 49) { /* c,2 */
+ r.x = (size_t) 50;
+ r.y = (size_t) (x + 50);
+ assert(p->dir == NORTH);
+ r.dir = EAST;
+ } else if(y == 150 && 50 <= x && x <= 99) { /* d,1 */
+ r.x = (size_t) 49;
+ r.y = (size_t) (x + 100);
+ assert(p->dir == SOUTH);
+ r.dir = WEST;
+ } else if(x == 50 && 150 <= y && y <= 199) { /* d,2 */
+ r.y = (size_t) 149;
+ r.x = (size_t) (y - 100);
+ assert(p->dir == EAST);
+ r.dir = NORTH;
+ } else if(x == 150 && 0 <= y && y <= 49) { /* e,1 */
+ r.x = (size_t) 99;
+ r.y = (size_t) (149-y);
+ assert(p->dir == EAST);
+ r.dir = WEST;
+ } else if(x == 100 && 100 <= y && y <= 149) { /* e,2 */
+ r.x = (size_t) 149;
+ r.y = (size_t) (149-y);
+ assert(p->dir == EAST);
+ r.dir = WEST;
+ } else if(y == 50 && 100 <= x && x <= 149) { /* f,1 */
+ r.x = (size_t) 99;
+ r.y = (size_t) (x - 50);
+ assert(p->dir == SOUTH);
+ r.dir = WEST;
+ } else if(x == 100 && 50 <= y && y <= 99) { /* f,2 */
+ r.y = (size_t) 49;
+ r.x = (size_t) (y + 50);
+ assert(p->dir == EAST);
+ r.dir = NORTH;
+ } else if(y == -1 && 100 <= x && x <= 149) { /* g,1 */
+ r.y = (size_t) 199;
+ r.x = (size_t) (x - 100);
+ assert(p->dir == NORTH);
+ r.dir = NORTH;
+ } else if(y == 200 && 0 <= x && x <= 49) { /* g,2 */
+ r.y = (size_t) 0;
+ r.x = (size_t) (x + 100);
+ assert(p->dir == SOUTH);
+ r.dir = SOUTH;
+ } else {
+ fprintf(stderr, "Bad position (%lld, %lld)\n", x, y);
+ exit(1);
+ }
+
+ return r;
+}
+
+void make_move_b(pos* p, const board* b, move m)
+{
+ if(m.n == UINT64_MAX) {
+ assert(m.turn == 'R' || m.turn == 'L');
+ if(m.turn == 'R') {
+ p->dir = (p->dir + 1) % NDIR;
+ } else {
+ if(p->dir == 0) {
+ p->dir = NDIR-1;
+ } else {
+ p->dir = p->dir - 1;
+ }
+ }
+ } else {
+ size_t oldx = SIZE_MAX, oldy = SIZE_MAX;
+ size_t steps = 0;
+ do {
+ oldy = p->y; oldx = p->x;
+ switch(p->dir) {
+ case NORTH:
+ if(p->y > 0 && b->data[(p->y-1) * b->w + p->x] == FRE) {
+ p->y--;
+ } else if(p->y == 0 || b->data[(p->y-1) * b->w + p->x] == NON) {
+ int64_t wbx = (int64_t) p->x;
+ int64_t wby = ((int64_t) p->y) - 1;
+ pos tpos = map_offboard(wbx, wby, p);
+ if(b->data[tpos.y * b->w + tpos.x] == FRE) *p = tpos;
+ }
+ steps++;
+ break;
+ case EAST:
+ if(p->x < b->w-1 && b->data[p->y * b->w + p->x + 1] == FRE) {
+ p->x++;
+ } else if(p->x == b->w-1 || b->data[p->y * b->w + p->x + 1] == NON) {
+ int64_t wbx = ((int64_t) p->x) + 1;
+ int64_t wby = (int64_t) p->y;
+ pos tpos = map_offboard(wbx, wby, p);
+ if(b->data[tpos.y * b->w + tpos.x] == FRE) *p = tpos;
+ }
+ steps++;
+ break;
+ case SOUTH:
+ if(p->y < b->h-1 && b->data[(p->y+1) * b->w + p->x] == FRE) {
+ p->y++;
+ } else if(p->y == b->h-1 || b->data[(p->y+1) * b->w + p->x] == NON) {
+ int64_t wbx = (int64_t) p->x;
+ int64_t wby = ((int64_t) p->y) + 1;
+ pos tpos = map_offboard(wbx, wby, p);
+ if(b->data[tpos.y * b->w + tpos.x] == FRE) *p = tpos;
+ }
+ steps++;
+ break;
+ case WEST:
+ if(p->x > 0 && b->data[p->y * b->w + p->x - 1] == FRE) {
+ p->x--;
+ } else if(p->x == 0 || b->data[p->y * b->w + p->x - 1] == NON) {
+ int64_t wbx = ((int64_t) p->x) - 1;
+ int64_t wby = (int64_t) p->y;
+ pos tpos = map_offboard(wbx, wby, p);
+ if(b->data[tpos.y * b->w + tpos.x] == FRE) *p = tpos;
+ }
+ steps++;
+ break;
+ default:
+ fprintf(stderr, "ERROR! Unknown direction encountered\n");
+ exit(1);
+ }
+ } while((oldy != p->y || oldx != p->x) && steps < m.n);
+ }
+}
+
+
diff --git a/day22/common.h b/day22/common.h
@@ -0,0 +1,40 @@
+#ifndef COMMON_H_
+#define COMMON_H_
+
+#include <stdio.h>
+#include <stdint.h>
+#include <assert.h>
+#include <reading.h>
+
+#define FRE 1
+#define STP 2
+#define NON 0
+
+#define NDIR 4
+
+enum direction {NORTH, EAST, SOUTH, WEST};
+
+typedef struct {
+ size_t h;
+ size_t w;
+ uint8_t* data;
+} board;
+
+typedef struct {
+ size_t x;
+ size_t y;
+
+ enum direction dir;
+} pos;
+
+typedef struct {
+ uint64_t n;
+ char turn;
+} move;
+
+size_t parse(board* b, pos* p, move** m, const char** lines, const size_t nlines);
+int64_t score_pos(pos* p);
+void make_move(pos* p, const board* b, move m);
+void make_move_b(pos* p, const board* b, move m);
+
+#endif
diff --git a/day22/einput b/day22/einput
@@ -0,0 +1,14 @@
+ ...#
+ .#..
+ #...
+ ....
+...#.......#
+........#...
+..#....#....
+..........#.
+ ...#....
+ .....#..
+ .#......
+ ......#.
+
+10R5L5R10L4R5L5
diff --git a/day22/input b/day22/input
@@ -0,0 +1,202 @@
+ ..#......#........................#...#......#.............#...........#......#...#............#....
+ ......#..........#...........#....................#....................................#..#.........
+ ...............#.##.............##...#..#..#.......#.#............#.#.#...#..................#......
+ ...............................#..#........................#......#...#............#................
+ .#....#.......#....#.......#.............#..#...........#.............#............#........#.......
+ ........#..................#.#........#......#.......#............#....##.........#.........#..#....
+ #.........................##..............##...................#.....##..............#..............
+ #............................................#..........#......#.#..........#...........#....#......
+ ..........................#.#.....#......#.....#...................................#.....#......#...
+ .....#...........##.....................................................##.#...#....................
+ .....#....#.#....................#.#....#.................#.........#.#................#...#........
+ #..........#.#.........#....#...........................................##......#...........#......#
+ .........#..##......#.....#...........#....##.....#........#..##....#................#..............
+ .....#..........##...........#................#.......#......#..............#......#.......#........
+ ........#......##......#..........#......#...................................#......................
+ ......................#..#........................................#.......#..........#.....#........
+ .#...#......#......#...................#....#..##...............##...#........#......#..............
+ .##...#.#....#.......##.......................#...........#...........#....#.#.........##........#..
+ ...#......................#.#...#............#......#............#....#.......#.............##......
+ .......................#..................#....#.....#.......#..............................#.......
+ #............#......#......#.#.....#.............#......#..............#.........#.......#....#..#..
+ ............................##.........#..........#......#......#.............#..................#..
+ ..............#..#.....#..#................#..#.................##.....#...........#.....#...#.##...
+ ...#..#...#.........###.........#....................................#......#....#.................#
+ ................#.......#.........#.........................#......#.........##.......#......#.#....
+ ...#........#....#.....................#.................#.#......#.........#.......#....#..##...#.#
+ .....#.....#.....#........#.....................#..#....#..............#...............#.........#..
+ ................#.............##.#.#..#..#.#..........#......#...#.#..............#...#..#..........
+ .......###......#..#......#........#.........................#......##........#.#.......#..##.#.....
+ .#.......#................#................#.....##..............................#...#..............
+ #...........................#...........#....##..........................#...........#.........#....
+ .....................................#..........#.................#.#...........#..................#
+ ....#...#.##.............#..#................................#.............#.......##...............
+ ......##............#...#....#.........#...............#.......#............#..........#........##..
+ ..#...#.................#.............#..#................#..........#.......#......................
+ ......#..........................#...#.......##..#..#...........................#....#.#......#.....
+ ...##........#.............#.#.......#...................#............##.........#.....#............
+ ...........#...................#.#.................#..............#.........#........##..#.....##...
+ .........#.....#.#......................................#.............#..............#....#.........
+ ...##.#.......#..#.......#........##..........#.............................#....#.........#.....#..
+ #.........#..........#......##......#.......#.........................#....#.....##............#....
+ ...#.#.#.......#.....#......#.............#......#.#............#....#.................#............
+ .........#......#......#..#....#.#.#..#.....#.....#......##.....#...#.#..................##..#.##...
+ .......#......#........#...#.........#..#..........#..................#.............#.......#.......
+ ......................#.......#................#......#.##.......##...........#....#........##......
+ ..#........#..#.....................##.................#...##....#..................#...###.....#...
+ .#...........................#........#......................#.......#..............................
+ ....................#..#...#....#...........#.............................#.....................#...
+ .....#.....#.....................#...#.#....................................#....#....###.......#.#.
+ ....................#.....#......#................#........##...............#.......................
+ ...............#.#.............#.....#.#......#...
+ .........#...#.#.#................................
+ ........................#..............#..........
+ .....#........#......................#.##.....##..
+ #................#.........................#.....#
+ .#....#.............#.......#....#.#......#.......
+ ...#........#...........#.....#...........#......#
+ ...#............#........#......#............###..
+ .#.........#...#..............#.#.......#.........
+ .....#...........................#........#......#
+ ..........#.....#....#.##.............#...#.......
+ .###....##................#..............##......#
+ ......#.#..........#...................#........#.
+ ....................##...........#................
+ ........#..........##.............................
+ .....#.#.................#...........#.....#......
+ ....#.................#...........................
+ ..................................#...............
+ .....#.......#............#......#..#....###..#...
+ .#....#.....................................#.....
+ ..##........................#...........#.#.......
+ .......#.......#.#................#......#........
+ .................#.#....#.............#.##........
+ ...#.............................#.........#......
+ ..#........#...............#..................#...
+ ..............................#......#............
+ .#..........##.#..............#.........#....#..#.
+ ..#............##..........#..#..........#......#.
+ .....#.......#......#......................#......
+ .............................##.............#.....
+ ..............................#...................
+ ....#......#.#..........#......#.........#..#.....
+ ........#.....#....#..##.#.#.#....................
+ ...............##......................#.......##.
+ .......#..............#........#.......#...#....#.
+ ......#.............#...#..#.#.......#.##.....#...
+ .................#....#..#..............#.........
+ ...#......#....#.....#.......#........#...#.#..#..
+ .........#....#.....#.............##..............
+ ......................#...........................
+ ......#...#.........#.............................
+ ......#.#......................................#..
+ ....#..........#................#....#.#.#........
+ .........#.................##.......#.......#.....
+ ............#....#...#...............##....#.#...#
+ ....................................#.............
+ #..#..#...........#.................#.#...........
+ ....#.......................#........#.#...#......
+ #............#.......................#........#...
+ .........#......#.......#.#..............#.##....#
+....#...........#....#.............................#.......#........#.#.#..##....#.##......#......#.
+...#..........................#.##.#.............................#.................###.#............
+...........#.......#.#..................................#............................#.#........#...
+....#..............#.#......#.#.#.#...#.......................#.............#............#....#.#...
+.............#....#..............#..#......#..........#...................#....#......#......#......
+..#...........#..#.......#.............#...........................#....#.#..#............#.........
+.................#.......#.#..............##....................................##.#................
+.....##..#...#...#....#................#.#....#..................#..................................
+....#............#...........#.#.................#.....................#....................#...#...
+............................#...#..............##..#....#....#.....#..........#.....................
+.......#.......#.#......##.........#................#.#..#..#.................#.....................
+..#...........................##.............#...................................#...#.#............
+..#..........................#.##.......#...............##.......................#.......#...#......
+...................#..#.......................#...##.........................#..................#...
+...##..........#......................#.#...............#.#.....#.#...............................#.
+................................#...........##.....#.....#.........#.........#...........#..#..#....
+..............................#....#.....#............#................#.##..................#..#.##
+.....................#.#......#.....#...#.....##.............#......#.#.............................
+.....##.................#.......#.................#.##............#..........#..#.....#..#..........
+#..#................#..........#.........#..#....................#......#..........#..........#.....
+............#..............##................#.#...#........##.........#......#..#......#......#....
+....##....................#.........................#....##...............#...###.....#.............
+.......#..............#...........##..####.....#.....#.####...........###......#....................
+......#....#...##...........#.....#.................#.....##.....#......#.........##................
+....#................................................#.........#..........................#..#.##...
+##...#..........................#...#.............#.......................#.#..#.........###..#...#.
+#...........#.#.....................#...............#.............#..#.......#......................
+....#..#.......................#...#..........#......#.#.....#..................................#...
+...............................#...#..............#..#..#..........#.........................#......
+....#.......................#.........#........................................#.............#......
+....................#...........#..........#.....#......#..........#............#.........#.....#...
+.....#...#..........#...............#..#............#...##.................#...............##.......
+.........................#.................................#........................#.....#..#......
+...........#.#..#........#.#....##........#...#.........................#.#.........................
+...............#.......#..#...#....#.......................#......................................#.
+.........##..#......#..##...#............#..#.....#......##..............................#..........
+.............................#.#.#...................#............#....#.........#..##....#.........
+........#.......#.....#..........#.................................#........................#....#..
+#.......#.........#...........#...........................#.##.#..........#....#.##.....#.........#.
+.....#..........#..........#...##................#..........#....................#.....#..#.#......#
+.........................#..#..........#...#.......#..............#.#..#.#...#...#..................
+...###.....#.#...............#........................................#.#.#...#.#........#...#......
+......#.........#.........................#......#.....##..............#........##...#..............
+...........#.........#...........#..#...#....#..................#.#....#........#...#.....#.........
+......##...#...............#..................................#.#........#....##.##.#...............
+....#..#..................................#..#....#....................................#..#.#.......
+.....#.................#.#....#...#.#.....................#.......................................#.
+.#..#.#.........#.........#..............##.#....#..#.#......##............##..........#........#...
+...........#.....#.......#..#.................................#............#........................
+...#.#.....#........#................#.#.....#.....................#...#............#..##...........
+....##..............#..............###..##........
+............##........##..........................
+.#.#.......#...................#..................
+....#..................................#....#.....
+#.......#..#...#....#..#..#.............#.........
+........#...#.................#...........#.......
+.#...#..........#.........#.............##........
+.......#...................#........#........#....
+#......##..#.............#....#.#.#.........#.....
+....................#..#..........................
+...#.......#........#....#.............#.#.....#.#
+.#..............#...#........#....#...............
+.........................#....#...##.......#......
+...#.............#..#..........#.#.#....#...#.....
+.#...............#...#...#....#.......#...........
+...#............................##............#...
+...#...........................#...........#..#...
+..#......#...........#...#...........##...#..#....
+........#.......................#..........#....#.
+...............#..............#......#.......##...
+..........#.....#.......#.....#...........#.#.....
+#...#....#......#..#........#.........##......#.#.
+.....##....#..........#.......#...................
+#...#.....................................#......#
+....#....#..#...#....#..............#..#..........
+............##...........#...#....................
+........#........#....#........#...........#......
+..#..#....................#..............#...#....
+...............#..........#.##....................
+.#.....#......#...................................
+.....................................#............
+...#......#....................#.........#.......#
+..........#..........#..........#....#............
+.....................#.....#..............##......
+................#..............#......#....#......
+.......#....#.##..##..#..............#...#.....#..
+.....#.......##...............#........#.......#..
+.......#...........#..............................
+.#..........#...........................###.#..#..
+...#......#..#..............#.....................
+...........##....#..............##......##........
+............#.#........................#.#.#....#.
+........#..............#.................#........
+.......#....................##....#............#..
+..#.##..............#......#............#.........
+##..#...........#..#....#.....#...........#.#.....
+.#.#.......#...#..#.............#.................
+......................................#.....#.....
+.....#.#.........#................................
+..................#........#........#.##..........
+
+9L8R50R46L28R44L26R40R36L17L29L36L6R31L25R12L39L10R38L16R49L42L20R5L37L19R8L13R15R2R37L25R39L14L48R25R45R24R11R50R14L15L15L31L41R35L4R23L48L26R28L24L13R17R19R7R16L35L13L3L44L10R24R13L9R7L10R3L49L48R17L22L27R31L32R41L30R16L20L50L11R23L12R12L2R14L13L39L29L30R8L8R33L49L14L40R36L5L30L2L40L15R34L21R35L13L28L1R15L45R11R20R36R45L38L48L47L39R10R8L17R38R41R28L25L15R9R8L12R15R16L49L40L10R10L4L49R42L12R26L20L14L2L25R33L6R41R10R10L31L34R50R42R48R3R21R43L18R22L41L41R47R8L43L40R45R49R36L48R38L41L23R22L25L25R40R7R1R7R9R40R45L34R44R6R29L16L26R18R24R5L9L28R27R42L27L12L48L21R21L3R33L18R26R45R36L13L4R9R34R46L21L38R12R45L50L32R2R45R4L39L13L47R21R48L35R40R33L32L27L36L39L12L11R9R33R5L25R1R16L1L8R41R32L36R47L23R9L6R35R12L33R6L43L31R19L7L47L7R31R14L40L30L4L50R2L14L16L29L15L37R42L32R23R42R49L41L34R35R48L32L47L27R20R2R37L4R44R31R41L34L43L5R29L15R25L30R44L4L36R27R14R12R31L29L44R41L19L35R9R13R5R2L27L39L26L23R22L10L14R12L23R28R22R2R16R36L40R30R5L27R26L31R7R49R1L50L22R43L9L44R21R23R14R24R9L32L2R25L34R37R6R17R1L41R40L17L13L50R4R26L23R13R29R46L25L2L30L49L37L9L9L16R38R46R2R18R16R3L35L30R43L23R12R5R38R21R42R19L44L7L43L44R46L5L8L15R19L21R12L2L47L10R34L13R33L14L47R20R16R37R17R44L26R24L50R16L5L16R6L28R25R1L20L20R1R42L9L43L42L31R32L48L3R44R47R15L19R23L5R47L36R4R8R43R15R5R37R13L1L3R25R25L18L31L13R26L12R14L45R34L6R19L38L40R25R8R42R35R5L44R38L34L42R13L33L11R1R27L31L43R37L14L46R25L33R24R7L5R36R19R36R46R39R35L47L12R38L48R42L50L10L5R17L22R34R35R24R6L5R7R29L9L31R41R17R15R3L20L50L24L14R43L18L1L9R8R39R4L28R3R3R42R39L33L30R14L47R28R33L22L6R41L29R1R15L40R8L48L17L22L12R28L29L42R4R10L16L22L39L6R3R27L38R2L25R12R3R46R15L38L8L23R36R36L11R43R2R8R34R4L17R8R21L23L28R50R21L17R39R2L37L4L19L14L49R43R35R42L37L14L10R48L26R41L34L2R16R2R26R9R44L15L7L1R1L9R12R33L48L43L46L22R41R1R18R40R23R35R29R28L4L19L23R4R45L30L17L15L3L9L28L30L28R49L24L7R23R26L30L20R24L2L23R14L27L41R33R17L39L42L41L16L6R22R26L39L13R33L10R32L13L45L20L36R25L4L24L15L28R22L42L38L12R28L6L47R16R50R47L5L43R28L21R1R50L13R34R23L43R22R38R29R37L31L3R42L3R26L23L4L46L24R40L13R34L13R36L12R46L38R21R44R25L23R34L43R30R38R39L16R1L34L35R43L13L43R46R47R2L23L15R22R47R23R35R31R10L6R18R32L25L13L37R44R20R50R28L46R26R48R46L38L49R33R8R32L18L32L39L35L28R8L36L16L38R27L6L16L15L28R46L17L32L11R41L37L13R21L11L1R14L48R33L49L16R29R23L41L38R2R42R27R26L41R49R36L29R22L8L13R45R48L42L45R39L35L12L43L12L35R40L43R36R21L14R44L12R9R43L42L39L16R9L11R50R41L46L40L17L42R47R44R48L19R2R4L41R4R39R47L30R50R28L13R38L3R22L10L21R31L39L24R7L44L22R21R7L11R49L25R22L13R16R14R18R33L11L35R3R23R6L44R31L10L4R43L16R31R46L43R46R35L5R50R48R42L33R35L7L20R38L4R40L45R40R43R46R30L18R6L11L7L47L38R37R32R44R45R23L43R39L30R23R6R40R33R50L33R21L35R29L1R34R15L16R50L42R47R43R27R21R31R49R22L7L7L2L20R8L16R48R4L35R42L45L13R42R15L9R1R15L31L47R15R40L21R12R11L10R42R17R3R19L15L24R37L18L36L42L21L50R9L42L27L24L43L44L49R13L10L18L5R25R41R19R18L8R42L9L22L37L5L16L4L22L50L14L40R40R2L32L9L24L6R23L24R50L7R48R39R27L18R17R43R37L41R38R50R6L37L2R38R17R1R31L3L26L34R23L14L13L32L15R27R18R16L34L6L11L46R32L11L13R41L3R43L19R24L1R33L1R2R21R33R8L18L20R27L2R43R1L28R15L16R21R40R42L28L11R5L28L11L2L27R47L16R10L3R44R21L31L28R10L35L7R28L50L19L31L48L45L24R24R38R44R35L2R50L34L27R22L2R23R43R24R27R5R12L46L3R21L38R20R11L4L4L5L24L7R1R49L26R34R47L41L4R6R4L27R28R17R24R15R21R11R43R26R38R40L39L40L27R37R47L28R6R34L38R17L7L10R26L49R32L9R14L29L14R13L21R40R1R39R1R24R33L6L3R11L40L1L13L7L42R21L3R1L35R12L21R16R3R20R5L15R18R8R42L13L29L48R38L31L10L1L13R45L28L34R50L27R4L37L46R26R50R7R12L44L25R7R6R27L7L3R46L18R6R14L45L45R30R45L35R19R27R19R4R18L41L19R5R5L30L47R35L25R42R22R12L15L33R9L39R18R19L8R21L14L40R22R44R3R36L22L13L48R29R33L40L25R47R17L47L9L8R1L23L30L22R28R30L21L33R43L41L3L42R27R38R40R48L9L25L42R31L36R45R47L44R41L1L3R17L25R47R47L38R18L21L32L39R30L28L40L7R11R13R6L42L43R30L41L21R23L16L19L5R46L44L46L4L33R33R11R35R48R13R43R8L14L37R11R34R46L38L41L14R31R40R45R29R13R5R44L47R35L29L20R2L36L39L15R9R48R17R20L30L28L42R26L44R2L23L21R48L40L37R29R6L3R18L15L37R48L7R4L13R45R10R7L40L11R19L5L9L36R49L4R15L32L43L28R14L16R36R46R45L15L47R42L15R24L40L1L25L13R43R7R22L15R3L24L35R39L32R10L45R40R31R8R49L13R19R43R46R39R50L6R42L24R49L21L3R28R45R36L39L37L19R38L14L48R27R15L44R24L4R35R2R32L29R14L50R20R5R5R15R46L1R39L9L38L44L33L19R28R28L33L41R38L40R12R7L42L14R7R14L24R14R30R24R19R34L26R26L34L31R22R32L13L19R36R25R27L1R9L25R28R12R26L35R6L27L17L46R4L13L4R50R45R39L37L47R6R48R21R21R4L35L23L5R32R48L40L1L8R42L3L27R42R36L26L29R1L33R16R19R20R1R42R38R41L2L47L37L26L24R8L17L6L49R25R9L41R8L12L12L49R9R49R26L30L4R31R35L16R40R20R31R43L12L14R41L27L42R19L45R28R18L47R4L5L41L50L12R24L31R4R44R43R32L42L29R44R45R10L3L49R4R12L42R48R26R41L47L4R41R20L23R32R12R37R10L40L19L18R28R9R6L50L2R37R16R27L16L37R36L41L1L38R17L46R18L36R20R28L33L2R13L10L6L41R38L12L45R11L5L41R19R42L39L11L34R28R37L50L33R34R39R17L18L9R36R45R47R16R30R13L49R27L8R12R48R23L24L1L5R35R10L34L16R14L18L43L9L23R49L22L35L16L48R9R24R39R15R26L10R36L33L39R48R25R31L23L30L48R47R1R40L16R34L46R48L7L1R22R19R4R10R1L45L20L1R47L45L25R11L24L23R38R29L34R47L13L13R3L26R42L50L11L35L17R18R37R43R49R11L29R33R16L14R23R30L40L5L11L50L23L41L38L38R17R49R8R39L10R10L20R31R4R23R29L5R10L15R32L29L34L40R3R24R6L38R11R37R9R20R34L48R45L14R35R4R46L17R6R17R45R48L4R2L30L46R14R47L24R17R33L7L49R22R1R43L36R3L38L36R23R6L17R5R18L9R20R43L14R24R31L21L18R46R24R14L5R39R4L11R18R8L41R32L22R17L29R27L50L44R50R34L46R38R10L12L11L34L12L41L26R21L24R33L25L40R18R24R9L36L7R26L2L9R42L8L24L5R23R48R7L44R11L47L12L27R48L25L15R34R37R46R12L18L7L46R50L24R38R2L26L9L43L1R38L6L6R43L40L41R5R39R28L35R3L32L1R6L14L15R49L16L40R34L6R48R41R41R11L5R10L20L27R15R4R23L39R27R2L22R49R33R43L26R47R2L38R42R22L30L44R29R11L39L42L30R31R47L44L26L31L15R3R11R9L45L30R27L34L35L16R37L18R15L29R25R41R8L39R29R10R33R14R12L9L11L30L3L49R40L27R40
diff --git a/day22/uppga.c b/day22/uppga.c
@@ -0,0 +1,20 @@
+#include "common.h"
+
+int main(int argc, char** argv)
+{
+ char** lines;
+ size_t nlines = readlines(&lines, "input");
+ printf("#lines: %lu\n", nlines);
+
+ board b;
+ pos p;
+ move* m;
+ size_t nmoves = parse(&b, &p, &m, (const char**) lines, nlines);
+
+ size_t i;
+ for(i = 0; i < nmoves; i++) {
+ make_move(&p, &b, m[i]);
+ }
+
+ printf("%lld\n", score_pos(&p));
+}
diff --git a/day22/uppgb.c b/day22/uppgb.c
@@ -0,0 +1,20 @@
+#include "common.h"
+
+int main(int argc, char** argv)
+{
+ char** lines;
+ size_t nlines = readlines(&lines, "input");
+ printf("#lines: %lu\n", nlines);
+
+ board b;
+ pos p;
+ move* m;
+ size_t nmoves = parse(&b, &p, &m, (const char**) lines, nlines);
+
+ size_t i;
+ for(i = 0; i < nmoves; i++) {
+ make_move_b(&p, &b, m[i]);
+ }
+
+ printf("%lld\n", score_pos(&p));
+}
diff --git a/day23/Makefile b/day23/Makefile
@@ -0,0 +1,20 @@
+CC=clang
+UTILS=../utils/reading.o
+INCLUDES=-I../utils
+
+all: utils common.o uppga uppgb
+
+common.o: common.c common.h
+ $(CC) $(CFLAGS) -c common.c $(INCLUDES)
+
+uppga: $(UTILS) common.o uppga.c
+ $(CC) -Wall -o uppga uppga.c common.o $(UTILS) $(INCLUDES)
+
+uppgb: $(UTILS) common.o uppgb.c
+ $(CC) -Wall -o uppgb uppgb.c common.o $(UTILS) $(INCLUDES)
+
+utils:
+ make -C ../utils
+
+clean:
+ rm -rf common.o uppga uppgb
diff --git a/day23/common.c b/day23/common.c
@@ -0,0 +1,251 @@
+#include "common.h"
+
+static size_t norder = 4;
+static char order[4] = "NSWE";
+
+space make_space(const size_t npos) {
+ space r;
+ r.h = 2*(npos+200);
+ r.w = 2*(npos+200);
+ r.hoffs = npos+100;
+ r.woffs = npos+100;
+
+ r.data = malloc(r.h * r.w * sizeof(*r.data));
+
+ return r;
+}
+
+void set_space(space s, const int64_t x, const int64_t y, const uint8_t val)
+{
+ assert((y + ((int64_t) s.hoffs)) >= 0);
+ assert((y + ((int64_t) s.hoffs)) < s.h);
+ assert((x + ((int64_t) s.woffs)) >= 0);
+ assert((x + ((int64_t) s.woffs)) < s.w);
+ s.data[(y + ((int64_t) s.hoffs)) * s.w + (x + ((int64_t) s.woffs))] = val;
+}
+
+static inline void inc_space(space s, const int64_t x, const int64_t y)
+{
+ assert((y + ((int64_t) s.hoffs)) >= 0);
+ assert((y + ((int64_t) s.hoffs)) < s.h);
+ assert((x + ((int64_t) s.woffs)) >= 0);
+ assert((x + ((int64_t) s.woffs)) < s.w);
+ s.data[(y + ((int64_t) s.hoffs)) * s.w + (x + ((int64_t) s.woffs))]++;
+}
+
+uint8_t get_space(space s, const int64_t x, const int64_t y)
+{
+ assert((y + ((int64_t) s.hoffs)) >= 0);
+ assert((y + ((int64_t) s.hoffs)) < s.h);
+ assert((x + ((int64_t) s.woffs)) >= 0);
+ assert((x + ((int64_t) s.woffs)) < s.w);
+ return s.data[(y + ((int64_t) s.hoffs)) * s.w + (x + ((int64_t) s.woffs))];
+}
+
+static inline void clear_spaces(space s, const pos* p, const size_t npos)
+{
+ size_t i;
+ for(i = 0; i < npos; i++) {
+ set_space(s, p[i].x-1, p[i].y-1, 0);
+ set_space(s, p[i].x-1, p[i].y, 0);
+ set_space(s, p[i].x-1, p[i].y+1, 0);
+
+ set_space(s, p[i].x, p[i].y-1, 0);
+ set_space(s, p[i].x, p[i].y, 0);
+ set_space(s, p[i].x, p[i].y+1, 0);
+
+ set_space(s, p[i].x+1, p[i].y-1, 0);
+ set_space(s, p[i].x+1, p[i].y, 0);
+ set_space(s, p[i].x+1, p[i].y+1, 0);
+ }
+
+ for(i = 0; i < npos; i++) {
+ set_space(s, p[i].x, p[i].y, 128);
+ }
+}
+
+int none_around(space s, pos p)
+{
+ assert(get_space(s, p.x, p.y) == 128);
+ return get_space(s, p.x - 1, p.y - 1) < 128 &&
+ get_space(s, p.x , p.y - 1) < 128 &&
+ get_space(s, p.x + 1, p.y - 1) < 128 &&
+ get_space(s, p.x - 1, p.y ) < 128 &&
+ get_space(s, p.x + 1, p.y ) < 128 &&
+ get_space(s, p.x - 1, p.y + 1) < 128 &&
+ get_space(s, p.x , p.y + 1) < 128 &&
+ get_space(s, p.x + 1, p.y + 1) < 128;
+}
+
+void propose_moves(space s, char* mvs, const pos* p, const size_t npos, const size_t round)
+{
+ clear_spaces(s, p, npos);
+
+ size_t i, j;
+ for(i = 0; i < npos; i++) {
+ if(none_around(s, p[i])) {
+ mvs[i] = 'X';
+ continue;
+ }
+ mvs[i] = 'X';
+ for(j = 0; j < norder; j++) {
+ char dir = order[(j + round) % norder];
+ if(dir == 'N') {
+ if(get_space(s, p[i].x - 1, p[i].y - 1) != 128 &&
+ get_space(s, p[i].x , p[i].y - 1) != 128 &&
+ get_space(s, p[i].x + 1, p[i].y - 1) != 128) {
+ inc_space(s, p[i].x, p[i].y - 1);
+ assert(get_space(s, p[i].x, p[i].y - 1) <= 4);
+ mvs[i] = dir;
+ break;
+ }
+ } else if(dir == 'S') {
+ if(get_space(s, p[i].x - 1, p[i].y + 1) != 128 &&
+ get_space(s, p[i].x , p[i].y + 1) != 128 &&
+ get_space(s, p[i].x + 1, p[i].y + 1) != 128) {
+ inc_space(s, p[i].x, p[i].y + 1);
+ assert(get_space(s, p[i].x, p[i].y + 1) <= 4);
+ mvs[i] = dir;
+ break;
+ }
+ } else if(dir == 'E') {
+ if(get_space(s, p[i].x + 1, p[i].y - 1) != 128 &&
+ get_space(s, p[i].x + 1, p[i].y ) != 128 &&
+ get_space(s, p[i].x + 1, p[i].y + 1) != 128) {
+ inc_space(s, p[i].x + 1, p[i].y);
+ assert(get_space(s, p[i].x + 1, p[i].y) <= 4);
+ mvs[i] = dir;
+ break;
+ }
+ } else if(dir == 'W') {
+ if(get_space(s, p[i].x - 1, p[i].y - 1) != 128 &&
+ get_space(s, p[i].x - 1, p[i].y ) != 128 &&
+ get_space(s, p[i].x - 1, p[i].y + 1) != 128) {
+ inc_space(s, p[i].x - 1, p[i].y);
+ assert(get_space(s, p[i].x - 1, p[i].y) <= 4);
+ mvs[i] = dir;
+ break;
+ }
+ } else {
+ fprintf(stderr, "ERROR! Unknown dir %c\n", dir);
+ exit(1);
+ }
+ }
+ assert(mvs[i] == 'N' || mvs[i] == 'S' || mvs[i] == 'E' || mvs[i] == 'W' || mvs[i] == 'X');
+ }
+}
+
+int make_moves(pos* p, const space s, const char* mvs, const size_t npos)
+{
+ int moved = 0;
+ size_t i;
+ for(i = 0; i < npos; i++) {
+ if(mvs[i] != 'X') {
+ switch(mvs[i]) {
+ case 'N':
+ if(get_space(s, p[i].x, p[i].y - 1) == 1) {
+ p[i].y--;
+ moved = 1;
+ }
+ break;
+ case 'S':
+ if(get_space(s, p[i].x, p[i].y + 1) == 1) {
+ p[i].y++;
+ moved = 1;
+ }
+ break;
+ case 'E':
+ if(get_space(s, p[i].x + 1, p[i].y) == 1) {
+ p[i].x++;
+ moved = 1;
+ }
+ break;
+ case 'W':
+ if(get_space(s, p[i].x - 1, p[i].y) == 1) {
+ p[i].x--;
+ moved = 1;
+ }
+ break;
+ default:
+ fprintf(stderr, "ERROR! Unknown dir (in make_moves) %c\n", mvs[i]);
+ exit(1);
+ }
+ }
+ }
+
+ return moved;
+}
+
+void print_board(const space s, const pos* p, const size_t npos)
+{
+ size_t i, j, k;
+ for(i = 0; i < s.h; i++) {
+ for(j = 0; j < s.w; j++) {
+ int64_t y = (int64_t) i - s.hoffs;
+ int64_t x = (int64_t) j - s.woffs;
+ int occup = 0;
+ for(k = 0; k < npos; k++) {
+ if(x == p[k].x && y == p[k].y) {
+ occup = k+1;
+ break;
+ }
+ }
+
+ if(occup) {
+ printf("#");
+ } else {
+ printf(".");
+ }
+ }
+ printf("\n");
+ }
+}
+
+static inline void getminmax(int64_t* vals, const pos* p, const size_t npos)
+{
+ size_t i;
+ vals[0] = INT64_MAX;
+ vals[1] = INT64_MIN;
+ vals[2] = INT64_MAX;
+ vals[3] = INT64_MIN;
+ for(i = 0; i < npos; i++) {
+ if(p[i].x < vals[0]) vals[0] = p[i].x;
+ if(p[i].x > vals[1]) vals[1] = p[i].x;
+ if(p[i].y < vals[2]) vals[2] = p[i].y;
+ if(p[i].y > vals[3]) vals[3] = p[i].y;
+ }
+}
+
+int64_t count_empty(const pos* p, const size_t npos)
+{
+ int64_t bounds[4];
+ getminmax(bounds, p, npos);
+
+ return (bounds[1] - bounds[0] + 1) * (bounds[3] - bounds[2] + 1) -
+ ((int64_t) npos);
+}
+
+pos* parse(size_t* npos, char** lines, size_t nlines)
+{
+ size_t i, j;
+ size_t cols = strlen(lines[0])-1;
+
+ size_t ntmp = 0;
+ pos tmp[nlines * cols];
+
+ for(i = 0; i < nlines; i++) {
+ for(j = 0; j < cols; j++) {
+ if(lines[i][j] == '#') {
+ tmp[ntmp].x = (int64_t) j;
+ tmp[ntmp].y = (int64_t) i;
+ ntmp++;
+ }
+ }
+ }
+
+ pos* r = malloc(ntmp * sizeof(*r));
+ memcpy(r, tmp, ntmp * sizeof(*r));
+ *npos = ntmp;
+
+ return r;
+}
diff --git a/day23/common.h b/day23/common.h
@@ -0,0 +1,31 @@
+#ifndef COMMON_H_
+#define COMMON_H_
+
+#include <stdio.h>
+#include <stdint.h>
+#include <assert.h>
+#include <reading.h>
+
+typedef struct {
+ int64_t x;
+ int64_t y;
+} pos;
+
+typedef struct {
+ size_t h;
+ size_t w;
+
+ int64_t hoffs;
+ int64_t woffs;
+
+ uint8_t* data;
+} space;
+
+pos* parse(size_t* npos, char** lines, size_t nlines);
+void print_board(const space s, const pos* p, const size_t npos);
+space make_space(const size_t npos);
+void propose_moves(space s, char* mvs, const pos* p, const size_t npos, const size_t round);
+int make_moves(pos* p, const space s, const char* mvs, const size_t npos);
+int64_t count_empty(const pos* p, const size_t npos);
+
+#endif
diff --git a/day23/einput1 b/day23/einput1
@@ -0,0 +1,6 @@
+.....
+..##.
+..#..
+.....
+..##.
+.....
diff --git a/day23/einput2 b/day23/einput2
@@ -0,0 +1,7 @@
+....#..
+..###.#
+#...#.#
+.#...##
+#.###..
+##.#.##
+.#..#..
diff --git a/day23/input b/day23/input
@@ -0,0 +1,73 @@
+..###.##.#.#.##..#.#.##..#.#.##.#.....#####.#.#..###.#.#....####.##.###.#
+..#.##.#..###..###..#..#....#..##..#.###..#....##.##.#.....##.######.####
+##....#....#.###..##.#####....##..#.######.#.#..#....####.#...####...####
+#.##.#.#.#.#.#.######.#...#.####...###.#.#..#####.....#..#.####.#...####.
+....###.....###..#..####...#.#.##.##..####..#.##.......###..#.###.#..###.
+.#...####.#..###.#...###....#.......##..#.#..#..##.##.#..#.#.##.#...##..#
+#..#.##.#.#.##...#.#####.####.##....#.###.#.#.##.###..#.###.###.#...#.#..
+##.#.##.#####...###..#.#....###.#...##.##....#.##.###....#.#.##.#.......#
+###.##...###..#.##...####..##.#.#.......#..#.#....###..###.#..###..#...##
+#.##.###.#.#...####.#...#.######.#.###..#.####.###.#...###.#..#.#..####..
+.....##.#..###.#.#.#.############.##.###.#....##.###....####....###.#####
+#.#..###.###..##.#..#####.#..##..#####.....###......#.#..###.#####.#..###
+.##.#.##....##.##...#..##...#....#.###..##.#....#..######...#..####..#..#
+.######.#.##.#.###.####..##....##.#####...#...##.##.#.##..#...##.#.##....
+...##.....#.###..##.#.##..####.#..#.#..##..#....#....#.......#...##...##.
+##.#....#######.#..#.#...#####.######.....#.#..#...######.##.####.#####..
+######.#.#.#.########..#..#...###..##.##.##...#.###..###..#.#..##.##.#..#
+..###.##..####...###..##.#...#.##.#.#.#####.#.##..#..#.#.#.#.#.##..###..#
+..##..##...#.######..########....#.###..##.#.#.#..#.#..#....#.##..#.##...
+#.#.##.##..#.#...#.#.#.###.#...#....###.###.#.....#....##..#######..##.#.
+.##...#.#.####....###..##...#.#..#.#.#.#.###.#.####.#...#####..##..###..#
+##..###.####.#####.######..#.......#.####..##....#.#.###..######.#.#####.
+.#....###..##.###..#.#.####.#..#..#.###.#.##.#....##.###.###.#.###.##....
+#..#..####.#.#..#.#.##.#..#.##..#.##...##.#..#.#...#.####.####..#.###....
+..##.........##.#.##.##.#..##..#..#.#.....#.#.#.#.#.###.#...#.###..##.###
+.#.#...##...#.......#.#.#...#.##.#..#.######...##.##.##.#.##.#.#..####..#
+.#.###.####..#..#...#.....#.....##...##.#....####.##..#..#....##.##....##
+#..#..#..##.#..##...#...##...#.###..#........###.#.##..#...###########.##
+.####...##.#..#..###.###.#..##..#...##...###.....###.#.##.#...#.###.###.#
+.#.#####.#...###.##..........##......##..###...#.#....#.#.###....#.#...##
+#.....#####.#.###.##.#.###.##...###.##.######.#...###..#....###...##...##
+..####..#.#.#.#####.#.#....#.####...#...#....##.#.#..#.#.#.###.###.##....
+....#.#.##..#.##.......######....#.##.###...##.###.....#.###.####.#####..
+#.#..#####.##.###.#..#.####.##.....##..###..#....##.###....#..##.##..####
+#.#.###.###.##.#.##.#.##.##.###.####.######.###..##..#..##....#..###.#.#.
+###..##..#..###.#...##.##..#.#.###.###..#..#....##..##.#........###....#.
+##.#..#.......#.#.#.##.##.##...#..##.###..###.#.##.#...#.#.####..#......#
+#..###.##....##.#..#.#.#.##.####...#.###.####.#..#..##....####.####.#.#..
+#...#.###...###.##.#.##.##..#.#..#..#.....#####..##.###...###.##.#.#.#...
+..#.....####....##...#..#.####...###.####.##..#..#..###..#.#..##.#.....##
+##.###...##.#.#...###...###.#..#.##.###...########.#..#....##..#..##..###
+....#..#..#......####....#.#.##...###.##.#..#.####..##.#..#..#..##..#####
+.##.#.##.##...#.#..#.##..###.##.###.#..##....#######.##.##.#.##.###...#..
+.#..#.##...###...###.###..###...#..#..###.#..#...###..#.##.#.###.##.###.#
+..##.##.###.####.#.###.#.......##..#..###...##...##..####.#######....#..#
+#.#..##...##....##.######..#..#.##...#.######..###..##.....#...#.####..##
+#..#.....#######...#....#.#..#..#...##.#.####....#.#.###..##...#.#.#.##..
+##.##.##..#..#..#...##..#.##.#####.....#.####....#...#.#######..##.###..#
+....##.##....####.#...####...##.#...#.....#...##.##.#.#.#..#.##...##..###
+####..##.###.#.....#.##.##...#.###.#####.###.#####.##.....#######.......#
+.##.....#...#.##.###.#.##....##.#..##.#..##....#.##..####.#..###.##.####.
+#..###....#..#.#..##....#...#.##..##.#....############.##...#.##..##...##
+....#.#..####..#......#.#.###......#....#..##...#...####.#.#..###.#.###..
+.######.....#######.....#.#.##..#..###..#..###..###........#....####.....
+...####.###.####..#.##..###......#..#.#.#..#.#.####.#.....#..##..#..####.
+.#..###...#.##..###.#.###.##..#.#..#....##.#.#.#.####.########.##.##..#..
+..#...####.##....#.###...#..#...#..#..#########.##.#..##.#.#...##..##..##
+.##....###...#.#....#.###..######.####..#.#.##....#..##..###.##.#.#.#..##
+.##.###..#.###.###..##.##...###.###.#.#....#.#...#.#..#####......#.######
+#....####....#####...##.#.#.#.#.#.......##...###..#...#..#...#.###.#..#.#
+..#.#.####....###.##..#...##..#.#..##..#.##.####.##..##.##....#..##.###..
+..###...##.........#....#..#.....#.###.......#.####.##.#.##..#.#....####.
+..#.######.##..#.######.#...##.#.###.....#####.#.#..#.####..###..#####..#
+..##.##.##..#..#.####.......#.#....#..#....#.......#....#####.##..##.####
+.###.#.###.###..####.#.##.#...#########....##.##.#...#.#.##.#.#.#####.###
+.#..##.##...#..#.#.##.#.....###.#.##.#.#.#.#.#...#####.#..#.###....###..#
+....###.#.#.###.#...###.#######...#....#....#.##.#.######.#..##.#.###..##
+#.#.####....###...####.##.#.#...####.##.##...#.###...#..###.###..###.#...
+#.##...###.###.#######...##..#..###....######.#.#.##..######.##.....#..#.
+##..###..##.#.#.##.#.#.#.#.#.##...####..##..###.##########..#...#####.###
+......#..#####...##.##.#.#.#.##.##...#....#..##.#####..#...#.#..#...###.#
+..###.##.##.##.#...#.....##.###.#.###..#......#.#..#.##.#..##..#.###.#.##
+.......#..##.#..#.####.####.#......#.#..#.#.#.##.#..#..###...##..#..#####
diff --git a/day23/uppga.c b/day23/uppga.c
@@ -0,0 +1,24 @@
+#include "common.h"
+
+int main(int argc, char** argv)
+{
+ char** lines;
+ size_t nlines = readlines(&lines, "input");
+
+ size_t npos;
+ pos* p = parse(&npos, lines, nlines);
+
+ space s = make_space(npos);
+
+ size_t round = 0;
+ int moved = 1;
+ char mvs[npos];
+ while(moved && round < 10) {
+ propose_moves(s, mvs, p, npos, round);
+ moved = make_moves(p, s, mvs, npos);
+ round++;
+ }
+
+ int64_t empty = count_empty(p, npos);
+ printf("%lld\n", empty);
+}
diff --git a/day23/uppgb.c b/day23/uppgb.c
@@ -0,0 +1,23 @@
+#include "common.h"
+
+int main(int argc, char** argv)
+{
+ char** lines;
+ size_t nlines = readlines(&lines, "input");
+
+ size_t npos;
+ pos* p = parse(&npos, lines, nlines);
+
+ space s = make_space(npos);
+
+ size_t round = 0;
+ int moved = 1;
+ char mvs[npos];
+ while(moved) {
+ propose_moves(s, mvs, p, npos, round);
+ moved = make_moves(p, s, mvs, npos);
+ round++;
+ }
+
+ printf("%zu\n", round);
+}
diff --git a/day24/Makefile b/day24/Makefile
@@ -0,0 +1,20 @@
+CC=clang
+UTILS=../utils/reading.o
+INCLUDES=-I../utils
+
+all: utils common.o uppga uppgb
+
+common.o: common.c common.h
+ $(CC) $(CFLAGS) -c common.c $(INCLUDES)
+
+uppga: $(UTILS) common.o uppga.c
+ $(CC) -Wall -o uppga uppga.c common.o $(UTILS) $(INCLUDES)
+
+uppgb: $(UTILS) common.o uppgb.c
+ $(CC) -Wall -o uppgb uppgb.c common.o $(UTILS) $(INCLUDES)
+
+utils:
+ make -C ../utils
+
+clean:
+ rm -rf common.o uppga uppgb
diff --git a/day24/common.c b/day24/common.c
@@ -0,0 +1,406 @@
+#include "common.h"
+
+static inline size_t ceil_div(const size_t x, const size_t y)
+{
+ assert(y > 0);
+ return (x + y - 1)/y;
+}
+
+static inline size_t bitvector_len(const bitvector* b)
+{
+ return ceil_div(b->n, 8 * sizeof(*b->v));
+}
+
+static inline size_t bitvector_remainder_bits(const bitvector* b)
+{
+ size_t remainder = b->n % (8 * sizeof(*b->v));
+ return remainder == 0 ? (8 * sizeof(*b->v)) : remainder;
+}
+
+void bitvector_init(bitvector* b, const size_t n)
+{
+ b->n = n;
+ b->v = calloc(bitvector_len(b), sizeof(*b->v));
+}
+
+void bitvector_clear(bitvector* b)
+{
+ free(b->v);
+ b->n = 0;
+}
+
+static inline void rotshift_r(bitvector* out, const bitvector* in)
+{
+ assert(out != in);
+ assert(out->n = in->n);
+
+ size_t i, l = bitvector_len(in);
+ uint64_t remainder = 0;
+
+ assert(l > 0);
+
+ for(i = 0; i < l-1; i++) {
+ out->v[i] = remainder ? HEADBIT_U64 | (in->v[i] >> 1) : in->v[i] >> 1;
+ remainder = in->v[i] & 0x01;
+ }
+
+ const uint64_t last_remainder = in->v[l-1] & (HEADBIT_U64 >> (bitvector_remainder_bits(in) - 1));
+ out->v[l-1] = remainder ? HEADBIT_U64 | (in->v[l-1] >> 1) : in->v[i] >> 1;
+ if(last_remainder) out->v[0] |= HEADBIT_U64;
+}
+
+void rotshift_l(bitvector* out, const bitvector* in) {
+ size_t i, l = bitvector_len(in);
+ for(i = 0; i < l-1; i++) {
+ out->v[i] = (in->v[i] << 1);
+ if((HEADBIT_U64 & in->v[i+1]) != 0) {
+ out->v[i]++;
+ }
+ }
+
+ out->v[l-1] = (in->v[i] << 1);
+ if((HEADBIT_U64 & in->v[0]) != 0) {
+ out->v[l-1] |= (HEADBIT_U64 >> (bitvector_remainder_bits(in) - 1));
+ }
+}
+
+static inline void bitvector_set(bitvector* b, const size_t n, const uint64_t v)
+{
+ assert(v == 0 || v == 1);
+ assert(n < b->n);
+
+ const size_t i = n / (8 * sizeof(*b->v));
+ const size_t m = n % (8 * sizeof(*b->v));
+
+ if(v == 0) {
+ b->v[i] &= (UINT64_MAX ^ (HEADBIT_U64 >> m));
+ } else {
+ b->v[i] |= (HEADBIT_U64 >> m);
+ }
+}
+
+static inline int bitvector_get(const bitvector* b, const size_t n)
+{
+ assert(n < b->n);
+
+ const size_t i = n / (8 * sizeof(*b->v));
+ const size_t m = n % (8 * sizeof(*b->v));
+
+ if((b->v[i] & (HEADBIT_U64 >> m)) != 0) {
+ return 1;
+ }
+ return 0;
+}
+
+static inline void bitvector_or(bitvector* out, const bitvector* a, const bitvector* b)
+{
+ size_t l = bitvector_len(a);
+ assert(l == bitvector_len(b));
+ assert(l == bitvector_len(out));
+
+ size_t i;
+ for(i = 0; i < l; i++) {
+ out->v[i] = a->v[i] | b->v[i];
+ }
+}
+
+void bitvector_print(const bitvector* b)
+{
+ size_t i, j, l = bitvector_len(b);
+
+ for(i = 0; i < l-1; i++) {
+ for(j = 0; j < 64; j++) {
+ if((b->v[i] & (HEADBIT_U64 >> j)) != 0) {
+ printf("1");
+ } else {
+ printf("0");
+ }
+ }
+ }
+
+ const size_t remainder = bitvector_remainder_bits(b);
+ for(j = 0; j < remainder; j++) {
+ if((b->v[l-1] & (HEADBIT_U64 >> j)) != 0) {
+ printf("1");
+ } else {
+ printf("0");
+ }
+ }
+}
+
+static inline void parse_row(board* out, const size_t row, const char** lines, const size_t nlines)
+{
+ assert(row < nlines - 2);
+ const char* line = lines[row + 1];
+
+ bitvector first_rs, first_ls;
+ bitvector_init(&first_rs, out->w);
+ bitvector_init(&first_ls, out->w);
+
+ size_t i;
+ for(i = 1; i < out->w + 1; i++) {
+ if(line[i] == '>') {
+ bitvector_set(&first_rs, i-1, 1);
+ } else if(line[i] == '<') {
+ bitvector_set(&first_ls, i-1, 1);
+ } else {
+ assert(line[i] == '.' || line[i] == '^' || line[i] == 'v');
+ }
+ }
+
+ bitvector trs, tls;
+ bitvector_init(&trs, out->w);
+ bitvector_init(&tls, out->w);
+
+ for(i = 0; i < out->w; i += 2) {
+ bitvector_or(&(out->row_mask[row][i]), &first_rs, &first_ls);
+ rotshift_r(&trs, &first_rs);
+ rotshift_l(&tls, &first_ls);
+ if(i+1 < out->w) {
+ bitvector_or(&(out->row_mask[row][i+1]), &trs, &tls);
+ rotshift_r(&first_rs, &trs);
+ rotshift_l(&first_ls, &tls);
+ }
+ }
+
+ bitvector_clear(&trs);
+ bitvector_clear(&tls);
+ bitvector_clear(&first_rs);
+ bitvector_clear(&first_ls);
+}
+
+static inline void parse_col(board* out, const size_t col, const char** lines, const size_t nlines)
+{
+ assert(col < out->w);
+
+ bitvector first_rs, first_ls;
+ bitvector_init(&first_rs, out->h);
+ bitvector_init(&first_ls, out->h);
+
+ size_t i;
+ for(i = 1; i < out->h + 1; i++) {
+ if(lines[i][col+1] == 'v') {
+ bitvector_set(&first_rs, i-1, 1);
+ } else if(lines[i][col+1] == '^') {
+ bitvector_set(&first_ls, i-1, 1);
+ } else {
+ assert(lines[i][col+1] == '.' || lines[i][col+1] == '>' || lines[i][col+1] == '<');
+ }
+ }
+
+ bitvector trs, tls;
+ bitvector_init(&trs, out->h);
+ bitvector_init(&tls, out->h);
+
+ for(i = 0; i < out->h; i += 2) {
+ bitvector_or(&(out->col_mask[col][i]), &first_rs, &first_ls);
+ rotshift_r(&trs, &first_rs);
+ rotshift_l(&tls, &first_ls);
+ if(i+1 < out->h) {
+ bitvector_or(&(out->col_mask[col][i+1]), &trs, &tls);
+ rotshift_r(&first_rs, &trs);
+ rotshift_l(&first_ls, &tls);
+ }
+ }
+
+ bitvector_clear(&trs);
+ bitvector_clear(&tls);
+ bitvector_clear(&first_rs);
+ bitvector_clear(&first_ls);
+}
+
+int intersects(const board* b, const uint64_t x, const uint64_t y, const size_t r)
+{
+ assert(y < b->h);
+ assert(x < b->w);
+
+ return bitvector_get(&(b->row_mask[y][r % b->w]), x) ||
+ bitvector_get(&(b->col_mask[x][r % b->h]), y);
+}
+
+board parse(char** lines, size_t nlines)
+{
+ board b;
+ b.h = nlines-2;
+ b.w = strlen(lines[0])-3;
+
+ b.row_mask = malloc(b.h * sizeof(*b.row_mask));
+ b.col_mask = malloc(b.w * sizeof(*b.col_mask));
+
+ size_t i,j;
+ for(i = 0; i < b.h; i++) {
+ b.row_mask[i] = malloc(b.w * sizeof(*b.row_mask[0]));
+ for(j = 0; j < b.w; j++) {
+ bitvector_init(&b.row_mask[i][j], b.w);
+ }
+ }
+
+ for(i = 0; i < b.w; i++) {
+ b.col_mask[i] = malloc(b.h * sizeof(*b.col_mask[0]));
+ for(j = 0; j < b.h; j++) {
+ bitvector_init(&b.col_mask[i][j], b.h);
+ }
+ }
+
+ for(i = 0; i < b.h; i++) {
+ parse_row(&b, i, (const char**) lines, nlines);
+ }
+
+ for(i = 0; i < b.w; i++) {
+ parse_col(&b, i, (const char**) lines, nlines);
+ }
+
+ return b;
+}
+
+void bestfinder(board* b, uint64_t* best, uint64_t* bestend, set* s, uint64_t endx, uint64_t endy)
+{
+ uint64_t i, r, x, y, nr, cb;
+
+ while(s->n != 0) {
+ i = 0;
+ while(s->d[i] == 0) i++;
+ s->d[i] = 0;
+ s->n--;
+
+ x = i % (b->w);
+ y = (i / b->w) % b->h;
+ r = i / (b->w * b->h);
+ nr = (r + 1) % b->lcm;
+ cb = best[r * (b->w * b->h) + y * b->w + x];
+
+ if(!intersects(b, x, y, nr) && best[nr * (b->w * b->h) + y * b->w + x] > cb+1) {
+ best[nr * (b->w * b->h) + y * b->w + x] = cb+1;
+ if(s->d[nr * (b->w * b->h) + y * b->w + x] == 0) {
+ s->d[nr * (b->w * b->h) + y * b->w + x] = 1;
+ s->n++;
+ }
+ }
+
+ if(x > 0 && !intersects(b, x-1, y, nr) && best[nr * (b->w * b->h) + y * b->w + (x-1)] > cb+1) {
+ best[nr * (b->w * b->h) + y * b->w + (x-1)] = cb+1;
+ if(s->d[nr * (b->w * b->h) + y * b->w + (x-1)] == 0) {
+ s->d[nr * (b->w * b->h) + y * b->w + (x-1)] = 1;
+ s->n++;
+ }
+ }
+
+ if(x < b->w-1 && !intersects(b, x+1, y, nr) && best[nr * (b->w * b->h) + y * b->w + (x+1)] > cb+1) {
+ best[nr * (b->w * b->h) + y * b->w + (x+1)] = cb+1;
+ if(s->d[nr * (b->w * b->h) + y * b->w + (x+1)] == 0) {
+ s->d[nr * (b->w * b->h) + y * b->w + (x+1)] = 1;
+ s->n++;
+ }
+ }
+
+ if(y > 0 && !intersects(b, x, y-1, nr) && best[nr * (b->w * b->h) + (y-1) * b->w + x] > cb+1) {
+ best[nr * (b->w * b->h) + (y-1) * b->w + x] = cb+1;
+ if(s->d[nr * (b->w * b->h) + (y-1) * b->w + x] == 0) {
+ s->d[nr * (b->w * b->h) + (y-1) * b->w + x] = 1;
+ s->n++;
+ }
+ }
+
+ if(y < b->h-1 && !intersects(b, x, y+1, nr) && best[nr * (b->w * b->h) + (y+1) * b->w + x] > cb+1) {
+ best[nr * (b->w * b->h) + (y+1) * b->w + x] = cb+1;
+ if(s->d[nr * (b->w * b->h) + (y+1) * b->w + x] == 0) {
+ s->d[nr * (b->w * b->h) + (y+1) * b->w + x] = 1;
+ s->n++;
+ }
+ }
+
+ if(y == endy && x == endx) {
+ size_t j;
+ for(j = 0; j < b->lcm; j++) {
+ bestend[(nr + j) % b->lcm] = bestend[(nr + j) % b->lcm] < cb + j ? bestend[(nr + j) % b->lcm] : cb + j;
+ }
+ }
+ }
+}
+
+void play(char** lines, size_t nlines)
+{
+ board b = parse(lines, nlines);
+ b.lcm = 700;
+ //b.lcm = 12;
+
+ set s;
+ s.n = 0;
+ s.nalloc = b.lcm * b.h * b.w;
+ s.d = calloc(s.nalloc, sizeof(*s.d));
+
+ uint64_t* best = malloc(s.nalloc * sizeof(*best));
+ memset(best, 0xff, s.nalloc * sizeof(*best));
+
+ uint64_t i, r, x, y, nr, cb;
+ uint64_t bestend[b.lcm];
+
+ for(i = 0; i < b.lcm; i++) {
+ bestend[i] = UINT64_MAX;
+ if(!intersects(&b, 0, 0, i+1)) {
+ best[i * (b.w * b.h)] = i+1;
+ s.d[i * (b.w * b.h)] = 1;
+ s.n++;
+ }
+ }
+
+ bestfinder(&b, best, bestend, &s, b.w-1, b.h-1);
+
+ uint64_t pb[b.lcm];
+
+ uint64_t min = UINT64_MAX;
+ for(i = 0; i < b.lcm; i++) {
+ printf("best[%llu, %zu, %zu] = %llu\n", i, b.w - 1, b.h - 1, best[i * (b.w * b.h) + ((b.h - 1) * b.w) + (b.w - 1)]);
+ printf("bestend[%llu] = %llu\n", i, bestend[i]);
+ if(bestend[i] < min) {
+ min = bestend[i];
+ }
+ }
+ printf("min = %llu\n", min);
+
+ memset(best, 0xff, s.nalloc * sizeof(*best));
+ for(i = 0; i < b.lcm; i++) {
+ uint64_t t = bestend[i];
+ bestend[i] = UINT64_MAX;
+ if(!intersects(&b, b.w-1, b.h-1, i+1)) {
+ best[i * (b.w * b.h) + ((b.h-1) * b.w) + (b.w - 1)] = t+1;
+ s.d[i * (b.w * b.h) + ((b.h-1) * b.w) + (b.w - 1)] = 1;
+ s.n++;
+ }
+ }
+
+ bestfinder(&b, best, bestend, &s, 0, 0);
+
+ min = UINT64_MAX;
+ for(i = 0; i < b.lcm; i++) {
+ printf("best[%llu, %zu, %zu] = %llu\n", i, 0UL, 0UL, best[i * (b.w * b.h)]);
+ printf("bestend[%llu] = %llu\n", i, bestend[i]);
+ if(bestend[i] < min) {
+ min = bestend[i];
+ }
+ }
+ printf("min = %llu\n", min);
+
+ memset(best, 0xff, s.nalloc * sizeof(*best));
+ for(i = 0; i < b.lcm; i++) {
+ uint64_t t = bestend[i];
+ bestend[i] = UINT64_MAX;
+ if(!intersects(&b, 0, 0, i+1)) {
+ best[i * (b.w * b.h)] = t+1;
+ s.d[i * (b.w * b.h)] = 1;
+ s.n++;
+ }
+ }
+
+ bestfinder(&b, best, bestend, &s, b.w-1, b.h-1);
+
+ min = UINT64_MAX;
+ for(i = 0; i < b.lcm; i++) {
+ printf("best[%llu, %zu, %zu] = %llu\n", i, b.w - 1, b.h - 1, best[i * (b.w * b.h) + ((b.h - 1) * b.w) + (b.w - 1)]);
+ printf("bestend[%llu] = %llu\n", i, bestend[i]);
+ if(bestend[i] < min) {
+ min = bestend[i];
+ }
+ }
+ printf("min = %llu\n", min);
+}
diff --git a/day24/common.h b/day24/common.h
@@ -0,0 +1,36 @@
+#ifndef COMMON_H_
+#define COMMON_H_
+
+#include <stdio.h>
+#include <stdint.h>
+#include <assert.h>
+#include <reading.h>
+
+typedef struct {
+ size_t n;
+ uint64_t* v;
+} bitvector;
+
+#define HEADBIT_U64 0x8000000000000000LL
+
+typedef struct {
+ size_t n;
+
+ size_t nalloc;
+ uint8_t* d;
+} set;
+
+typedef struct {
+ size_t h;
+ size_t w;
+ size_t lcm;
+
+ bitvector** row_mask;
+ bitvector** col_mask;
+} board;
+
+void play(char** lines, size_t nlines);
+board parse(char** lines, size_t nlines);
+int intersects(const board* b, const uint64_t x, const uint64_t y, const size_t r);
+
+#endif
diff --git a/day24/einput b/day24/einput
@@ -0,0 +1,7 @@
+#.#####
+#.....#
+#>....#
+#.....#
+#...v.#
+#.....#
+#####.#
diff --git a/day24/einput2 b/day24/einput2
@@ -0,0 +1,6 @@
+#.######
+#>>.<^<#
+#.<..<<#
+#>v.><>#
+#<^v^^>#
+######.#
diff --git a/day24/input b/day24/input
@@ -0,0 +1,37 @@
+#.####################################################################################################
+#<<^<<v.v^>v.<v>.^^>vvv<..^><>vvv>v>.v<>^>vv<<^><<^.<v^^<<<<<v^v><v>v^>vv>>.<^>.>^^^.<><><^^<v^><><.<#
+#<<^<<vv^vv<<^<><>>^<^vvv><>>>^.<v^<..<.>v>v>vvv><.v<^>v^v<<<>>>>>vv<^<<<v>^<.>>vv><<.>v<.^v.v<^<>>v>#
+#<<.v>.v<v<<^v.v>><v.<v<^.>>>.<^>^^^><<>.v><<vv.^v^.^<v>v^vv^<.>v<v><.v^.v<v<v>>><^v.v^^^<<v<^^<>v>v>#
+#<>^v>vvv><..^..v<<^v^><.<<<<>>>^v><.<<^^vv<^v.<^^<^v^>>vv<.>v><..^><.vv>v^>>v><^v<<<^v<^v<v<<^v.vv^>#
+#>^v<>>v<^^vv<<<v^v^<<v>v^vv^vv>><>^.^vv^<>^<v^^<.^v<.^<>^>vv.><<^>v<^^>v^<v.^.^<>v>^>v.<^vvvv<>>.>v>#
+#<^^>><v><<^v<v>vvv>v^>v<^^^^><>^v^.<v^>.<>>vvv^v>.<v<<<^v>>>><v^^<>^v<>>^v>^^^^vvv^^><>^^^^<v<..><^>#
+#>><<<><>^v^<<v>>.<v^^^^<vv^>>>v<v><v>>^>>^^^>v.<v^v>><><^v><vv<^.^vvvv<>.^>v><<<^>vv<^^v<v^^<><.^^v.#
+#<>>^^>v<v.>v.v>^<<>^.>>vv^vv<^>v^><.^v<<v^<.^>v^.^v.<^.^<^<..^>><>v.>^v>vvvv<<>v^<vv<>vv>v>.>v^<^^^>#
+#>vv<v>v<v>^<>v^<^vv<>v>^><><<>>v^<>v.<.>>>>v<v>v^<v<^v<>>v^<>v^>v>v<^<^v^^<v.<^vv<<<.>^v^><v>^^<.<>>#
+#>v^.>vv^vv>.><<^.v^.v<>.^>v><<>v^^<<^<.^.^vv^<^^^><<>.v<<v<v<^^>v<<^<vv^^>>vvv>vvv<^vv.^.v>.<v.><^v>#
+#<><>^v^^<.vv<v>^v<<^v>^.<v>^<.>.>^.v<<^vv.vv<v^<v<^v.>^^^<^^><^vv<<<>v<>><vv.<.<<vv<v.<<.>^>>>^>^.^>#
+#<^><v<><v>v^^<^<vv>^^>^v^>v^>^>><v.>^<.<v<>.<^>>^<<^v^v^.><>v><<^^^vvv<><^>^^v.>><>>v<<^.v<v>^<>v^<<#
+#>.><<<^<v<v>vv>v><.<v>.^^<<<<<><v>^.><^>vvv>v^<^<^v^<><>>.<v<v^v><^.vv^^>^vv>v^<v^<<<>^.v^<vv<v^v>.>#
+#>.<>^><v><.^>vv.^.>v<<v^<^<><>...<>.>^<^><<>v>^>^<.^><><v<>v>>.<^v^<.<vv^v>.v^<v>vv>v>>>^.<^<v^<<..<#
+#>^<<><<^>vvv>>>>v<<^v^>><>..^>v>>^<v>>v^^^.>.<>.^<^<v^>>v><.v>^v<v>v<^.^<^v<.v>^v>v>^>>^^v>>>>^^^^<<#
+#>><^^v>vv>v<^<><v>vv^>^^^v^<^<><.<<^^>><<>v><><<>^<^>v^v^v<><v.><v>>..v^><v>><v^<^vvv>v.^^<<><>v.<><#
+#>^^vv<<>>^^^>v<<<<v>.v^>v>v>vvv<^^<<v<.^^<<^^v<<><<>v.vv.^>^>><^><<vv>^.<>>v>^^v>^vv>.^^v>^.vvv>><<<#
+#><^^^>vv.<^>^<><vv<><^^v<v.>.vv><^<.^^.v<vv<v<<<^<vvv.^^v^>^v.>^v<<<^vv><<v..^<v<^>>.^^^>v<><^vv^<v<#
+#<>^^.>><v>v>^^.v<>.^vv^>.<^<vv<<v<v<v>.<^v>.<><v><^<^^>v>>^>.^>>^><.<><^<<v^v^<>vv<<<>>>^>^<vv^v<^^<#
+#<>v^v><<v<v<.v><vv^v>><>><^.>>^vv>^.<v^^<^><>v<v^<v>vv>^v>vv<<v^>>>^>>>><>vvvv<^>v>^^>>^>^^^..^<v^<>#
+#>v^<^^>v^v^<^>.<vv.<^>>>v.v^^<<^^<.<^.v<<^>v.>^v<.vvv^<vv<><>.v^>>vv<<<v>vvv>^<>^<vvv><v^vv<^^v>^<^<#
+#<v^^v><.>>vv^.>>>^^><.v><<>^^><vv<><>v^v<<v^<v><.vv><<>>^^^>vvvv.^<<>vv.<.v.v<><><>.<><^^>v>v>v.^^<<#
+#<>v^^<v^^>^>^<<<><<<^^>v>^><^v^>.<^^.<<.<v>><..^<v^^><^<<<.<.vvv.<<^v^<<<>v^.<^><>>.^>v<>^v><.^^>^><#
+#><<^^^vvv^^>v^v^>v<v.v^<<<v^><>v><<vvv.v<>vv<<^^^><v^vv.>^<^><^>>v>.^<^^v^<<^><<^.^>vvv>>>.<><^v^^<<#
+#<>>vv.^^^<^^>v<<>^>>v^<v.vv<vv^.<<v><v>v^>>>^^<.><^v^vvv..><><>v.^.v<vv><>v>><><>v^<<^.^^^v<^>>^<^^>#
+#<>>.^>>v<>>>^<v>.>^><>^^>^vv>vv^><.<<<<<^<>.^.v^vv><v<vv>vv^^<><^.^>>v^<><><^v<v.>^^^>^v^^<v^><^<..>#
+#><..>vv<<>vv^vv^>>.^^>^v><^^v<<..<^>.>^<vv^v>>><v^.>v^<>..<^<<<^>v^v<>v><vvv^^v^<>vv^<<<v<<vv<>>v^v>#
+#>v<^>v<>v.v<>^vv.^<>v>>^v>.^^^>^<v^^>v>^><..v>v.>vvv^.^<v><^^v.^^<^vv..v^^^.>><>vvv>^vv^v<>>v^>v^v^.#
+#>v><<^<.<^<<v.^^v^^^>>vv<^<^^.^^^v.<<.^>^>.<vv<v<^.>.^v^^v<><><^<^<^>v<><>^^<<<<>^..>v>><>^.v^.<>^^>#
+#>>^^^^^v.<<>^^v>^vv.^<.<v^.^.^^>v<^^v<>v<^.>v<<<^>v^vv^><>>^^.><<>.v<^v^<>>^<>^v>v>>^^.<v<>v>.>vv^<.#
+#<<^v>^^>^>.<^<>vvv^^v>v<<>v<.><^<<v><v<.v>v^>>>^v<vv>>>>>v^>.^^^>^.<<>vv<^v<>v>v^vv>v><.v.>.v><><.><#
+#>v.^>v^^<>>v^.>^<<>><vv><<v<^>^<>.^<>>^^>^^>.><^>vv<<<v><^<<vv>^.^<v<<>v^.<<<.<>^<^v<^^<^>v>><.^>.<<#
+#><<<<.^.vvvv^^<v^^^...<>v<<<v^^<v<.>>>><<^^<>^vv<<<v^^><.<^><<.<>vv<><>vv^>>vvv^^.><^<<v>^^^^.<v>>>>#
+#<^.>>^vv<v<<v>>^>v.>^.vv^.>^<^v^.^<..><<.vvv>>vv>.^v^.>^<vv^vv^<^>>^>^>><<<^vv.^.>^>><v>v^v><^<>vv^>#
+#..v^>..>v....v<vv^<^.^>v.<.>^<<vv^^^>v^<<>v^v^>^<<>v^^^>.<^>^<<.v.v<<<^>>><^<^<<>.^^^<<<><^^^vv<vv.<#
+####################################################################################################.#
diff --git a/day24/uppga.c b/day24/uppga.c
@@ -0,0 +1,96 @@
+#include "common.h"
+
+void playa(char** lines, size_t nlines)
+{
+ board b = parse(lines, nlines);
+ b.lcm = 700;
+
+ set s;
+ s.n = 0;
+ s.nalloc = b.lcm * b.h * b.w;
+ s.d = calloc(s.nalloc, sizeof(*s.d));
+
+ uint64_t* best = malloc(s.nalloc * sizeof(*best));
+ memset(best, 0xff, s.nalloc * sizeof(*best));
+
+ uint64_t i, r, x, y, nr, cb;
+
+ for(i = 0; i < b.lcm; i++) {
+ best[i * (b.w * b.h)] = i+1;
+ s.d[i * (b.w * b.h)] = 1;
+ s.n++;
+ }
+
+ while(s.n != 0) {
+ i = 0;
+ while(s.d[i] == 0) i++;
+ s.d[i] = 0;
+ s.n--;
+
+ x = i % (b.w);
+ y = (i / b.w) % b.h;
+ r = i / (b.w * b.h);
+ nr = (r + 1) % b.lcm;
+ cb = best[r * (b.w * b.h) + y * b.w + x];
+
+ if(!intersects(&b, x, y, nr) && best[nr * (b.w * b.h) + y * b.w + x] > cb+1) {
+ best[nr * (b.w * b.h) + y * b.w + x] = cb+1;
+ if(s.d[nr * (b.w * b.h) + y * b.w + x] == 0) {
+ s.d[nr * (b.w * b.h) + y * b.w + x] = 1;
+ s.n++;
+ }
+ }
+
+ if(x > 0 && !intersects(&b, x-1, y, nr) && best[nr * (b.w * b.h) + y * b.w + (x-1)] > cb+1) {
+ best[nr * (b.w * b.h) + y * b.w + (x-1)] = cb+1;
+ if(s.d[nr * (b.w * b.h) + y * b.w + (x-1)] == 0) {
+ s.d[nr * (b.w * b.h) + y * b.w + (x-1)] = 1;
+ s.n++;
+ }
+ }
+
+ if(x < b.w-1 && !intersects(&b, x+1, y, nr) && best[nr * (b.w * b.h) + y * b.w + (x+1)] > cb+1) {
+ best[nr * (b.w * b.h) + y * b.w + (x+1)] = cb+1;
+ if(s.d[nr * (b.w * b.h) + y * b.w + (x+1)] == 0) {
+ s.d[nr * (b.w * b.h) + y * b.w + (x+1)] = 1;
+ s.n++;
+ }
+ }
+
+ if(y > 0 && !intersects(&b, x, y-1, nr) && best[nr * (b.w * b.h) + (y-1) * b.w + x] > cb+1) {
+ best[nr * (b.w * b.h) + (y-1) * b.w + x] = cb+1;
+ if(s.d[nr * (b.w * b.h) + (y-1) * b.w + x] == 0) {
+ s.d[nr * (b.w * b.h) + (y-1) * b.w + x] = 1;
+ s.n++;
+ }
+ }
+
+ if(y < b.h-1 && !intersects(&b, x, y+1, nr) && best[nr * (b.w * b.h) + (y+1) * b.w + x] > cb+1) {
+ best[nr * (b.w * b.h) + (y+1) * b.w + x] = cb+1;
+ if(s.d[nr * (b.w * b.h) + (y+1) * b.w + x] == 0) {
+ s.d[nr * (b.w * b.h) + (y+1) * b.w + x] = 1;
+ s.n++;
+ }
+ }
+ }
+
+ uint64_t min = UINT64_MAX;
+ for(i = 0; i < b.lcm; i++) {
+ if(best[i * (b.w * b.h) + ((b.h - 1) * b.w) + (b.w - 1)] < min) {
+ min = best[i * (b.w * b.h) + ((b.h - 1) * b.w) + (b.w - 1)];
+ }
+ }
+
+ printf("min = %llu\n", min);
+}
+
+int main(int argc, char** argv)
+{
+ char** lines;
+ size_t nlines = readlines(&lines, "input");
+ printf("#lines: \t%lu\n", nlines);
+
+ printf("#cols : \t%lu\n", strlen(lines[0])-1);
+
+ playa(lines, nlines);
+}
diff --git a/day24/uppgb.c b/day24/uppgb.c
@@ -0,0 +1,12 @@
+#include "common.h"
+
+int main(int argc, char** argv)
+{
+ char** lines;
+ size_t nlines = readlines(&lines, "input");
+ printf("#lines: \t%lu\n", nlines);
+
+ printf("#cols : \t%lu\n", strlen(lines[0])-1);
+
+ play(lines, nlines);
+}
diff --git a/day25/Makefile b/day25/Makefile
@@ -0,0 +1,17 @@
+CC=clang
+UTILS=../utils/reading.o
+INCLUDES=-I../utils
+
+all: utils common.o uppga
+
+common.o: common.c common.h
+ $(CC) $(CFLAGS) -c common.c $(INCLUDES)
+
+uppga: $(UTILS) common.o uppga.c
+ $(CC) -Wall -o uppga uppga.c common.o $(UTILS) $(INCLUDES)
+
+utils:
+ make -C ../utils
+
+clean:
+ rm -rf common.o uppga
diff --git a/day25/common.c b/day25/common.c
@@ -0,0 +1,74 @@
+#include "common.h"
+
+int64_t snafu2i64(const char* str, const size_t len)
+{
+ assert(len < 27);
+
+ int64_t r = 0;
+
+ size_t i;
+ for(i = 0; i < len; i++) {
+ r *= 5;
+ if(str[i] == '1') {
+ r += 1;
+ } else if(str[i] == '2') {
+ r += 2;
+ } else if(str[i] == '0') {
+ r += 0; // hah
+ } else if(str[i] == '-') {
+ r -= 1;
+ } else if(str[i] == '=') {
+ r -= 2;
+ } else {
+ fprintf(stderr, "Error! Bad SNAFU char %c\n", str[i]);
+ exit(1);
+ }
+ }
+
+ return r;
+}
+
+static inline void strrev(char* buf, const size_t len)
+{
+ size_t i = 0;
+ while(i < len-i-1) {
+ buf[i] ^= buf[len-i-1] ^= buf[i] ^= buf[len-i-1];
+ i++;
+ }
+}
+
+void i64_2snafu(char* buffer, const size_t buffer_len, const int64_t x)
+{
+ int64_t t = x;
+ size_t i = 0;
+
+ while(t > 0) {
+ assert(i < buffer_len-1);
+ switch(t % 5) {
+ case 0:
+ buffer[i] = '0';
+ t /= 5;
+ break;
+ case 1:
+ buffer[i] = '1';
+ t = t/5;
+ break;
+ case 2:
+ buffer[i] = '2';
+ t = t/5;
+ break;
+ case 3:
+ buffer[i] = '=';
+ t = (t+2)/5;
+ break;
+ case 4:
+ buffer[i] = '-';
+ t = (t+1)/5;
+ break;
+ }
+ i++;
+ }
+
+ buffer[i] = '\0';
+ strrev(buffer, i);
+}
diff --git a/day25/common.h b/day25/common.h
@@ -0,0 +1,12 @@
+#ifndef COMMON_H_
+#define COMMON_H_
+
+#include <stdio.h>
+#include <stdint.h>
+#include <assert.h>
+#include <reading.h>
+
+int64_t snafu2i64(const char* str, const size_t len);
+void i64_2snafu(char* buffer, const size_t buffer_len, int64_t x);
+
+#endif
diff --git a/day25/einput b/day25/einput
@@ -0,0 +1,13 @@
+1=-0-2
+12111
+2=0=
+21
+2=01
+111
+20012
+112
+1=-1=
+1-12
+12
+1=
+122
diff --git a/day25/input b/day25/input
@@ -0,0 +1,107 @@
+1-=022001=-1-
+2-1020=0-01=2000
+1==-2=122-=2-21102
+1-0=1=-0-==0=--=-2
+1-0-1=--22=
+2=110---012022-21
+22==0
+2-0-10=112
+2210=1-=-1-011=2-
+1-=-=0212
+1=100011=21101=
+2-===02
+1--120
+1=--1=-000-=00=210
+2220=210-01
+1=011--1
+100212002=0=0
+2-=2=0=-00022
+200-
+1200=
+1=1221-01-01-22
+1=1=22==-1
+1-1=201-
+1=10
+2
+1--2=2=201020-=
+1-2-==211=-221=-
+100-20=-002=
+1-021
+20021--=1
+2--2=0
+1=010=2-=200-01-1
+2=1
+202102
+100-0-0=0-1-
+2-
+22-12=0010=-221=-
+1=1
+10--120
+1210-020=-1-210=1
+102-=1
+2=0012=1=10=22-
+2=0
+1=222
+2=-0000=-=11-
+1-11-21=02=10
+11201---=1=202110
+10-1=21202=1=10=0
+220102=2110-1
+21110101
+2--0-0--01-01---2
+1=10=1-1-1=0121-=2==
+1---=0=10021011
+111=1=21
+110220==20=2
+20--12==20
+10-11=1-01
+2=-==11=
+2==2-
+1-0
+220=-=-102==
+10-0-20
+21201=-211001=0-11-
+2=020-=20
+12=-1---2-=2-02
+10=-=20-121
+12-
+10-02--0=-==
+11-
+212-2--1-1-=122
+1=2-
+2020=-1-1002-==-01
+2==11201==10-2
+200-=-0-0-
+1--=====12
+12-=02-2-1
+21-2=21==10-2=201-
+102
+111=00
+2=-2-0--222=
+11--=
+2=0-102=2=
+1=2-22-=20121-1-12
+1-==1-0=--
+100
+1=0=220002
+11-0-2
+12
+1-020120020
+2-==
+1020==-02
+220=-1
+2=-0==-2=021-000
+112==
+11=1-01=0-2=-10=2==
+1=1001
+2-=
+10-1==1=-2111-=2
+1=-0==
+2112===0-202=1
+102=-
+1=12=
+1=200=01=22-0
+1-2-=2
+211220=-01===-1==2
+1101-12=--=2020
+110001-001-==2=
diff --git a/day25/uppga.c b/day25/uppga.c
@@ -0,0 +1,19 @@
+#include "common.h"
+
+int main(int argc, char** argv)
+{
+ char** lines;
+ size_t nlines = readlines(&lines, "input");
+
+ int64_t sum = 0;
+
+ size_t i;
+ for(i = 0; i < nlines; i++) {
+ sum += snafu2i64(lines[i], strlen(lines[i])-1);
+ }
+
+ char buf[256];
+ i64_2snafu(buf, 256, sum);
+
+ printf("%s\n", buf);
+}
diff --git a/day3/Makefile b/day3/Makefile
@@ -0,0 +1,20 @@
+CC=clang
+UTILS= ../utils/reading.o ../utils/smallset.o
+INCLUDES=-I../utils
+
+all: utils common.o uppga uppgb
+
+common.o: common.c common.h
+ $(CC) $(CFLAGS) -c common.c $(INCLUDES)
+
+uppga: $(UTILS) common.o uppga.c
+ $(CC) -Wall -o uppga uppga.c common.o $(UTILS) $(INCLUDES)
+
+uppgb: $(UTILS) common.o uppgb.c
+ $(CC) -Wall -o uppgb uppgb.c common.o $(UTILS) $(INCLUDES)
+
+utils:
+ make -C ../utils
+
+clean:
+ rm -rf common.o uppga uppgb
diff --git a/day3/common.c b/day3/common.c
@@ -0,0 +1,14 @@
+#include "common.h"
+
+size_t map(const char c)
+{
+ assert(('A' <= c && c <= 'Z') || ('a' <= c && c <= 'z'));
+ if(c <= 'Z') {
+ return (size_t) (c - 'A') + 26;
+ }
+ return (size_t) (c - 'a');
+}
+
+size_t prio(const uint64_t x) {
+ return x+1;
+}
diff --git a/day3/common.h b/day3/common.h
@@ -0,0 +1,15 @@
+#ifndef COMMON_H_
+#define COMMON_H_
+
+#include <stdio.h>
+#include <stdint.h>
+#include <assert.h>
+#include <reading.h>
+#include <smallset.h>
+
+#define ASIZE (2*26)
+
+size_t map(const char c);
+size_t prio(const uint64_t x);
+
+#endif
diff --git a/day3/input b/day3/input
@@ -0,0 +1,300 @@
+gtZDjBcmpcDgpZcmmbgtdtqmCGVCGGsvhCFCCqvmCMMM
+JrhfzfLTNfJhPnhQnfzHfCFFQFSGvMFCGQFsQSMSVs
+TllTRrfNNlfzwhtZBZgtRDBp
+vMdwjZdjwjvjdTZZvCcQMGnQMQcbcgLLCL
+rsVhfmssPWzDVGCLJSbCgPLSQG
+lfWNDHDgfszFRTFtwwNjdv
+GLPqVqdVGCLCdczjMjzMfzld
+JnWQvJDmvWBtlMzhrzfHQgcz
+tDtJDDDDtWRRmBwJwWtpPRsGCGScLPGSqspNCS
+ChVzZzfNDzNJmBQfjjJfmH
+MrTMPMncGMJvPPvPWTbrMWvgmBgQwgdpwmdpdpjwpHQcdw
+SPvvvbqrFvMvZzJzsFVzVJNV
+mvBbvMFqbMMVVmtCBHpDdDPTDspdNWPDVP
+zjSfftcQtwtSfQSpNDppsNsjPNdRPP
+fgfStJShrgvvCLLv
+GmFnNNwbFFbhQQGQnGwwwfBgnMMqVDBZVVBMfMVzVz
+vWzRRHzTHcgfZDVfBgfH
+SSTvrvRcPpcvjFGwNGbNpbwQwz
+FFgbZZFZgFmpstLgmbtzqNrwVPlMPlSWWrMPNp
+QQhTvjhcvjjvTcTcTfCcSRwwWzwzPMrzWNNWVVhwrwWq
+GRQBfCRnGGTcDvBfGvffCCjnFZtFFgStJLbLHbFLJZdgmd
+pppdjcrMMRDJLJdRcwRDrwssqHGGDHsZHHsvBVtvmVHV
+nlCFWzGzzQFlSlhGWnPzFbSsBZmsssmVVmsBvnHqvNVqqm
+lFTTTCSQSTrdGJJLJG
+jpsGMgsmghQwQsMmhlQshjtTNTRTnFqRWnnqRfFnnt
+SLBCHrcvZHbSvSZrSvSWnfvVNvftVlFRTqnRTq
+JrzdZbBcHBCrrlHrrSsMgmGpJPDPQmpgQgPG
+cmcZHgwgMgHSLmtjLfWPNNrWBNfffp
+JTqGTsClHslVVRVCVGVJGnBrjdnnrdBNvjPNBNBrWvnW
+VVlQlqTFJlzzlsVGsRCZMthHDbwbFhgcbwHchg
+qgZjgjjbssqgsjlNqjhTtdrfQdTdWLLnDVfHtHWd
+zcGMBDDzcLnztfQQQz
+JSppJcBScMmMFFBRCpRCMmGlggvjhbhlNlglwbslCZjhDZ
+hvhmqcqwwcTBvvwQnRQnRnTRFzFzQz
+jWLPPtPsgMtpdLMLWllpgLLQFQhFJjnVrzFrVFhnRzJJrJ
+WPWffgtSdspdhSMdlSdtfBbHmSvqbNBCCmcBmcvcCH
+frVcrVcggfSZJfbbJvBd
+hwWQnwhWQmQmThTSsdvvSMBTBzcb
+wGnFFCGlQwntGtCtwntwDmFwRgLrHqNRqqcNNgRrHHLggCjp
+wRSwwHDMsRGHvNBNjTgvjgJD
+mcLcFCclWQWQpPQWVQcQcvvNJjrNBTrvgJgBvTRvCg
+VFPbQLchQLSRfbMtdHGH
+lfVrhnlRRqrJZVDJdHSWCvJCJSbj
+BFsgcgMNNQgSvbfCff
+ffNPcMtzqPlnmRGh
+ZJplFmRJmWRJRWmTJCvtTtnLCtndCqtqnr
+SQsVPQHBQZNSNSLCfSLrcLcrrr
+VMjPjbNMDsVHmRllmZpZWmjh
+LcTLRbJhhdhLJbbclfVvfWQVWFRWFFfq
+rZNttSNvtgsPPFsqBFPWQF
+HGCSmHrrwNnHGMLpDhbzzpmJJv
+VlSWzRtWSJqWdfhdqBdF
+mTDHsmmmcHpgrCgCrTsMMtqfsFNsZqfdMZMNbd
+TDcpvrpHCprCpHrmcQvTHgTQzSnLJnPPJlLzwJtRVJwLjJ
+vZSWZJZJFvhZldZHdvvlphZSNGNnmzwCPNHNHGNrrRHGCPmP
+bjfgcbjTQTFQBnGRRBCBNwBnCz
+csqscsbssQLsgQcLgLQLQTQpFdlhdvdZdpZWhJplShWWtq
+QgQvHnfflfBwQCfwlfglnQQccNcRqGGcjmcsGjddwdzsJc
+DhZbTLZTDMVTsRzsqsRjszTz
+FSZVtMLMMWbSgqSvPQlnpH
+MMPllnnBmfSHvBgCLf
+whZjGRJdjcNjjhRjCvgCfbSvCZLHfpZs
+RRWGWwNRWwhwclmrgFmngFPMWm
+VVHQGDGDGsdRrmZBQZRCVHZCNcSTTPMwwvTTwSSNqBqvgMvN
+nfhdLfjFnJpblLbJjWhtnjWPScNnwSTPTPqTvgngNNvSvS
+fpWljtpLjflfLfzlhZGQHZQVddHrrQRDRz
+VCHCjwCwMSZSqQzhhQqcWZJD
+GGGrFFgNRNNgmfnTdgmWQpczvPvQPWQJGDpzzc
+lgTttRTgmfNRntrTTngrCbjCwJCHjLBBHlMVMsbB
+szgPPlCblggVszhLmzvcvNrqpjNqmrqqpGvG
+wBQDtBfQDtFvLjjctLqTMr
+ZFWWdDLQFwSfDSBSQQBWnnnQVdbhgRVbsHzsshbClzzCVggb
+VpVsHVcqcMVMMNHpsspstbMqzBztJZTBBfJfzTvZfvWJWSTv
+mDDQgCQQQHdrwgSvZSmJJZvWfJJf
+drCjggDlPdgrlbjNcnhcHsbpsj
+cNNDRRpDcNcTpppsqHLQGLfRLvHzLH
+lFntJjtbFFlsmsjvnGqHWLfhfqzzQh
+sgPbjBJtPgbPJblblJgbgbwdBTwDCwpwrdZZVcCcDppc
+GGclMjLnnjCMchcChLMLcnnzRFJDZJSRSzzzzDSShszPRS
+VHgFQgwVwfNNpQVfHzQsPPPJDbmZbJDJbS
+HfNVWdHVvgHgVWVNppNWVHwTlvBFcClBCjcTLTlBnnLrTL
+GTLdlJhffQwDRvWLrp
+HVZVNjjsPqzNjNNmNgDWMrRQpWvWRHrDHBWp
+VCqVzjPjCpVqCVPCsbctcnblcGlTbGnlbFJf
+flHdfdBNdZcflBMjqMjBNfZQhvJbGvqvsshJQsJCJDWvvD
+gFTzRRpzRTwbgbLmtCvsJhWsChrWCrtWCC
+VzzzFbVRLPznmRBffPNBHNMdlZfl
+FFFMwCqJFFmrRwgnbLrL
+GpjGpQHQpfjdjDRnLrbrRQmJzzgg
+BphfhDcNcHNvPBvSqJMWJS
+NndbWpDBNbjvWLZqWsWQ
+JPFFTSPfgcMgftQQGjvTmsGqzssG
+gPgcfcVFgcHqSqVhbBCHlpbbpDlhDD
+FSdfWFTTBnjsDCjsmrrT
+pQzLRVLppLGcQjqbmVDJsChCvCbVsm
+qHLRGqqZzGjLqBNMFdnHlNlBFN
+DjqbfBTchDjqqCjjCTWNTbdzSVzGZQGBwZnQnVwpSSnQ
+ssJlPrtvMsRLrrJQGNZJSpZpGzSG
+rlFssHsvPRPMvFmtHvtqjhTgjbqhWqNmNqgDNh
+vcpnRqwwLLbvvcGpDQWDFSCgMrWWQWRR
+gtNfBfllrFlHrlrl
+ZPzftBmsNBNBPJBZPmZPNtmPdGLsqbwqpqcndVLLGpVGvqgV
+vRBfQqqBQPfbrFvPBvPbhLDVDVDQZVVtZtlWLLLt
+jcJmFFwnhJVZLWVl
+sHTcmNNHzncmcjmdsBCrBCPCrBBqCFrqzb
+bbZRnGmNnBGGMNRTgCmWWGGSrvSvFHvzFvFQDF
+LjwphpdPdLpLJVqfJrQzDzfrvQHSvDcQrQ
+DJphdwDsnmbZsTZM
+rdNrZNBSzSztnNzWCcNpHlMwlwHWlM
+QqLGLJvLjtvQWhgHgchHwHJw
+GtjTGtDRqvfLRGnrzsmZmfrVFBrV
+TdMhZrTTNvwphcLL
+WnnmffmDWnWPsPCJNpNcpNVNQp
+fsjbWfFFfnmmDsFDnnflSSdczlMdTHTzTTRRBdtT
+cMcPcMcwgWJMjWWhFWCCQCmqCFdh
+bSLVLblnNnLbVfnsbSbCChSQdChptpdqZrmCmZ
+DLGNfnGVDNDHbfzjRcRgqHMRBJPc
+HVFVlVHjzjjlCJjHjCjnvDrggrgLdqzddMqrzz
+SSfBTmtNdLqngvrm
+TwnNfPWWpBSBNtTHZCGlPHCQJHZHPV
+prvccpFQpMcQBwsvssshdwSTPD
+qbGHVbNJGqwdPgDrTsDJ
+fGbGqqlGGHflqLlzZBBrRcrtrZlp
+fCSPhltMBmPmbdgd
+DjvJJscvTsHHDbWzBWsWbdwgLB
+VVHDZvTppRcJVFFppvvRJDJqMSGqCtZdthttrnthSZMGCr
+ZcSrSdrhDjBDDCmZdZmZjhwVHwqVVsMwgswVVwMfhw
+PNvzTPNbnzcPbGQNJTvqwsWgVgVMMWpQqwgHpp
+JTPGPTzNttnbRTPlPtNNRlFrFmBcmDljjmBFSCmLZZBr
+mNvRRCVMtNRdFNtMtBHHprpHgJgJWwpBnprg
+LZDDlSLlTslDfbcpJJWndwcscnwr
+qdZZGSDhMVRCGtmC
+VGFjjgBShGdGzQczcGRG
+MppqCDfCMwfLDfvNmrtWstRcMPzRMRsRsPQS
+NwDCffLppbqqrqvTBngSbnBHglZllH
+vdllJVDzmVDVqvvWvdqJlcWrCsfCsfSSsSJfCSfQQCCbCQ
+jnTHZPZHMjZhMjTpHgMpgnbNqBstnfrtSSrBSNssCrfN
+LHLTFLjTMTTTwjHhpHTcwmDcWVDlvRDmvqwWlW
+rqQsSStdmsdLqlNNPGlGlV
+FpFpzJNTcHzRHRHlGwFVLFBLFGVvlw
+WCCjWRNJTJWhQhbhrbnd
+jsQjfrRTRwzSsRTgNchlnlhqcnlQmQ
+dFDtdFBDddHLJpVpHHtVbtHFCWlWlGlNlmGggNqgglmcchqb
+dLDHMVdLtBBDBFVJBFthtJHRTvsMSvsTrTSRvPPjPzSwRP
+CSPpSrLlrlPrPchLnSlbDbbRttDVhbGRDDJRtD
+fzfvmzTMmfsFszsHZsHMHVfwtbjBDDGjtRBjQQGGJb
+HmvmTFmqmTsHqzzzzdTsMMScndccdLppnLCSPcCLrVgr
+pfMflRnfrnjrpjnFzDpfDMmMLRTLZVTgLsvdZgLLZHSVWZRd
+tBGNhwPGcNBBWwZddsSTTPgVLPdT
+JwthtwbbhNBQhwhbBCrzpnprnWnprlzWlClD
+PPnZZjnFNDjlJJhtMddfTTdD
+QGLHFWvQJtzfpvCt
+swqSmmQWLQwFWLwwRcqNNBnnbgPqbPNbglVZ
+GCLSjjZGZhpvGtBgjJlnJDhhJMVDPnJlJP
+mNtQQwNzQRHWdJHnPTsddlln
+zQrfmbtNbcQcrzmrRBZqBcvpjSGLZGLZBB
+zGNzgsjDssvNbPlWJfJq
+RLMVSRMLhCLZSMZHDSJWvpcqfbfhvpJqcWPv
+dMVHLFHLZMLRLLFRHHHVZMgDTntgstGwznzGGnzjDFwG
+wCLCHLBwzBtQRLHLbNFFfdqdDqVrVfBN
+JGvljmgGZvMlfDRRnnnZnfND
+GppRlgJlSllSgjMsmllpTjcCLczWztPWPwwwzWThtcQh
+WvHbvvWnFHszDRSltcCctCFD
+gCmJmCCPTPqpgrZtjdRtDRplcSjS
+rJJrQPPJQmrmrhGTznCfLMMbfvWfbCWQ
+TqBWtTbFBNNRRtwQpJJvvvZPpTSQ
+fRMfsMssrGhSmMwSQvvZJm
+VggcVlsCgHnVFnndbbnR
+NdrSSWBNPPSWWHPPlwlLZHLZLMhjlLLH
+pVptMTgVTzLwZTzlbF
+qsRmRJtsMvMqgqgRvCdcSrWSPcWrDmmdBN
+nbJnfqWcmCMnSBSHwzWBsHHz
+dVpdvdppdptppDlvlHcczSgNcgww
+VGTdTVtGtRLFPTDbcfCmmcCQJQjcrT
+VTjrjrjTlTjQMdpGrWMSHvSG
+wnNJbDmttnwnhNwcJmNGdvWvMSfvMfhSSppSdp
+JznFnNsGnzzGFDJsFNmLgVVQZBlLZjQTLTjTls
+hpngHwcpWHgjjfhzTJBfBB
+RFFbFlQlSdRsbRQQMGPRGdSGjBvvNTvzZMBvjzBBTJTvMBBT
+GPSSPDDDFzGlGGRzLzGGPRWqnprcgCHwCHpwHWVcncLV
+LLlLGffQLPRThRwP
+MpZjbmznWqmqZznmzmpZqZnMRgPBCTPfgRTTwTjhwBPPghjP
+VnZpMsMMJnWsmnJpJmzrtFlGQFrHGvSvfHStNV
+MQqHMQPnqmpDdTLLRnDjsj
+NGFzwgtLBtFFGrrCtzgfgCNgSsdTDSSTsdssjDdSlZRjTSBs
+zCwNLthfrbCgzzhqhmccJPhQHVmV
+SndBVcgdqcRBRcdPBBcVcQTSSMLMlTssMNMWsHMsLQ
+GmJvZvhqpvZtNwwWLTTLwMMm
+JFJpzFGZqjvhGZcjBPcCBBPnnVBc
+rJWbqTvwvJNbPDPPvLcZvPDp
+QMnfBsjmFPLcHRDfPp
+lQlMlmtFsMMBstljlnGhtMhmGNqJqTcWNNbWdGwdNNJCrTrq
+LcjcNCQNQWDpRDjRTj
+vWvszVVSsBGWsTJRFHRJTTSTRJ
+vvGbtqbGVVBqtzbqvBdzVLWNLClwnwMLWlQNMfdPQP
+TWBZsWrjzZzWBrBsrrsTLNNJvFnJVmlSFFQnGpmnSJJS
+qdCggdqqqhhqwhRbCwbCPqhlJFPPGJQVvvvnpVVmPnnFvS
+ffgCfghDqDdCsGWZjTsLrsfW
+QzQSSQmzSsLQcLmrcsLzccgqCnwqCtZDnDnrZwgnqTTT
+hFRHHRPRPMtWPGVPRlMljRPCgWBBDTgJBgnwqTZDBZDWDB
+jPjPHRMjjvdjVFhdNfbsbbQfbcddmNtL
+jJlTqMqJtdztJqzcSJSlTdSlprLsRRHwcRRrsrHbrnnRHsHL
+VVVMWNNWmNmLnPLRHrLp
+NGhfvvVWBNfNNCNCQTMqjzgTQBSSSqll
+SSSRMRSRpnMRHLqWLfPlDGlGWldD
+hbNtlmvrNrsVDWsGPfPfqG
+jvbBNmvlJjRcCzHFppCJ
+hhWWPjnBGBGnjqBWSnhhsNLllLNcLczJcqcTlLTlfl
+FHvFFMHwdmvrDbwCbbvHwdHnZTMLzTNTczflJTZclzNLlLcJ
+HdFFvdDvpCDdrnwrGhBQhWRRpsjQWWQW
+sBsvtJtdRdjNbWWrTllqlNgg
+nSZSnPPZzMSnSlScWWWgrVWCrqgrWMWr
+lzSncQcLZLzlwDvtdDdFdFJJhHvJ
+lpsTLDlTtFtlWHPDvvgPfgMrQQJM
+zmNbzcNjzldjwmbdbhhjcjRgfwrgvMwMMSRJSvQQvrRf
+ZhjqcjzNhmzNqBqNznmcWHplCFGnpCtFsGWHHWsH
+ZPGQBFHFbhSrHqtfSrSr
+nMdznzzMDTnjMQrMWtrMptplqpqS
+wzjczJmccTJCmcVghZBJbPBQBbVh
+wLLMJbqSBBnnJhbvbFSSRRlztTrHzrrrrd
+QNNGVPjWPGVqltTHWCqCdH
+sjNGmmGVGgQNGDVmsVpgqQVpMDhvbLwMffZfhZbLnfLLLZwb
+gQLcQrMtBPdwSBsSlmBm
+TfCpTJnTbfqgsgwgppsSzp
+jVbvTnvWfJnJjjbfCjWWjrFPrLMtcDPgLMQQRtgZVF
+gwpHvpgwngGHcnvNvgnmsqCzmMzlfqmmqzHHCm
+JrdSLdBVPRDtRtPfPPzCJhjqmljzmmqszzsM
+SWLDDtVdrZWtSBRZfRcwgFGnpNFpnTnWnTvT
+rpcnHrwrhWccNZDDBBgBVCSW
+nmzFRRjFmmJQNDJC
+qznMlqGnzRtRGvqGFRPrdMhwTpTLfLcppLHp
+wthvbmhmChWMRJLJzngZpzLLNC
+SsdBVjSTjBdffBFfcSdVHfTrnDZGpQgNZHNnLZGpJngJGLng
+sSdTcdVScdcrccjcrBPrBSjcvmRRwlWPhwmqtgWhMPtmMMqR
+CJJBdBCrHdBhtRHctBQhRMrBwZpwZWNZNSNTwSNpQWpZsSSW
+LVFnvnbDjLsDPsPqFFvPvDnTzSTwNwPZpSmpSpgmgZWNTW
+LjlflbFjsvVlrHcrHtrfcChH
+tVLJGNRtfBBNGBrfrbzmfhPsrsPC
+DWWDQHQgllSFqFzcsJmzzSSzmrrs
+MJFQDgMqnHlDvFdGNBNNZGNVVvjV
+wnNwGCBBFNWBqjFBnLLGVDHhHmDPHvZTjTvTrPvD
+bMbttVScMJQtdgSgstbJRSPmrTHmHmrmmSDZlrPrPDhv
+cMbgpsbVbzbdRMRFWLqzBfLGwwwwfW
+JpSnGSGpbGgsWWPHJrdfsT
+MNsRqNNvMQDTLWHlffNHLN
+qqmtRzRvCRRQDqjqjDmsmRpZwSZbcwbnCcCSBBnSSnnC
+TWqlqpRqRptqlRhrmtGGzhbSrSdz
+VgsBVMvgVZfZvPsMVNvfZfvVbSPdhFPFhbzLhJdGFJmLhhhL
+QZgvZgvHwbwHbMsMRllRjDRDnQRqlRjl
+fsPQwnHnHLLfnBBnwwGtjTGRWTWTWwhV
+jblbdjZFDMbGllqTGTtVlq
+gmdMgZMbjpZDcrrDgdmszsPLpQfpBPPnNQNLLz
+HRsPPGMhLPMrnPchPSwStjbSttSvtHSqQw
+dfsCfpCJVJCvdFBFwStwjj
+gTNWmWfTNVZVJzZWpWJgTpfhnDrMnDclgDlDrDRnRcMLDs
+ZQZQJMqdwmZvqfPmwRjpBBjHjnshnjtt
+zcTPTLDTFWLGTrTSWPcDSSHjRlhRsDhHslslssBRljjj
+TrNFLbTWrGNZvmvVQPQV
+htfLgmtSLcTWNLcT
+slbHlBBGbqRsblBHvdNJJcjFFNBTVWWWcn
+bbQsHMMblHrMsGRqvQhwCTQCwtQCzSpfmS
+zmqdphmFmSpTzhdqhFmwjjGbtcvDbcGGjllGQjSP
+HJFrMCsVLrHRRMCNrVMVnctvstlGcQlPtGGjQtGlvP
+RFLHLVWrNgVJzwzwfgffwdfp
+vdMjSmMMpmMWhRpndRmZnhvHqLpGHcJGGGDLHHLGcfcLfc
+lPBwwrsCgLFggcqqLW
+TWszsWNBTNdmSRvjbZZT
+zFlBGpzzzLLNjBwPcwwmcNPfWNQn
+VHSHRJTJDSVVnmcVVPpWmpnf
+DMZHHrDHHrJrrZrShZsHGbMBbFgGjGCgjpFlBzzb
+FVMpsvTqvqMssVsWZSrqWFvwlGDGwQzwfwQQNLzDlwlZwf
+hPbgBHhJJcJPwCwDpNllCCHC
+pnjbBmjgbgmqtSmsTtsF
+DHZHmfTmCfjDZHMZmzffHHnQwwTBdQwbSdBGBQwhBQTQww
+cqstRFWNtLrNFwdVShlBSlhBRl
+StJWpLptNWLtJcpqPrFHDjZzzvnDDHPCZjPvvz
+hzffhGVGGhzRqTBLTqHL
+sFFFsMQlwJMsmrBFSNHTHNqrTS
+pbdsJMdJMJbwbmJJtbTtgnffGgVVChvD
+FvJnFnCpQTddSSmFdFpPPsVhppDjBzjDVhDV
+RgZMZbsgzlDPlhjb
+cHHHRgRZgfHHZGZfHZcLLHrrCrmJCmddrsvdJsmvFFQG
+dpJDdZwLnvdvFmFMmHjslMLH
+CGCztgPhWCWhzzzNNPGfrrWfmbbsmmHjFHDMsbHMsjFPjbHm
+rNQDGzzhCCfNrzrDzChTcZZvQcTRJpTwdvQpVc
+VpvNGhGHGNhHbPsbVbvfFtLCzSCFSBsCFSFCLB
+MlqJwTnrRRrRnMlQMHfHzHzWFWtmTzLWFC
+ljZDDHqqjqRbpNhjNNgcgc
+qrQtDzcQzbrcfdbqrQrthtscSsvpvnsSHpTpLpspmsSs
+CVwNNVRNBSHsLSFBTv
+CVVVNZjlVlGwlGlljNlWJVrrfqbPQQqHqJhhftbfDJqf
+lpmrPDPDjPlmWrVzPztZwFjtFbBnRtZbbcRL
+dnqJCCgQdNqbqRbRbBLt
+QGhGddGCTdMHNTGgshgJhzvSmWWPSsnprpPzWzsWlr
+hCJHTdJJNvTdSSNssjvfwgntwDgtgwDGCtZwtRRB
+mbllFmFMFbMVWWLpbpZwwBZTZnnVwnTggtDB
+MmzLQpFPTmPzHvfJNNzhNs
+dzgBwzlgrrBrVLLlwLBgBlgRScDMMDDswMsHZRGDsZGZmM
+HPfPbjCFJjCvfnnsjsDDcccmZsRSMc
+hCvHfWPPnvJhPWpqNNhqLqzLqLLd
diff --git a/day3/uppga.c b/day3/uppga.c
@@ -0,0 +1,26 @@
+#include "common.h"
+
+int main(int argc, char** argv)
+{
+ char** lines;
+ size_t nlines = readlines(&lines, "input");
+
+ size_t i,j,sum=0;
+ smallset a,b,c;
+ smallset_init(&a, ASIZE); smallset_init(&b, ASIZE); smallset_init(&c, ASIZE);
+ for(i = 0; i < nlines; i++) {
+ size_t slen = strlen(lines[i]);
+ if(lines[i][slen-1] == '\n') slen--;
+
+ for(j = 0; j < slen/2; j++) smallset_insert(&a, map(lines[i][j]));
+ for(j = slen/2; j < slen; j++) smallset_insert(&b, map(lines[i][j]));
+ smallset_intersection(&c, &a, &b);
+
+ sum += prio(smallset_getone(&c));
+
+ smallset_empty(&c); smallset_empty(&b); smallset_empty(&a);
+ }
+ smallset_clear(&a); smallset_clear(&b); smallset_clear(&c);
+
+ printf("sum: %zu\n", sum);
+}
diff --git a/day3/uppgb.c b/day3/uppgb.c
@@ -0,0 +1,28 @@
+#include "common.h"
+
+int main(int argc, char** argv)
+{
+ char** lines;
+ size_t nlines = readlines(&lines, "input");
+
+ size_t i,j,k,sum=0,slen;
+ smallset a[3];
+ smallset_init(&a[0], ASIZE); smallset_init(&a[1], ASIZE); smallset_init(&a[2], ASIZE);
+
+ for(i = 0; i < nlines; i += 3) {
+ for(j = 0; j < 3; j++) {
+ slen = strlen(lines[i+j]);
+ if(lines[i+j][slen-1] == '\n') slen--;
+ for(k = 0; k < slen; k++) smallset_insert(&a[j], map(lines[i+j][k]));
+ }
+
+ smallset_intersection(&a[0], &a[0], &a[1]);
+ smallset_intersection(&a[0], &a[0], &a[2]);
+ sum += prio(smallset_getone(&a[0]));
+
+ for(j = 0; j < 3; j++) smallset_empty(&a[j]);
+ }
+ for(j = 0; j < 3; j++) smallset_clear(&a[j]);
+
+ printf("sum: %zu\n", sum);
+}
diff --git a/day4/Makefile b/day4/Makefile
@@ -0,0 +1,20 @@
+CC=clang
+UTILS=../utils/reading.o #../utils/stack_u64.o
+INCLUDES=-I../utils
+
+all: utils common.o uppga uppgb
+
+common.o: common.c common.h
+ $(CC) $(CFLAGS) -c common.c $(INCLUDES)
+
+uppga: $(UTILS) common.o uppga.c
+ $(CC) -Wall -o uppga uppga.c common.o $(UTILS) $(INCLUDES)
+
+uppgb: $(UTILS) common.o uppgb.c
+ $(CC) -Wall -o uppgb uppgb.c common.o $(UTILS) $(INCLUDES)
+
+utils:
+ make -C ../utils
+
+clean:
+ rm -rf common.o uppga uppgb
diff --git a/day4/common.c b/day4/common.c
@@ -0,0 +1,10 @@
+#include "common.h"
+
+int readfour(uint64_t* v, FILE* fp)
+{
+ if(read_next_u64(&v[0], fp) == EOF) return EOF;
+ if(read_next_u64(&v[1], fp) == EOF) return EOF;
+ if(read_next_u64(&v[2], fp) == EOF) return EOF;
+ if(read_next_u64(&v[3], fp) == EOF) return EOF;
+ return 0;
+}
diff --git a/day4/common.h b/day4/common.h
@@ -0,0 +1,9 @@
+#ifndef COMMON_H
+#define COMMON_H
+
+#include <stdio.h>
+#include <reading.h>
+
+int readfour(uint64_t* v, FILE* fp);
+
+#endif
diff --git a/day4/input b/day4/input
@@ -0,0 +1,1000 @@
+33-62,26-62
+49-89,49-88
+2-4,3-92
+7-98,7-98
+6-74,6-73
+78-79,13-78
+90-95,95-95
+62-66,56-67
+2-93,4-92
+12-64,11-11
+7-83,5-91
+20-87,20-88
+29-93,26-92
+19-20,20-31
+62-62,7-63
+9-83,9-84
+8-27,28-95
+6-49,6-48
+7-71,65-71
+90-96,19-89
+13-97,98-99
+17-75,75-76
+90-91,44-90
+5-62,24-92
+45-76,46-76
+9-22,23-23
+93-94,35-93
+32-34,33-48
+43-44,6-44
+79-86,80-86
+7-7,6-93
+77-82,83-91
+59-60,32-59
+7-27,7-7
+2-23,22-23
+35-35,6-36
+32-34,11-33
+24-35,28-34
+37-62,62-64
+9-18,18-18
+8-53,2-7
+2-99,1-99
+15-95,65-94
+17-71,6-18
+38-71,13-63
+6-77,4-9
+1-99,2-98
+13-67,13-66
+45-87,45-86
+13-59,12-82
+18-79,17-19
+83-83,36-83
+38-77,38-76
+17-17,16-41
+78-94,79-94
+36-87,6-91
+30-38,29-29
+54-56,22-55
+43-43,37-43
+2-99,1-1
+16-88,15-17
+13-14,2-14
+26-57,26-58
+19-86,19-86
+97-98,67-97
+1-92,2-92
+1-3,3-77
+25-54,54-54
+44-53,46-60
+16-74,74-74
+4-7,8-28
+96-99,95-99
+37-70,36-80
+59-68,60-60
+47-95,29-87
+91-91,68-91
+18-91,19-90
+16-27,5-28
+94-96,63-95
+3-20,19-73
+18-74,8-80
+6-71,3-72
+52-71,53-93
+6-8,7-97
+68-77,22-78
+29-76,30-30
+13-98,13-99
+7-73,3-74
+64-98,16-74
+20-78,9-21
+17-65,18-18
+71-96,27-96
+55-91,46-56
+93-96,5-92
+15-15,14-77
+18-49,17-49
+77-78,70-77
+31-88,31-87
+38-85,57-86
+39-87,87-87
+26-77,76-77
+1-1,3-47
+5-96,95-96
+25-78,15-60
+11-84,84-84
+22-30,22-30
+6-85,83-86
+32-40,32-39
+4-97,4-97
+34-90,26-91
+23-68,23-67
+41-51,30-33
+21-83,22-82
+21-85,1-74
+72-74,6-73
+6-6,5-94
+10-83,10-83
+11-85,5-12
+81-82,82-82
+4-82,82-82
+25-89,25-25
+70-79,74-78
+17-51,26-50
+7-70,6-70
+21-81,21-80
+72-88,71-71
+68-72,21-73
+74-95,73-75
+15-94,12-13
+47-96,48-96
+58-70,10-58
+69-69,63-69
+7-95,7-94
+13-66,13-65
+1-18,2-18
+4-90,4-89
+24-84,23-23
+89-90,14-89
+8-10,7-16
+16-18,21-96
+19-30,1-29
+78-99,9-97
+2-9,6-19
+58-82,53-85
+51-96,51-97
+11-70,69-70
+1-2,2-95
+93-95,41-94
+95-95,10-96
+18-18,17-48
+1-99,2-2
+66-68,67-98
+5-7,6-90
+49-94,50-66
+12-41,2-91
+10-93,93-94
+27-51,27-52
+9-15,15-99
+16-47,15-48
+11-89,25-85
+39-77,7-64
+9-91,91-92
+65-66,22-66
+9-83,9-31
+8-78,8-77
+2-98,2-99
+33-53,25-50
+11-91,9-97
+46-90,2-91
+69-70,70-95
+39-53,15-39
+63-85,64-85
+15-82,13-13
+38-55,56-56
+14-34,14-33
+28-47,24-46
+8-98,7-98
+24-35,27-98
+44-67,45-64
+65-90,65-91
+23-89,21-24
+1-2,4-48
+12-97,13-89
+11-91,41-90
+72-72,11-72
+5-61,6-75
+25-77,25-78
+1-98,5-96
+22-57,22-56
+69-92,25-69
+6-85,5-85
+46-48,19-47
+19-25,24-94
+6-96,3-12
+18-67,67-68
+42-43,42-96
+95-95,74-95
+20-38,37-68
+2-72,2-73
+21-23,25-71
+4-29,4-29
+87-88,41-88
+59-66,66-92
+54-95,54-96
+5-88,88-88
+73-74,46-74
+12-13,12-41
+5-11,7-12
+62-64,18-63
+98-98,2-98
+69-77,28-70
+7-62,29-61
+7-7,6-98
+35-94,9-35
+77-78,77-90
+10-10,9-86
+26-32,4-26
+79-92,27-85
+40-88,41-82
+20-58,15-59
+64-97,63-65
+6-23,2-24
+11-15,13-14
+16-88,15-26
+35-77,36-77
+47-94,25-48
+17-54,5-53
+97-98,98-98
+9-87,35-86
+46-89,2-46
+11-49,33-48
+41-80,40-98
+11-95,10-10
+22-71,11-71
+14-63,64-64
+49-51,50-97
+1-81,82-82
+36-93,1-93
+38-80,38-39
+41-66,10-65
+20-44,19-21
+42-98,41-98
+65-78,66-77
+2-5,4-96
+15-62,62-63
+7-85,6-8
+46-82,45-81
+45-47,46-85
+18-39,37-44
+40-64,63-64
+24-49,24-48
+64-94,63-63
+22-23,5-23
+13-96,12-12
+43-75,43-75
+15-96,70-95
+42-43,42-53
+64-66,42-77
+86-94,88-93
+35-94,9-93
+5-98,6-6
+21-97,20-20
+7-99,8-8
+12-12,11-88
+6-48,7-48
+60-73,61-73
+28-56,27-79
+39-61,2-64
+78-78,28-79
+35-97,13-96
+8-97,9-90
+6-96,4-4
+23-98,22-97
+11-78,11-79
+37-92,37-92
+33-66,32-67
+27-88,87-88
+32-89,90-90
+7-96,7-97
+10-98,10-10
+2-83,82-84
+2-13,13-82
+23-27,22-24
+46-85,47-89
+16-71,70-71
+4-79,3-76
+96-96,1-96
+15-89,15-88
+22-32,26-82
+21-21,20-21
+5-67,6-68
+46-60,25-61
+56-95,34-99
+11-74,11-75
+2-14,14-97
+4-97,11-92
+19-34,18-18
+4-20,5-33
+91-91,68-91
+2-99,1-2
+68-87,68-86
+3-98,3-3
+91-99,9-90
+21-58,26-56
+33-70,34-64
+81-81,82-83
+49-66,48-50
+10-11,11-62
+7-92,29-83
+19-89,88-89
+7-42,42-90
+60-76,76-99
+51-53,52-91
+33-56,34-57
+5-88,46-87
+15-96,15-95
+8-27,27-95
+96-98,38-96
+9-40,41-43
+68-83,68-82
+5-11,7-93
+50-50,8-50
+26-69,68-70
+23-44,13-82
+90-94,93-95
+1-95,1-96
+29-31,30-83
+49-81,48-50
+41-70,42-70
+10-73,11-72
+9-10,16-18
+72-73,1-73
+47-71,47-48
+4-97,23-96
+10-96,10-96
+15-43,43-80
+57-82,18-57
+4-19,2-2
+46-81,38-82
+55-72,24-55
+63-64,60-64
+12-99,22-97
+31-62,53-67
+41-87,67-86
+30-30,31-82
+20-34,19-35
+76-77,43-77
+25-52,32-53
+50-95,51-98
+50-50,49-75
+4-91,90-90
+61-89,60-89
+4-93,4-94
+22-93,22-94
+50-66,49-58
+22-89,23-88
+20-94,33-93
+12-30,11-71
+11-54,11-75
+6-60,5-6
+36-45,3-46
+84-96,31-83
+25-25,25-29
+17-18,17-30
+45-69,45-70
+64-98,65-65
+5-60,16-59
+81-81,25-81
+23-69,66-70
+34-97,35-96
+7-90,6-97
+76-79,75-75
+27-97,27-96
+14-34,23-32
+28-95,94-96
+36-68,36-67
+25-27,26-96
+93-95,67-94
+29-91,30-30
+57-58,29-58
+44-65,43-45
+2-16,16-34
+15-99,16-43
+33-62,33-62
+1-79,1-80
+60-96,60-97
+28-28,28-50
+90-94,33-89
+14-51,13-15
+3-76,3-77
+21-48,25-87
+23-25,24-97
+74-76,74-75
+34-36,35-74
+78-96,79-96
+3-94,5-90
+81-95,81-94
+62-70,61-73
+55-55,20-55
+88-90,6-89
+88-88,3-89
+14-99,13-15
+6-78,29-77
+63-73,72-73
+38-38,38-87
+5-93,5-94
+66-90,45-94
+42-68,41-43
+62-90,86-90
+16-50,15-31
+80-81,63-81
+49-62,38-50
+70-90,53-96
+19-19,20-81
+7-16,15-75
+9-98,92-97
+29-95,28-95
+99-99,1-97
+39-96,40-40
+1-1,2-99
+24-28,7-23
+9-57,8-74
+27-31,26-27
+6-93,5-93
+39-89,38-40
+43-84,84-85
+3-69,2-2
+24-88,87-88
+6-97,2-96
+5-93,4-5
+43-43,44-86
+17-73,17-72
+85-86,28-85
+9-35,35-36
+14-93,13-22
+62-64,30-63
+71-71,48-71
+48-88,49-78
+13-57,58-96
+21-81,10-19
+37-39,36-37
+14-17,10-15
+23-74,73-75
+4-29,1-5
+2-96,95-99
+13-82,12-13
+51-98,51-97
+21-21,20-37
+17-68,17-69
+32-49,68-74
+55-73,49-74
+11-53,10-12
+2-4,3-99
+55-56,53-56
+14-24,13-25
+19-58,18-58
+62-87,62-86
+11-93,93-94
+44-64,43-80
+2-82,3-82
+37-38,33-38
+97-98,18-98
+12-47,46-47
+5-95,4-96
+22-98,16-21
+1-70,69-70
+8-93,8-92
+36-89,36-90
+84-96,82-86
+38-38,37-89
+77-96,96-96
+80-82,23-81
+48-92,14-49
+80-80,5-80
+49-80,20-81
+77-85,76-78
+6-6,5-90
+42-97,42-96
+98-99,45-99
+25-95,94-96
+1-66,7-66
+43-44,44-65
+14-71,3-82
+4-11,4-49
+31-43,33-42
+65-99,9-66
+48-98,98-98
+4-78,5-77
+21-38,22-22
+5-99,99-99
+1-1,3-17
+53-97,17-54
+8-57,7-7
+83-95,25-96
+43-49,42-42
+80-90,81-90
+33-65,34-60
+48-65,11-66
+4-99,6-92
+7-60,6-60
+3-47,47-85
+27-59,26-28
+57-76,73-77
+52-60,51-72
+2-99,98-99
+37-70,70-70
+19-95,5-12
+1-98,1-2
+84-89,39-85
+24-89,89-98
+15-16,15-24
+10-10,9-77
+9-39,8-58
+13-73,13-74
+32-60,13-61
+55-70,57-65
+54-56,42-55
+2-27,11-26
+9-83,8-85
+39-40,12-39
+50-52,15-51
+97-97,4-97
+58-59,2-58
+36-37,37-85
+32-77,31-33
+73-96,6-94
+84-86,52-85
+24-26,25-75
+2-79,1-2
+36-36,35-68
+6-50,5-50
+6-94,94-95
+6-28,3-29
+53-53,33-53
+5-98,95-97
+33-91,34-34
+18-83,84-98
+41-41,3-41
+34-90,89-90
+73-73,4-73
+56-57,57-78
+2-4,4-94
+61-70,53-71
+73-74,74-74
+3-99,5-98
+7-66,66-73
+4-13,12-13
+71-79,70-80
+58-93,57-59
+7-90,8-90
+53-94,22-53
+9-47,10-47
+19-99,37-98
+55-55,55-55
+48-84,28-85
+57-90,57-88
+70-70,3-71
+6-68,6-68
+1-4,5-97
+12-42,13-13
+2-78,2-77
+29-61,7-86
+71-71,43-71
+63-74,42-75
+83-83,58-83
+4-20,3-4
+30-92,31-31
+2-15,8-40
+13-69,12-14
+81-82,21-81
+33-45,33-44
+87-92,18-88
+52-96,95-96
+10-53,11-52
+81-95,81-96
+8-8,4-7
+4-99,3-5
+51-77,52-76
+17-89,16-16
+19-21,20-80
+1-3,2-94
+96-97,3-97
+50-58,57-86
+38-98,38-39
+8-97,5-9
+11-96,95-97
+28-43,27-44
+21-26,20-25
+58-97,12-92
+1-3,3-88
+11-47,10-72
+1-71,3-85
+40-40,39-97
+3-89,3-90
+7-92,37-91
+73-89,61-90
+61-80,28-92
+61-62,11-61
+19-80,19-80
+4-6,5-78
+6-54,16-81
+92-97,20-91
+61-62,5-62
+40-65,39-39
+57-66,54-67
+2-98,3-76
+13-99,12-88
+96-97,2-97
+46-56,56-57
+7-94,11-94
+5-78,4-5
+31-71,31-79
+47-47,48-83
+72-91,72-92
+36-37,37-70
+57-98,98-98
+7-99,7-98
+2-99,2-98
+27-96,95-96
+19-27,28-93
+1-9,8-52
+92-92,1-92
+38-84,84-85
+94-97,22-95
+19-37,32-36
+4-17,17-96
+27-80,28-99
+40-60,59-60
+8-96,8-97
+16-75,15-36
+33-73,34-73
+54-76,75-76
+49-87,86-87
+11-38,38-91
+40-69,68-69
+39-41,40-40
+90-90,64-90
+11-82,12-56
+28-90,89-90
+90-95,8-91
+9-92,10-91
+10-98,28-97
+29-30,30-91
+26-91,26-27
+7-91,69-92
+21-93,22-63
+6-8,7-35
+71-71,63-71
+39-47,13-48
+15-79,15-15
+9-73,9-73
+46-69,17-88
+16-97,18-86
+8-65,64-65
+1-44,2-43
+33-78,32-32
+23-97,40-97
+21-22,21-74
+93-93,10-93
+21-22,21-42
+2-5,5-18
+21-51,18-37
+38-92,47-77
+83-84,3-83
+16-94,15-95
+1-92,92-93
+1-98,98-98
+48-89,34-47
+9-44,10-45
+88-90,43-89
+3-16,17-29
+39-44,1-40
+41-67,38-75
+2-6,1-7
+8-67,9-55
+42-60,42-61
+18-52,31-51
+46-47,47-74
+24-69,23-24
+30-30,30-31
+1-84,83-84
+2-87,1-87
+9-50,9-51
+28-83,20-34
+19-47,40-51
+3-86,4-4
+17-79,1-2
+26-75,25-75
+8-16,17-54
+35-90,42-97
+1-18,23-62
+2-12,1-39
+13-90,12-96
+71-91,71-91
+23-60,12-24
+26-84,54-83
+18-24,18-25
+18-56,23-55
+32-59,31-33
+35-52,34-81
+22-72,22-71
+8-38,7-37
+34-69,69-69
+10-79,15-68
+16-87,24-28
+20-50,8-51
+6-52,52-84
+86-86,21-87
+26-94,26-93
+63-82,63-81
+5-18,17-91
+7-18,7-28
+10-36,10-95
+44-96,9-84
+48-51,49-62
+90-98,89-98
+31-31,32-56
+75-75,74-75
+28-80,79-92
+7-63,26-62
+4-5,5-18
+40-84,21-85
+43-51,42-44
+4-91,35-95
+51-73,51-52
+4-51,51-51
+80-80,52-80
+46-85,19-84
+9-11,10-36
+32-33,33-90
+3-92,4-92
+6-96,5-99
+77-78,66-78
+7-31,9-87
+11-70,32-69
+46-57,25-74
+4-42,41-42
+28-92,91-92
+7-23,21-22
+7-97,17-97
+12-94,6-13
+59-84,59-83
+46-46,47-78
+10-99,9-99
+1-73,13-72
+1-73,2-2
+15-91,16-84
+4-84,1-85
+3-98,2-98
+89-89,2-90
+16-96,16-96
+30-69,31-70
+16-68,73-89
+13-30,12-29
+27-97,98-99
+58-95,8-94
+18-18,17-83
+1-55,3-55
+37-43,42-89
+1-89,1-90
+51-53,23-52
+50-57,58-91
+95-96,25-96
+41-41,27-41
+26-76,59-77
+85-87,25-86
+14-62,15-63
+98-98,51-98
+81-98,50-97
+1-72,2-73
+1-4,3-64
+12-82,11-97
+6-24,24-24
+55-85,54-65
+6-68,67-69
+2-3,3-73
+4-91,4-86
+36-99,35-99
+10-79,21-78
+20-39,39-97
+7-82,6-8
+58-91,38-58
+13-63,14-39
+42-44,43-96
+84-95,82-84
+29-65,30-65
+44-58,57-58
+8-34,34-35
+11-36,11-35
+26-94,72-93
+12-26,14-88
+3-91,4-89
+6-6,5-99
+96-97,95-96
+38-51,30-45
+20-98,21-77
+16-98,16-97
+5-97,12-12
+14-25,25-92
+30-65,30-31
+52-53,35-53
+71-73,22-94
+6-96,3-99
+8-42,7-7
+28-96,29-97
+67-91,90-92
+3-95,12-95
+8-98,9-9
+27-27,26-87
+7-79,78-79
+36-90,36-89
+84-85,21-84
+69-69,68-92
+19-98,61-99
+16-98,98-99
+1-96,95-96
+16-84,16-85
+18-87,87-88
+92-97,85-95
+13-83,83-84
+20-67,3-21
+23-71,55-72
+62-97,61-61
+82-91,51-81
+24-25,25-93
+58-58,59-99
+39-93,38-93
+7-64,14-63
+35-99,36-98
+89-89,29-90
+77-78,67-78
+3-90,89-90
+26-90,26-89
+22-38,22-37
+66-66,65-94
+71-75,68-74
+47-93,7-93
+9-90,73-87
+39-39,38-82
+27-40,33-39
+66-93,67-92
+9-86,86-87
+13-95,34-94
+47-78,14-46
+2-96,2-96
+4-30,23-29
+9-88,21-89
+2-61,2-60
+15-69,15-68
+20-91,20-90
+38-77,70-76
+8-65,9-9
+96-97,14-97
+55-67,67-67
+12-78,26-83
+1-95,1-1
+56-99,64-98
+1-56,13-57
+14-84,8-96
+37-38,38-76
+4-99,5-5
+46-87,27-86
+80-80,4-80
+9-25,25-78
+33-85,34-35
+26-77,70-76
+68-98,67-98
+8-12,17-66
+2-41,2-42
+8-46,47-47
+8-92,5-8
+1-5,5-98
+6-94,7-7
+96-97,73-96
+19-51,50-51
+30-95,31-85
+16-91,17-91
+11-13,12-62
+2-99,3-99
+44-91,58-90
+28-63,1-18
+46-92,19-52
+37-54,3-55
+67-68,68-82
+2-99,98-99
+8-40,40-40
+7-58,6-58
+9-75,9-75
+4-39,39-39
+16-70,16-71
+27-82,81-82
+38-83,38-82
+4-76,75-97
+5-42,6-41
+43-82,82-82
+27-27,26-77
+14-14,13-74
+17-87,87-94
+14-78,13-62
+54-85,53-86
+1-15,1-95
+69-79,70-74
+5-86,10-85
+29-39,49-78
+41-99,41-42
+15-95,14-15
+32-78,33-78
+16-94,21-93
+5-5,4-94
+1-65,8-64
+2-99,5-98
+34-59,38-58
+36-43,7-36
+5-21,20-62
+11-92,7-7
+23-91,24-91
+6-90,5-91
+18-60,15-64
+40-87,39-41
+58-81,57-58
+3-88,4-88
+49-50,32-49
+28-34,27-90
+30-38,5-31
+8-91,7-92
+43-81,44-81
+10-97,9-99
+3-86,2-3
+80-98,4-92
+2-2,1-99
+15-41,15-42
+27-28,27-83
+9-83,4-10
+48-90,47-90
+31-67,2-32
+80-80,5-80
+10-85,10-84
+30-84,29-29
+16-45,17-45
+34-35,34-41
+28-30,29-68
+9-25,25-69
+65-66,56-66
+19-36,20-20
+53-53,53-98
+6-22,10-60
+29-29,28-93
+20-56,54-55
+8-83,8-83
+13-87,87-88
+40-81,24-66
+82-83,30-82
+68-70,1-69
+88-89,20-88
+1-99,2-99
+4-73,5-55
+71-72,18-72
+47-47,28-47
+53-69,52-69
+14-29,28-29
+53-82,83-87
+3-4,10-19
+59-93,1-92
+23-94,23-95
+27-56,26-26
+58-94,57-59
+87-87,49-88
+75-78,69-89
+18-96,19-87
+3-98,90-99
+29-45,45-58
+2-66,58-65
+15-76,14-88
+2-92,92-92
+31-79,32-79
+9-98,9-99
+7-90,6-99
+19-19,18-72
+86-86,85-98
+10-13,12-93
+2-47,48-51
+9-62,1-9
+6-95,6-94
+4-98,7-97
+80-99,99-99
+34-71,50-57
+48-67,31-66
+53-88,53-53
+5-55,5-54
+56-60,55-55
+13-45,12-45
+4-78,5-45
+52-84,84-84
+52-98,52-97
+7-8,9-92
+1-98,2-17
+42-79,9-80
+57-64,38-59
+31-37,37-72
+21-99,1-25
diff --git a/day4/uppga.c b/day4/uppga.c
@@ -0,0 +1,21 @@
+#include "common.h"
+
+static inline int iscontain(uint64_t *v)
+{
+ return ((v[0] <= v[2] && v[3] <= v[1]) ||
+ (v[2] <= v[0] && v[1] <= v[3]));
+}
+
+int main(int argc, char** argv)
+{
+ uint64_t v[4];
+ uint64_t c = 0;
+ FILE* fp = fopen("input", "r");
+
+ while(readfour(v, fp) != EOF) {
+ if(iscontain(v)) c++;
+ }
+ printf("%llu\n", c);
+
+ return 0;
+}
diff --git a/day4/uppgb.c b/day4/uppgb.c
@@ -0,0 +1,23 @@
+#include "common.h"
+
+static inline int iscontain(uint64_t *v)
+{
+ return ((v[0] <= v[2] && v[3] <= v[1]) ||
+ (v[2] <= v[0] && v[1] <= v[3]) ||
+ (v[0] <= v[2] && v[2] <= v[1]) ||
+ (v[2] <= v[0] && v[0] <= v[3]));
+}
+
+int main(int argc, char** argv)
+{
+ uint64_t v[4];
+ uint64_t c = 0;
+ FILE* fp = fopen("input", "r");
+
+ while(readfour(v, fp) != EOF) {
+ if(iscontain(v)) c++;
+ }
+ printf("%llu\n", c);
+
+ return 0;
+}
diff --git a/day5/Makefile b/day5/Makefile
@@ -0,0 +1,20 @@
+CC=clang
+UTILS=../utils/reading.o ../utils/stack_u64.o
+INCLUDES=-I../utils
+
+all: utils common.o uppga uppgb
+
+common.o: common.c common.h
+ $(CC) $(CFLAGS) -c common.c $(INCLUDES)
+
+uppga: $(UTILS) common.o uppga.c
+ $(CC) -Wall -o uppga uppga.c common.o $(UTILS) $(INCLUDES)
+
+uppgb: $(UTILS) common.o uppgb.c
+ $(CC) -Wall -o uppgb uppgb.c common.o $(UTILS) $(INCLUDES)
+
+utils:
+ make -C ../utils
+
+clean:
+ rm -rf common.o uppga uppgb
diff --git a/day5/common.c b/day5/common.c
@@ -0,0 +1,80 @@
+#include "common.h"
+
+#define swap(x,y) (x^=y^=x^=y)
+
+static inline void invertstacks(stack_u64** stacks, size_t nstacks)
+{
+ size_t i,k,l;
+ stack_u64* ss = *stacks;
+ for(i = 0; i < nstacks; i++) {
+ k = 0;
+ l = ss[i].nmemb-1;
+ while(k < l) {
+ swap(ss[i].data[k], ss[i].data[l]);
+ k++;
+ l--;
+ }
+ }
+}
+
+void makeamove(stack_u64* stacks, size_t nstacks, uint64_t* move) {
+ uint64_t f=move[1], t=move[2], n=move[0];
+ assert(f < nstacks);
+ assert(t < nstacks);
+ assert(n <= stacks[f].nmemb);
+ size_t i;
+ for(i = stacks[f].nmemb-n; i < stacks[f].nmemb; i++)
+ stack_u64_push(&stacks[t], stacks[f].data[i]);
+ stacks[f].nmemb -= n;
+}
+
+void printtops(stack_u64* stacks, size_t nstacks) {
+ size_t i;
+ for(i = 0; i < nstacks; i++) printf("%c", (char) stack_u64_getlast(&stacks[i]));
+}
+
+void parse(stack_u64* moves, stack_u64** stacks, size_t* nstacks, char** lines, size_t nlines)
+{
+ int hasstacks = 0;
+ size_t nalloc_stacks = 128;
+ size_t ninitd_stacks = 0;
+ *stacks = calloc(nalloc_stacks, sizeof(**stacks));
+ stack_u64_init(moves);
+
+ size_t r,i;
+ for(r = 0; r < nlines; r++) {
+ char* line = lines[r];
+ if(strlen(line) > 0 && line[1] == '1') {
+ hasstacks = 1;
+ *nstacks = ninitd_stacks;
+ invertstacks(stacks, *nstacks);
+ }
+
+ if(!hasstacks) {
+ for(i = 1; i < strlen(line); i += 4) {
+ size_t j = i >> 2;
+ while(j+1 > ninitd_stacks) {
+ if(ninitd_stacks >= nalloc_stacks) {
+ nalloc_stacks <<= 1;
+ *stacks = realloc(*stacks, nalloc_stacks * sizeof(**stacks));
+ }
+ stack_u64_init(&(*stacks)[ninitd_stacks]);
+ ninitd_stacks++;
+ }
+
+ if(line[i] != ' ') stack_u64_push(&(*stacks)[j], (uint64_t) line[i]);
+ }
+ } else {
+ if(strlen(line) > 0 && line[0] == 'm') {
+ char* p;
+ uint64_t rn;
+ p = sread_next_u64(&rn, line);
+ stack_u64_push(moves, rn);
+ p = sread_next_u64(&rn, p);
+ stack_u64_push(moves, rn-1);
+ p = sread_next_u64(&rn, p);
+ stack_u64_push(moves, rn-1);
+ }
+ }
+ }
+}
diff --git a/day5/common.h b/day5/common.h
@@ -0,0 +1,15 @@
+#ifndef COMMON_H_
+#define COMMON_H_
+
+#include <stdio.h>
+#include <stdint.h>
+#include <assert.h>
+#include <string.h>
+#include <stack_u64.h>
+#include <reading.h>
+
+void parse(stack_u64* moves, stack_u64** stacks, size_t* nstacks, char** lines, size_t nlines);
+void makeamove(stack_u64* stacks, size_t nstacks, uint64_t* move);
+void printtops(stack_u64* stacks, size_t nstacks);
+
+#endif
diff --git a/day5/input b/day5/input
@@ -0,0 +1,512 @@
+ [M] [S] [S]
+ [M] [N] [L] [T] [Q]
+[G] [P] [C] [F] [G] [T]
+[B] [J] [D] [P] [V] [F] [F]
+[D] [D] [G] [C] [Z] [H] [B] [G]
+[C] [G] [Q] [L] [N] [D] [M] [D] [Q]
+[P] [V] [S] [S] [B] [B] [Z] [M] [C]
+[R] [H] [N] [P] [J] [Q] [B] [C] [F]
+ 1 2 3 4 5 6 7 8 9
+
+move 1 from 7 to 4
+move 3 from 4 to 7
+move 4 from 3 to 4
+move 5 from 6 to 9
+move 1 from 8 to 1
+move 2 from 3 to 2
+move 3 from 4 to 6
+move 1 from 3 to 6
+move 9 from 7 to 1
+move 1 from 2 to 4
+move 3 from 4 to 9
+move 4 from 9 to 8
+move 6 from 8 to 2
+move 1 from 8 to 6
+move 1 from 4 to 1
+move 11 from 1 to 7
+move 1 from 4 to 7
+move 7 from 2 to 5
+move 5 from 6 to 3
+move 2 from 4 to 3
+move 2 from 5 to 9
+move 1 from 8 to 6
+move 3 from 1 to 5
+move 2 from 6 to 9
+move 1 from 4 to 8
+move 2 from 2 to 1
+move 7 from 5 to 9
+move 6 from 3 to 6
+move 1 from 2 to 5
+move 1 from 3 to 8
+move 12 from 7 to 3
+move 1 from 1 to 8
+move 2 from 1 to 9
+move 20 from 9 to 5
+move 1 from 1 to 7
+move 5 from 5 to 3
+move 1 from 8 to 7
+move 2 from 8 to 3
+move 2 from 6 to 5
+move 1 from 6 to 4
+move 18 from 3 to 2
+move 1 from 4 to 2
+move 1 from 7 to 9
+move 1 from 1 to 9
+move 1 from 6 to 1
+move 8 from 5 to 2
+move 1 from 1 to 6
+move 19 from 5 to 2
+move 5 from 2 to 6
+move 2 from 9 to 7
+move 20 from 2 to 1
+move 1 from 9 to 4
+move 8 from 6 to 2
+move 5 from 1 to 3
+move 27 from 2 to 1
+move 34 from 1 to 7
+move 1 from 2 to 6
+move 2 from 3 to 1
+move 1 from 4 to 9
+move 1 from 2 to 6
+move 2 from 1 to 7
+move 1 from 6 to 7
+move 1 from 9 to 3
+move 2 from 6 to 3
+move 1 from 6 to 4
+move 5 from 3 to 4
+move 5 from 4 to 2
+move 4 from 1 to 4
+move 4 from 1 to 4
+move 2 from 3 to 6
+move 1 from 6 to 9
+move 25 from 7 to 5
+move 1 from 6 to 4
+move 17 from 5 to 2
+move 14 from 7 to 6
+move 1 from 7 to 3
+move 1 from 9 to 3
+move 10 from 2 to 3
+move 2 from 2 to 9
+move 12 from 3 to 5
+move 18 from 5 to 8
+move 1 from 4 to 2
+move 5 from 2 to 1
+move 1 from 5 to 3
+move 3 from 2 to 1
+move 1 from 2 to 7
+move 2 from 2 to 6
+move 9 from 6 to 7
+move 16 from 8 to 2
+move 6 from 7 to 3
+move 2 from 8 to 9
+move 1 from 1 to 8
+move 16 from 2 to 6
+move 1 from 8 to 3
+move 2 from 1 to 2
+move 1 from 9 to 3
+move 7 from 4 to 1
+move 7 from 3 to 7
+move 9 from 7 to 8
+move 1 from 5 to 6
+move 2 from 9 to 7
+move 1 from 9 to 5
+move 11 from 6 to 8
+move 1 from 3 to 1
+move 1 from 4 to 2
+move 2 from 8 to 5
+move 3 from 5 to 8
+move 2 from 1 to 9
+move 5 from 1 to 4
+move 3 from 4 to 1
+move 1 from 3 to 2
+move 3 from 2 to 1
+move 1 from 9 to 1
+move 1 from 2 to 5
+move 2 from 4 to 7
+move 20 from 8 to 5
+move 1 from 9 to 7
+move 11 from 6 to 1
+move 17 from 1 to 5
+move 1 from 8 to 2
+move 7 from 5 to 8
+move 1 from 4 to 5
+move 2 from 1 to 2
+move 2 from 8 to 4
+move 4 from 7 to 6
+move 2 from 6 to 8
+move 2 from 1 to 2
+move 1 from 1 to 4
+move 4 from 8 to 9
+move 2 from 1 to 9
+move 3 from 8 to 1
+move 25 from 5 to 2
+move 23 from 2 to 1
+move 1 from 7 to 1
+move 6 from 9 to 8
+move 6 from 8 to 3
+move 3 from 6 to 2
+move 10 from 1 to 2
+move 1 from 6 to 3
+move 2 from 3 to 6
+move 2 from 3 to 2
+move 2 from 6 to 8
+move 1 from 4 to 6
+move 14 from 1 to 9
+move 2 from 3 to 4
+move 14 from 2 to 4
+move 1 from 6 to 9
+move 17 from 4 to 3
+move 1 from 8 to 6
+move 2 from 7 to 2
+move 1 from 4 to 2
+move 1 from 5 to 9
+move 9 from 2 to 4
+move 17 from 3 to 7
+move 3 from 4 to 2
+move 1 from 8 to 3
+move 4 from 5 to 7
+move 1 from 3 to 6
+move 1 from 4 to 5
+move 14 from 7 to 9
+move 2 from 1 to 9
+move 3 from 2 to 1
+move 1 from 2 to 5
+move 1 from 3 to 7
+move 4 from 1 to 2
+move 2 from 6 to 7
+move 3 from 9 to 8
+move 4 from 2 to 4
+move 17 from 9 to 7
+move 1 from 2 to 8
+move 8 from 9 to 6
+move 1 from 8 to 2
+move 19 from 7 to 9
+move 9 from 4 to 2
+move 5 from 7 to 3
+move 3 from 5 to 9
+move 6 from 2 to 5
+move 1 from 9 to 4
+move 3 from 2 to 9
+move 25 from 9 to 5
+move 1 from 3 to 6
+move 2 from 5 to 8
+move 6 from 6 to 7
+move 1 from 3 to 4
+move 2 from 3 to 4
+move 1 from 8 to 2
+move 2 from 2 to 9
+move 2 from 8 to 3
+move 5 from 7 to 6
+move 3 from 7 to 9
+move 7 from 5 to 8
+move 2 from 3 to 5
+move 1 from 3 to 5
+move 1 from 6 to 2
+move 6 from 9 to 5
+move 1 from 9 to 2
+move 1 from 6 to 9
+move 2 from 5 to 6
+move 2 from 9 to 8
+move 11 from 8 to 1
+move 2 from 5 to 9
+move 3 from 6 to 5
+move 1 from 4 to 7
+move 5 from 5 to 7
+move 1 from 4 to 8
+move 7 from 7 to 2
+move 12 from 5 to 2
+move 10 from 1 to 8
+move 1 from 9 to 6
+move 3 from 8 to 1
+move 1 from 1 to 6
+move 10 from 2 to 3
+move 8 from 8 to 7
+move 1 from 9 to 8
+move 2 from 3 to 5
+move 14 from 5 to 8
+move 1 from 3 to 2
+move 3 from 8 to 1
+move 3 from 8 to 4
+move 3 from 2 to 4
+move 5 from 6 to 4
+move 8 from 7 to 9
+move 6 from 8 to 7
+move 1 from 5 to 7
+move 6 from 2 to 9
+move 4 from 4 to 6
+move 4 from 4 to 9
+move 3 from 9 to 3
+move 1 from 8 to 6
+move 1 from 5 to 6
+move 2 from 7 to 2
+move 1 from 3 to 4
+move 3 from 4 to 1
+move 3 from 4 to 3
+move 5 from 6 to 4
+move 4 from 3 to 8
+move 1 from 6 to 4
+move 8 from 3 to 2
+move 2 from 8 to 5
+move 11 from 9 to 7
+move 9 from 1 to 9
+move 2 from 7 to 3
+move 1 from 6 to 8
+move 1 from 6 to 5
+move 5 from 9 to 8
+move 3 from 9 to 7
+move 2 from 9 to 1
+move 2 from 3 to 7
+move 12 from 7 to 1
+move 2 from 8 to 9
+move 5 from 4 to 5
+move 4 from 9 to 4
+move 1 from 1 to 3
+move 7 from 1 to 3
+move 7 from 5 to 6
+move 1 from 9 to 1
+move 1 from 5 to 1
+move 5 from 7 to 8
+move 4 from 6 to 7
+move 5 from 1 to 8
+move 1 from 4 to 3
+move 12 from 8 to 7
+move 2 from 2 to 4
+move 2 from 8 to 9
+move 3 from 8 to 2
+move 2 from 6 to 7
+move 4 from 7 to 8
+move 1 from 6 to 8
+move 4 from 3 to 2
+move 15 from 7 to 8
+move 1 from 7 to 6
+move 3 from 3 to 5
+move 2 from 3 to 4
+move 5 from 2 to 5
+move 3 from 1 to 5
+move 4 from 5 to 6
+move 4 from 5 to 9
+move 1 from 5 to 7
+move 4 from 9 to 4
+move 2 from 2 to 9
+move 2 from 5 to 2
+move 2 from 2 to 1
+move 3 from 4 to 9
+move 2 from 9 to 4
+move 2 from 8 to 5
+move 2 from 5 to 2
+move 8 from 2 to 4
+move 2 from 1 to 3
+move 2 from 3 to 5
+move 3 from 6 to 9
+move 2 from 6 to 1
+move 2 from 1 to 4
+move 1 from 2 to 4
+move 1 from 5 to 7
+move 2 from 2 to 7
+move 18 from 4 to 2
+move 1 from 5 to 9
+move 2 from 7 to 9
+move 18 from 8 to 4
+move 1 from 7 to 8
+move 22 from 4 to 8
+move 6 from 2 to 6
+move 3 from 6 to 8
+move 3 from 6 to 4
+move 3 from 4 to 7
+move 3 from 7 to 1
+move 14 from 2 to 3
+move 10 from 3 to 2
+move 27 from 8 to 1
+move 1 from 7 to 6
+move 1 from 3 to 7
+move 2 from 2 to 8
+move 2 from 9 to 8
+move 18 from 1 to 4
+move 6 from 1 to 5
+move 10 from 4 to 7
+move 1 from 3 to 7
+move 4 from 7 to 2
+move 3 from 9 to 7
+move 1 from 6 to 5
+move 1 from 2 to 7
+move 2 from 5 to 6
+move 2 from 6 to 5
+move 3 from 5 to 1
+move 6 from 1 to 3
+move 4 from 5 to 9
+move 11 from 2 to 9
+move 2 from 1 to 6
+move 3 from 4 to 6
+move 5 from 7 to 3
+move 2 from 6 to 1
+move 2 from 1 to 5
+move 1 from 8 to 2
+move 1 from 1 to 8
+move 1 from 6 to 4
+move 2 from 4 to 5
+move 4 from 5 to 9
+move 11 from 3 to 6
+move 1 from 3 to 6
+move 8 from 6 to 5
+move 1 from 3 to 5
+move 4 from 4 to 8
+move 21 from 9 to 6
+move 2 from 9 to 5
+move 1 from 9 to 3
+move 1 from 2 to 6
+move 7 from 8 to 6
+move 12 from 6 to 5
+move 1 from 8 to 2
+move 10 from 6 to 7
+move 15 from 7 to 2
+move 2 from 7 to 3
+move 13 from 6 to 8
+move 9 from 5 to 1
+move 12 from 5 to 3
+move 1 from 2 to 3
+move 1 from 9 to 7
+move 9 from 3 to 4
+move 3 from 4 to 6
+move 1 from 7 to 6
+move 6 from 4 to 1
+move 2 from 5 to 2
+move 6 from 1 to 8
+move 9 from 8 to 6
+move 7 from 3 to 2
+move 1 from 2 to 9
+move 9 from 6 to 1
+move 13 from 1 to 7
+move 4 from 8 to 5
+move 2 from 7 to 1
+move 3 from 6 to 4
+move 3 from 5 to 8
+move 3 from 2 to 6
+move 1 from 5 to 3
+move 1 from 3 to 4
+move 1 from 9 to 8
+move 3 from 8 to 7
+move 12 from 2 to 9
+move 10 from 7 to 4
+move 5 from 8 to 4
+move 1 from 8 to 5
+move 11 from 4 to 7
+move 8 from 9 to 7
+move 1 from 6 to 2
+move 8 from 2 to 6
+move 1 from 5 to 8
+move 4 from 1 to 5
+move 4 from 9 to 6
+move 3 from 1 to 3
+move 2 from 8 to 4
+move 1 from 7 to 6
+move 1 from 2 to 7
+move 2 from 3 to 7
+move 4 from 4 to 9
+move 11 from 6 to 9
+move 10 from 7 to 8
+move 1 from 3 to 4
+move 1 from 6 to 4
+move 4 from 5 to 7
+move 6 from 7 to 4
+move 1 from 8 to 7
+move 4 from 6 to 7
+move 12 from 4 to 8
+move 12 from 8 to 1
+move 1 from 8 to 2
+move 10 from 1 to 7
+move 2 from 4 to 1
+move 8 from 8 to 3
+move 4 from 1 to 6
+move 8 from 7 to 6
+move 2 from 6 to 5
+move 2 from 5 to 2
+move 13 from 9 to 3
+move 3 from 2 to 5
+move 8 from 3 to 4
+move 7 from 6 to 7
+move 1 from 9 to 2
+move 1 from 9 to 1
+move 2 from 6 to 4
+move 3 from 4 to 8
+move 1 from 1 to 7
+move 4 from 4 to 6
+move 3 from 8 to 7
+move 1 from 2 to 9
+move 1 from 5 to 2
+move 1 from 2 to 5
+move 2 from 4 to 5
+move 1 from 7 to 2
+move 13 from 3 to 4
+move 7 from 4 to 3
+move 4 from 5 to 9
+move 1 from 4 to 7
+move 5 from 6 to 3
+move 3 from 9 to 7
+move 10 from 7 to 8
+move 3 from 4 to 8
+move 1 from 5 to 4
+move 2 from 3 to 1
+move 3 from 7 to 4
+move 4 from 8 to 6
+move 2 from 9 to 3
+move 2 from 4 to 5
+move 4 from 4 to 3
+move 8 from 8 to 3
+move 3 from 6 to 8
+move 1 from 2 to 6
+move 5 from 7 to 9
+move 1 from 4 to 3
+move 3 from 7 to 5
+move 3 from 8 to 4
+move 7 from 7 to 5
+move 3 from 7 to 8
+move 1 from 9 to 8
+move 3 from 4 to 1
+move 1 from 5 to 8
+move 3 from 7 to 1
+move 6 from 8 to 3
+move 3 from 9 to 5
+move 2 from 6 to 5
+move 2 from 1 to 6
+move 16 from 3 to 8
+move 4 from 5 to 8
+move 4 from 3 to 8
+move 1 from 9 to 5
+move 1 from 6 to 5
+move 3 from 3 to 7
+move 6 from 1 to 6
+move 1 from 5 to 4
+move 3 from 5 to 2
+move 2 from 7 to 4
+move 1 from 2 to 8
+move 6 from 8 to 1
+move 2 from 4 to 5
+move 2 from 2 to 3
+move 7 from 8 to 7
+move 1 from 4 to 6
+move 3 from 6 to 4
+move 3 from 4 to 9
+move 3 from 6 to 3
+move 11 from 8 to 6
+move 12 from 5 to 4
+move 5 from 6 to 1
+move 9 from 3 to 2
+move 7 from 6 to 1
+move 7 from 7 to 8
+move 5 from 8 to 3
+move 2 from 3 to 6
+move 2 from 8 to 1
+move 1 from 7 to 2
+move 7 from 3 to 8
+move 1 from 9 to 1
+move 14 from 1 to 3
+move 9 from 2 to 8
+move 11 from 3 to 4
+move 22 from 4 to 1
+move 2 from 3 to 1
+move 16 from 8 to 4
+move 1 from 9 to 2
+move 3 from 6 to 9
+move 3 from 9 to 5
+move 1 from 2 to 6
+move 1 from 5 to 7
diff --git a/day5/uppga.c b/day5/uppga.c
@@ -0,0 +1,28 @@
+#include "common.h"
+
+int main(int argc, char** argv)
+{
+ char** lines;
+ size_t nlines = readlines(&lines, "input");
+
+ stack_u64* stacks;
+ size_t nstacks;
+ stack_u64 moves;
+
+ parse(&moves, &stacks, &nstacks, lines, nlines);
+
+ size_t i,j;
+ for(i = 0; i < moves.nmemb; i+=3) {
+ uint64_t tmp = moves.data[i];
+ moves.data[i] = 1;
+ for(j = 0; j < tmp; j++)
+ makeamove(stacks, nstacks, &(moves.data[i]));
+ }
+ printtops(stacks, nstacks);
+ printf("\n");
+
+ for(i = 0; i < nstacks; i++) {
+ stack_u64_clear(&stacks[i]);
+ }
+ stack_u64_clear(&moves);
+}
diff --git a/day5/uppgb.c b/day5/uppgb.c
@@ -0,0 +1,26 @@
+#include "common.h"
+
+int main(int argc, char** argv)
+{
+ char** lines;
+ size_t nlines = readlines(&lines, "input");
+
+ stack_u64* stacks;
+ size_t nstacks;
+ stack_u64 moves;
+
+ parse(&moves, &stacks, &nstacks, lines, nlines);
+
+ size_t i;
+
+ for(i = 0; i < moves.nmemb; i+=3) {
+ makeamove(stacks, nstacks, &(moves.data[i]));
+ }
+ printtops(stacks, nstacks);
+ printf("\n");
+
+ for(i = 0; i < nstacks; i++) {
+ stack_u64_clear(&stacks[i]);
+ }
+ stack_u64_clear(&moves);
+}
diff --git a/day6/Makefile b/day6/Makefile
@@ -0,0 +1,20 @@
+CC=clang
+UTILS= ../utils/reading.o #../utils/stack_u64.o
+INCLUDES=-I../utils
+
+all: utils common.o uppga uppgb
+
+common.o: common.c common.h
+ $(CC) $(CFLAGS) -c common.c $(INCLUDES)
+
+uppga: $(UTILS) common.o uppga.c
+ $(CC) -Wall -o uppga uppga.c common.o $(UTILS) $(INCLUDES)
+
+uppgb: $(UTILS) common.o uppgb.c
+ $(CC) -Wall -o uppgb uppgb.c common.o $(UTILS) $(INCLUDES)
+
+utils:
+ make -C ../utils
+
+clean:
+ rm -rf common.o uppga uppgb
diff --git a/day6/common.c b/day6/common.c
@@ -0,0 +1,12 @@
+#include "common.h"
+
+int pairwise_diff(char* s, size_t n)
+{
+ int i,j;
+
+ for(i = n-2; i >= 0; i--)
+ for(j = i+1; j < n; j++)
+ if(s[i] == s[j]) return i+1;
+
+ return 0;
+}
diff --git a/day6/common.h b/day6/common.h
@@ -0,0 +1,11 @@
+#ifndef COMMON_H_
+#define COMMON_H_
+
+#include <stdio.h>
+#include <stdint.h>
+#include <assert.h>
+#include <reading.h>
+
+int pairwise_diff(char* s, size_t n);
+
+#endif
diff --git a/day6/input b/day6/input
@@ -0,0 +1 @@
+tnmmpfmfzmmnsmsjmjjbvvhnhzzfmmgpmgpgbgnnwffjhffzqqmzzbnbssrqqrnnhsnngsszsqzszhzfhzfzwzfzrrmhmghgwhhjjqwqttwhttjllrtrtzzcfzfgzznfznfzfnnbddvmvzmmfsmfsmfffhlfldlqqrnrznnhmmgqqzhhmjhmhppqbpbbngnlldvvdqvvrtrdrtrnttnppfllrbbrprpnpdplpmllhwwddqpdprddzzfccqpcqpcpcbbdhdjdjwjcwcctdcttzgzmmscmsmdmttwhwzhhnjhnhlhvhlvlglpgpmmjmgmrgrddmwddjfftfwflfslffqtfqttpftppflfmmhvhvcvbvhbhggpbgbppvdpvpvfppbwwsnnhphllbdbnbvbmvvzffvsffdldmlmtmccnlnbnjbnjnhhbfhhgzzlwlfflzffdccggdcgcjjhffjfgfgcczjccvwcvvqgvvqvllqzqmqllhjjqnqggttsdddjgdjgjzzrgrfrbrssrgrgdgrgbbssmdsdfddsndnsdnsdnnmqqsspqqmrqqpmmsjmmszzqvqrvrzznnjdndtntfnttgtctqtwwnwswrrthrttsdttlhlvvdzzgqgttnppjpljplpgpvgvqqvppzmmqggtjgtgstslltjltjjgcjcmjmsshvvtppgmmlslqqshqshsllbggfpgffdsdgssncchctcwwtllgqlqblqlqvvmsvmmwnnzppqllsttgmttftvfvjjrzzswzzjvzjzljjchcshcscbbrdbrbcrrnvvtctntvtvbvjvqjqggsrspsprrbgghdghhmwwldldzdttrvrnrfftqtftrrdsszlzvvbtbffftzzrzqrrhjhghhwbhhsjsfsttdjdjnjhjmjpmplplrrdjdcdjdbjblllbqlqdlqlpqptppdhhqmqfqhqhchwwqjqfjqfqhqshsmswsbbvssdspdpsdssstntltrrgnnmttgmmsjjrlrnlrnrnwrwfwlfltlzllcjcmjcjpjhphcpcwppmvmjjzbzvbbfnfcflfddntddbmmmhnnsrnrrvdvnvcvwvcwvwrrqwqccqmmswmmjrjmmwjmjfjhwrtbjzdvlgrjmvzfmhcqsncvlhzzncjlbvcwrdwjmqjcnptqslvfzpsvltgzsvjdsjrppdrmqrbqwhddfhnftfblspsrhtdtjwdnhbcbtlwlvccsfscvczzrrqmwbwbdmwgzqntvflppqvppwrhnvtlsbzqglhsfdgssqzdtjdpwrrhbnbtwhhnmnlwfwlqffjjrndbpwwsvdrhddbjnnqzmtpvvtwbcpndjzlhcfrrdvmljswjzvmfqcdsgqwclqshwrmblszdvsnrpdgnllmlchzdjlrrpndmmgddjqgjqrhwfbwddqdfbvptrmzhtsqfsfswpnvmtswqprjhbzvntgrlzthhnqbtpplqpvcfnpgdtbhqbhflltbbtmmhcwztslmpznttmssclhmnbsbrwlblrbsdfmnpqbwwmsncvzmpqwhzjgcgdrzvglgdtswmstdhrprdjfmqtjlmplbjtzcgnrwpdvpfjjfwjfnnpmdtwtqsgfndngsbmcwjtglqwtfrclbczfcmjtgcwszhzrbcphrhwmhcwghjznzthnwpljjltdlvqtffsrbmwcsvrdmqqggbznnlzbbqtgspqvnjpbdhtzmgttrcwwszwpgdrcnfqtgrgqdrctlzwtdwqppbhnwgldnqltznnfpbfqtgmmwpcqnndbgmrrtgtvnmlfcwsldchjnnqfrhpzwtclrzftsqllgvpqbgmfjdhqjttwcvbpvfqsvhbhhtwnqnbgndbtzhcvgglbhghbzrbrmdllmgfgttqmhtdnwrpwllhnghrjctrbzrcpnjnctvmrlpjhftnfbczrjrnnbqplplcrbngbhvmmvcffmgvbhjzbhcmtwmwgmjmwjvvlqfldswpntjnsjvmdlbzqqlgbwspwvmnwtwjbczmwplrhmjgsppnmtwmvsfwnsgddgwqcvpftcpzrhpldnwmcjgtjmljjbcmjcqdbwczndnjnjgrmtjrqnnjndzqdqpcgdqptdbrqftnwrgqmrzrvsfmmmbpltlncvtgrjfjmvtgwqphczwjhdrdwtfvgztbhrndvpcbgfjfvmrrljwrvcrtdmtjndfnwgcnfrzgsnjpztbwwsbvqfnpjctgrhsflhnzbbsfqbnmtnvrmjzsbjfndvttpvpfjhqntflgbfnzcclcwmhbsgqfjdcgsvrhtstspfzgvgglgddqmclsmzgzgtncdsfmwdvtcsgwvbzjvclwppqdjgfcrcbzcwbdhrnssjbmnmfmwthdrnmlfhqlddwqrdhsdvdcsmcgjsgcmpnhlbnqftpdjswtmpbznlcrhtswgnmwjcdfmljdngzfsmlzjjnzmfzshmztdbdmcqwmlvcrzgpmbjqcghclwvdbrhgvwqchnndftnrtptmctdlhmfjvpzrpccddfpcdwmzqfhnsqzrvwblzfhcjdcjfctczwqrcbjnrpdcbbnsgnlvqqmnsfgsqschjlbzhhsrbvdbfrhvsgrlzwncgwpdbvmblgzbwbcbgqfwmdmgcrbbjfcvmqgztqpptdhwmvmsdqwplpgcjzgqzdrftzhqbltvhrmlrfffcgfpqzwrrbbtlsjgmtbjvtnmhwdpjptjwfwgjgvbfqwmflrrqzlzdcmtlnptdrpcpdnswcfscnndnrfbgwvvncdjgsdpbwptdtvrqlmrhmvvcwblhhzbjdpsbszhrftfbcgwhwrgglnjzqdhcqnvlhgqjhnddvrslhntssptsbhmqwwqqnbvfmcbgpvgjbrttnvlljdbtfplgmbwtcbcdtqdpqqdvhbmpmtszwpzblcfrtznhhtcljtdlhjdbnlhvwgjsmgvrslrfwnmzwlstpgltvrgnpdqztvfnvdhdtwwqdfsmtpbpdclsbnwcgjzchjcsjmvhbjshmjjlpgdzcgbmmchwmcsddsvhsnpqtcpnhqnbvwgwqhtjbqncgwwftnrzsbsjtvqmjzqvvncmncwflcfpcjqgdtbsmjzzsdjfvhnqbgjhmfgjghwscthbfmbndltbqzwpqtmrswvprpmgwqnqpfnmffrpdlpfqmhrthppzvzwbrtjvwvjndsqdlqtbpqwfcttggnjmcqqnmjwfhfjgcvlnmtlgbdvmctzlwbfgnflwtsflgnfbnfbhhdgjctzvvmrhdsmvmmtnqwtszmqcpsbrqrgjfrzctcbzmtdlhwjtfdqbtthdnqcrpwrhcrvjstbhpltvgmvpmvfjstgzjsgzprzcqzqztvvdcnrrqwrhddcrhhncdrlwzwqlnbbzcfmqtnwgfdscmrbwnbldlfrqchzdnlnmwncgrzdclnvcvplgwjsbzmbnnsdrsfhrlssvncnwmcrjdjbjpdtrrvlnbjvspfqbwdpcnnpjzfnmbhcdhlmdgbpvbzmfltzstnznfctcdzhbfsvnfbsjqzmwfllhtrsfghlrpjgrgzgchlwrdmqzbrncsvnwhfqmwjbnvjctzphcsftqsbmwntgvjqhhvwndvmfmjhhhmfdvrlhpvzmmhrbhbddqbdmgqqsvddsswmzqcjmvhztfqpchzpwhdshzjlmbmnsgzqhbnmrshwvtmgmgndtddpfwsjrrjdhncdhtlczdvlbvqplttnzrblthlcffdtfsdtpwzdgbldvnsttvpzmbgnqddrszftcpwrgmfzhjjvghpntmzcttcsnrjnfpqzqqqljhzlrpgwngllqjwnwfcsphqplgbzmfqfgbfsqpsrntszqbcqnhctsnbfshmlbwfflrwwsjwqwfqlgnftdwmctmclwjhjhbsspqldlshbmpbgrftpnbpsqldhrrbdqwfwvfhclrlfdjfmzgmptdjdcsplcspznfjrfhtsjndwpslrdgnllllwqjgznrhswfssdlvdpmwwgmstqbhfmdhtzvzzvhwzbrrvvsl
diff --git a/day6/uppga.c b/day6/uppga.c
@@ -0,0 +1,20 @@
+#include "common.h"
+
+int main(int argc, char** argv)
+{
+ char** lines;
+ size_t nlines = readlines(&lines, "input");
+
+ assert(nlines == 1);
+
+ char* s = lines[0];
+ size_t len = strlen(s);
+
+ size_t i,step=0;
+ for(i = 0; i < len; i+=step, s+= step) {
+ if((step = pairwise_diff(s, 4)) == 0) {
+ printf("%zu\n", i+4);
+ break;
+ }
+ }
+}
diff --git a/day6/uppgb.c b/day6/uppgb.c
@@ -0,0 +1,20 @@
+#include "common.h"
+
+int main(int argc, char** argv)
+{
+ char** lines;
+ size_t nlines = readlines(&lines, "input");
+
+ assert(nlines == 1);
+
+ char* s = lines[0];
+ size_t len = strlen(s);
+
+ size_t i,step=0;
+ for(i = 0; i < len; i+=step, s += step) {
+ if((step = pairwise_diff(s, 14)) == 0) {
+ printf("%zu\n", i+14);
+ break;
+ }
+ }
+}
diff --git a/day7/Makefile b/day7/Makefile
@@ -0,0 +1,20 @@
+CC=clang
+UTILS=../utils/reading.o
+INCLUDES=-I../utils
+
+all: utils common.o uppga uppgb
+
+common.o: common.c common.h
+ $(CC) $(CFLAGS) -c common.c $(INCLUDES)
+
+uppga: $(UTILS) common.o uppga.c
+ $(CC) -Wall -o uppga uppga.c common.o $(UTILS) $(INCLUDES)
+
+uppgb: $(UTILS) common.o uppgb.c
+ $(CC) -Wall -o uppgb uppgb.c common.o $(UTILS) $(INCLUDES)
+
+utils:
+ make -C ../utils
+
+clean:
+ rm -rf common.o uppga uppgb
diff --git a/day7/common.c b/day7/common.c
@@ -0,0 +1,122 @@
+#include "common.h"
+
+void tn_init(tn* t, char* name, const size_t size) {
+ t->name = name;
+ t->size = size;
+
+ t->children_alloc = TN_DEFAULT_ALLOC;
+ t->children_n = 0;
+ t->children = malloc(t->children_alloc * sizeof(*(t->children)));
+
+ t->parent = NULL;
+}
+
+void tn_set_parent(tn* t, tn* pere)
+{
+ t->parent = pere;
+}
+
+void tn_add_child(tn* t, tn* fils)
+{
+ if(t->children_n >= t->children_alloc) {
+ t->children_alloc <<= 1;
+ t->children = realloc(t->children,
+ t->children_alloc * sizeof(*(t->children)));
+ }
+
+ t->children[t->children_n] = fils;
+ t->children_n++;
+ fils->parent = t;
+}
+
+void print_tree(tn* t, size_t level)
+{
+ size_t i;
+ for(i = 0; i < level; i++) printf(" ");
+ printf("%s (%zu)\n", t->name, t->size);
+ for(i = 0; i < t->children_n; i++)
+ print_tree(t->children[i], level+2);
+}
+
+void tn_cleartree(tn* t)
+{
+ size_t i;
+ for(i = 0; i < t->children_n; i++) tn_cleartree(t->children[i]);
+ free(t->children);
+ free(t);
+}
+
+tn* find_root(tn* t)
+{
+ if(t->parent == NULL) return t;
+ return find_root(t->parent);
+}
+
+tn* find_child(tn* t, char* s)
+{
+ size_t i;
+ for(i = 0; i < t->children_n; i++) {
+ if(strcmp(t->children[i]->name, s) == 0)
+ return t->children[i];
+ }
+ return NULL;
+}
+
+tn* parse_input(char** lines, size_t nlines)
+{
+ size_t i;
+
+ size_t ralloc = 1;
+ size_t rn = 0;
+ tn** r = calloc(ralloc, sizeof(*r));
+ tn* cp = NULL;
+
+ for(i = 0; i < nlines; i++) {
+ char* line = lines[i];
+ if(strncmp(line, "$ cd /", 6) == 0) {
+ if(rn == 0) {
+ ralloc = 1;
+ r[0] = malloc(sizeof(**r));
+ tn_init(r[0], "", 0);
+ rn = 1;
+ }
+ cp = r[0];
+ } else if(strncmp(line, "$ cd ..", 7) == 0) {
+ assert(cp->parent != NULL);
+ cp = cp->parent;
+ } else if(strncmp(line, "$ cd ", 5) == 0) {
+ char* ndir = &line[5];
+ tn* childp;
+ if((childp = find_child(cp, ndir)) == NULL) {
+ if(rn >= ralloc) {
+ ralloc <<= 1;
+ r = realloc(r, ralloc * sizeof(*r));
+ }
+
+ r[rn] = malloc(sizeof(**r));
+ tn_init(r[rn], ndir, 0);
+ childp = r[rn];
+ rn++;
+ tn_add_child(cp, childp);
+ }
+ cp = childp;
+ } else if(line[0] != '$' && line[0] != 'd') {
+ uint64_t tmp;
+ sread_next_u64(&tmp, line);
+ cp->size += tmp;
+ }
+ }
+
+ tn* root = r[0];
+ free(r);
+ return root;
+}
+
+void sum_sizes(tn* t)
+{
+ size_t i;
+ for(i = 0; i < t->children_n; i++) {
+ sum_sizes(t->children[i]);
+ t->size += t->children[i]->size;
+ }
+}
diff --git a/day7/common.h b/day7/common.h
@@ -0,0 +1,28 @@
+#ifndef COMMON_H_
+#define COMMON_H_
+
+#include <stdio.h>
+#include <stdint.h>
+#include <assert.h>
+#include <reading.h>
+
+#define TN_DEFAULT_ALLOC 1
+#define NO_SIZE (SIZE_MAX)
+
+typedef struct _struct_tn {
+ char* name;
+ size_t size;
+
+ size_t children_alloc;
+ size_t children_n;
+ struct _struct_tn** children;
+
+ struct _struct_tn* parent;
+} tn;
+
+tn* parse_input(char** lines, size_t nlines);
+void sum_sizes(tn* t);
+void print_tree(tn* t, size_t level);
+void tn_cleartree(tn* t);
+
+#endif
diff --git a/day7/einput b/day7/einput
@@ -0,0 +1,23 @@
+$ cd /
+$ ls
+dir a
+14848514 b.txt
+8504156 c.dat
+dir d
+$ cd a
+$ ls
+dir e
+29116 f
+2557 g
+62596 h.lst
+$ cd e
+$ ls
+584 i
+$ cd ..
+$ cd ..
+$ cd d
+$ ls
+4060174 j
+8033020 d.log
+5626152 d.ext
+7214296 k
diff --git a/day7/input b/day7/input
@@ -0,0 +1,950 @@
+$ cd /
+$ ls
+dir cvt
+4967 hcqbmwc.gts
+5512 hsbhwb.clj
+dir hvfvt
+dir phwgv
+277125 pwgswq.fld
+42131 qdzr.btl
+dir svw
+144372 vmbnlzgb.wbd
+dir zft
+$ cd cvt
+$ ls
+dir bbgsthsd
+146042 bcqrmp.czf
+dir chhdjtlw
+dir cpcfcc
+dir dch
+dir djb
+dir djfww
+dir drdf
+dir fgbqtjlj
+dir hjsmmj
+243293 hvfvt.qtb
+245795 lrpb
+dir msptbrl
+181756 qlqqmndd.zcb
+18658 rtfzt.tjp
+dir slpc
+$ cd bbgsthsd
+$ ls
+236957 djfww.fcb
+112286 hcqbmwc.gts
+106102 qggjrzts
+$ cd ..
+$ cd chhdjtlw
+$ ls
+226927 cpcfcc
+309815 djfww
+117933 hcqbmwc.gts
+dir mbdrgfzs
+dir pbmcnpzf
+131558 pwgswq.fld
+298691 qlqqmndd.zcb
+$ cd mbdrgfzs
+$ ls
+164331 hvfvt.dvq
+$ cd ..
+$ cd pbmcnpzf
+$ ls
+102120 bjgg.cqd
+$ cd ..
+$ cd ..
+$ cd cpcfcc
+$ ls
+15756 ddc
+dir dqc
+dir glm
+dir jbszm
+200345 pwgswq.fld
+145508 qlqqmndd.zcb
+dir vcptbw
+dir zrtm
+$ cd dqc
+$ ls
+dir cpcfcc
+92063 mzp
+dir qmhnvmh
+dir snqqcjlw
+8423 zdjwr.blc
+$ cd cpcfcc
+$ ls
+dir hvfvt
+$ cd hvfvt
+$ ls
+289372 pwgswq.fld
+307397 qlqqmndd.zcb
+$ cd ..
+$ cd ..
+$ cd qmhnvmh
+$ ls
+274778 jczjwdl.smd
+194322 ngrrfm
+$ cd ..
+$ cd snqqcjlw
+$ ls
+182851 nprvrgd.tbb
+$ cd ..
+$ cd ..
+$ cd glm
+$ ls
+188702 hpq.hgm
+$ cd ..
+$ cd jbszm
+$ ls
+187645 pwgswq.fld
+$ cd ..
+$ cd vcptbw
+$ ls
+dir mgqd
+$ cd mgqd
+$ ls
+157695 rhldvntj.jzm
+268696 rjnngctw
+$ cd ..
+$ cd ..
+$ cd zrtm
+$ ls
+218820 bcqrmp.czf
+172319 czpsl.dnf
+180114 hcqbmwc.gts
+165216 hvfvt.nnw
+dir zft
+$ cd zft
+$ ls
+161245 dtqjg.czv
+249888 hpq.hgm
+192037 zft
+$ cd ..
+$ cd ..
+$ cd ..
+$ cd dch
+$ ls
+dir djfww
+dir fzqgwwnf
+dir hqvmq
+dir mmcrzqc
+42136 qlqqmndd.zcb
+dir vdtlh
+dir wfltm
+271200 zrtm
+$ cd djfww
+$ ls
+37427 dct
+204401 hcqbmwc.gts
+283140 jmq
+dir lbrhbc
+154148 pncb.bmp
+53366 vzt.cnn
+$ cd lbrhbc
+$ ls
+dir djfww
+153648 djfww.pps
+308911 mvtjzp.btg
+219150 ncmc
+253604 wqft.ggb
+293759 zft
+$ cd djfww
+$ ls
+24794 hcqbmwc.gts
+$ cd ..
+$ cd ..
+$ cd ..
+$ cd fzqgwwnf
+$ ls
+233720 scdd.pwr
+$ cd ..
+$ cd hqvmq
+$ ls
+dir cdld
+dir cpcfcc
+dir djfww
+85564 hpq.hgm
+dir qnc
+81509 wtnl.crs
+$ cd cdld
+$ ls
+293421 llpltsgn.tqb
+$ cd ..
+$ cd cpcfcc
+$ ls
+230813 cglljgv
+178203 qlqqmndd.zcb
+186410 zrtm.tbt
+$ cd ..
+$ cd djfww
+$ ls
+201830 zrtm
+$ cd ..
+$ cd qnc
+$ ls
+305356 bdf.jrh
+dir zrtm
+$ cd zrtm
+$ ls
+dir bdhdrr
+$ cd bdhdrr
+$ ls
+dir nffdrnb
+$ cd nffdrnb
+$ ls
+301601 nbrjz
+$ cd ..
+$ cd ..
+$ cd ..
+$ cd ..
+$ cd ..
+$ cd mmcrzqc
+$ ls
+dir cpcfcc
+264271 hpq.hgm
+208744 tzsjrf.zdc
+274096 zft
+$ cd cpcfcc
+$ ls
+226054 cpcfcc
+$ cd ..
+$ cd ..
+$ cd vdtlh
+$ ls
+84229 bzlg.crn
+58668 cpcfcc.zqw
+141409 hpq.hgm
+dir mdgst
+37090 pstsh.qwv
+40357 qlqqmndd.zcb
+dir smr
+dir sqbgcsgh
+dir trp
+$ cd mdgst
+$ ls
+151033 fsmvbpsl.nqr
+$ cd ..
+$ cd smr
+$ ls
+140764 cpcfcc.dpg
+$ cd ..
+$ cd sqbgcsgh
+$ ls
+dir djfww
+263783 dvm
+105219 hpq.hgm
+29647 hwcgv.gvg
+162537 lwjhgh.wmt
+235511 nlw
+dir zwddrdfz
+$ cd djfww
+$ ls
+260084 vcgpvpd
+$ cd ..
+$ cd zwddrdfz
+$ ls
+225632 bhrzzw
+269756 cqq.vrz
+$ cd ..
+$ cd ..
+$ cd trp
+$ ls
+233192 vqwngcs
+$ cd ..
+$ cd ..
+$ cd wfltm
+$ ls
+140990 djfww
+$ cd ..
+$ cd ..
+$ cd djb
+$ ls
+213191 cjwrs.prd
+dir dhvpqt
+dir gtgftm
+dir hvfvt
+208325 jwhp
+301446 qlqqmndd.zcb
+dir qnlbgvf
+dir tps
+dir zft
+dir zrtm
+dir zwnlm
+$ cd dhvpqt
+$ ls
+dir sbcj
+$ cd sbcj
+$ ls
+20611 ggt
+$ cd ..
+$ cd ..
+$ cd gtgftm
+$ ls
+179526 qcqbtmvq
+$ cd ..
+$ cd hvfvt
+$ ls
+dir djstcnrt
+dir hggpvn
+dir hvfvt
+63889 hvfvt.tjm
+265836 qlqqmndd.zcb
+105663 zft
+223582 zft.llg
+26037 zzwwg.lqh
+$ cd djstcnrt
+$ ls
+201498 hcqbmwc.gts
+139156 hpq.hgm
+277342 pshgz.rtp
+dir rjb
+257294 rqrb.lhh
+dir tqnbfnt
+313308 zft.dvc
+$ cd rjb
+$ ls
+268438 hpq.hgm
+dir hvfvt
+dir hvwpb
+161024 mzbcgqc.nvw
+137875 pwgswq.fld
+260008 pzzcww
+283261 wnvlrg.tmn
+$ cd hvfvt
+$ ls
+dir dvwqqt
+163397 hcqbmwc.gts
+265154 pwgswq.fld
+dir trsh
+dir vnf
+$ cd dvwqqt
+$ ls
+315187 hcqbmwc.gts
+$ cd ..
+$ cd trsh
+$ ls
+dir ssrdpg
+$ cd ssrdpg
+$ ls
+dir vjdc
+$ cd vjdc
+$ ls
+dir srvdrhdq
+$ cd srvdrhdq
+$ ls
+74145 djfww
+$ cd ..
+$ cd ..
+$ cd ..
+$ cd ..
+$ cd vnf
+$ ls
+dir djfww
+$ cd djfww
+$ ls
+184018 pwgswq.fld
+$ cd ..
+$ cd ..
+$ cd ..
+$ cd hvwpb
+$ ls
+dir jwpjrcvs
+$ cd jwpjrcvs
+$ ls
+dir cpcfcc
+$ cd cpcfcc
+$ ls
+52191 sdlv
+$ cd ..
+$ cd ..
+$ cd ..
+$ cd ..
+$ cd tqnbfnt
+$ ls
+dir djfww
+206341 fmpb.lnp
+dir fpsjg
+4589 hcqbmwc.gts
+dir hvfvt
+8796 hvfvt.hdz
+238364 tgcdpjc.fjm
+dir zrtm
+40577 zrtm.fsr
+$ cd djfww
+$ ls
+217182 djfww.rbf
+$ cd ..
+$ cd fpsjg
+$ ls
+52456 djfww
+$ cd ..
+$ cd hvfvt
+$ ls
+dir rqhzvb
+275026 szwgzm.qjd
+dir zbmtstj
+$ cd rqhzvb
+$ ls
+8395 gcmzsd.jzf
+$ cd ..
+$ cd zbmtstj
+$ ls
+39691 qlqqmndd.zcb
+dir qqcdss
+180676 rwl.zwr
+$ cd qqcdss
+$ ls
+106297 zrtm.nsl
+$ cd ..
+$ cd ..
+$ cd ..
+$ cd zrtm
+$ ls
+153478 ldhvt
+$ cd ..
+$ cd ..
+$ cd ..
+$ cd hggpvn
+$ ls
+19109 cpcfcc.fbh
+249168 fnqjc
+207420 qgzsh.pfs
+135472 qlqqmndd.zcb
+$ cd ..
+$ cd hvfvt
+$ ls
+dir djfww
+213659 hcqbmwc.gts
+dir jzdwq
+204021 nvbgf
+185328 qlqqmndd.zcb
+dir zrtm
+$ cd djfww
+$ ls
+180713 rwmm.gjt
+$ cd ..
+$ cd jzdwq
+$ ls
+57424 djfww.qtm
+104960 slq.bfp
+174906 svc
+$ cd ..
+$ cd zrtm
+$ ls
+dir mrtvhht
+$ cd mrtvhht
+$ ls
+188512 djfww.fvm
+$ cd ..
+$ cd ..
+$ cd ..
+$ cd ..
+$ cd qnlbgvf
+$ ls
+dir fjrhtssv
+46767 jhbnml.lpq
+$ cd fjrhtssv
+$ ls
+198664 fgcc
+245142 tsc.rsd
+$ cd ..
+$ cd ..
+$ cd tps
+$ ls
+dir fmlwghjv
+146731 gwch.ttr
+dir jjzmdd
+dir rtltrng
+191609 wff.mqt
+$ cd fmlwghjv
+$ ls
+189227 zrtm.vgg
+$ cd ..
+$ cd jjzmdd
+$ ls
+dir hvfvt
+178057 mpdfrrm
+49493 pwgswq.fld
+220129 sqgfb.flm
+231012 zrmsnmr
+$ cd hvfvt
+$ ls
+dir lbndbhc
+12602 mnclbss
+746 ppw
+$ cd lbndbhc
+$ ls
+49601 cdqvs.gwc
+158670 wvjpchjg
+$ cd ..
+$ cd ..
+$ cd ..
+$ cd rtltrng
+$ ls
+dir cpgh
+115613 hvfvt
+59441 zfs
+$ cd cpgh
+$ ls
+dir djfww
+$ cd djfww
+$ ls
+dir tgt
+$ cd tgt
+$ ls
+dir vqwvqss
+$ cd vqwvqss
+$ ls
+dir bsdrhz
+$ cd bsdrhz
+$ ls
+dir pld
+$ cd pld
+$ ls
+8543 mfs.gsb
+$ cd ..
+$ cd ..
+$ cd ..
+$ cd ..
+$ cd ..
+$ cd ..
+$ cd ..
+$ cd ..
+$ cd zft
+$ ls
+dir fhjgg
+$ cd fhjgg
+$ ls
+114494 pwgswq.fld
+$ cd ..
+$ cd ..
+$ cd zrtm
+$ ls
+201142 tlhr.rtd
+298232 wlcztszv
+$ cd ..
+$ cd zwnlm
+$ ls
+240023 hcqbmwc.gts
+159126 hpq.hgm
+22101 hvfvt.bfw
+dir ltzl
+dir mtfr
+dir sbw
+dir sqscdjlj
+dir ssf
+$ cd ltzl
+$ ls
+260692 hpq.hgm
+204540 hvfvt
+$ cd ..
+$ cd mtfr
+$ ls
+15391 pwgswq.fld
+$ cd ..
+$ cd sbw
+$ ls
+293226 hcqbmwc.gts
+267478 htllcq
+176349 nlbhcf.vpn
+286577 zft.gds
+$ cd ..
+$ cd sqscdjlj
+$ ls
+128776 gnh
+dir qbdpvcbt
+284505 qlsn.vdq
+$ cd qbdpvcbt
+$ ls
+280709 crv.hgm
+$ cd ..
+$ cd ..
+$ cd ssf
+$ ls
+13328 djfww.pjn
+19971 hvfvt
+dir zft
+$ cd zft
+$ ls
+97761 dnmnz
+$ cd ..
+$ cd ..
+$ cd ..
+$ cd ..
+$ cd djfww
+$ ls
+109590 bwfnnf.wpd
+297297 cmht.ljg
+280726 hvfvt
+$ cd ..
+$ cd drdf
+$ ls
+56764 pwgswq.fld
+300547 wqqm
+210698 zrtm.jvq
+$ cd ..
+$ cd fgbqtjlj
+$ ls
+22217 vrmgsz.ctg
+$ cd ..
+$ cd hjsmmj
+$ ls
+232911 bcqrmp.czf
+164656 hcqbmwc.gts
+dir jql
+dir ntd
+dir prgm
+dir psfvhh
+dir zft
+$ cd jql
+$ ls
+212767 zhnhn.lzm
+dir zrtm
+$ cd zrtm
+$ ls
+35950 bcqrmp.czf
+$ cd ..
+$ cd ..
+$ cd ntd
+$ ls
+dir vml
+$ cd vml
+$ ls
+60833 bcqrmp.czf
+$ cd ..
+$ cd ..
+$ cd prgm
+$ ls
+316166 pwgswq.fld
+$ cd ..
+$ cd psfvhh
+$ ls
+152195 pwgswq.fld
+92448 qlqqmndd.zcb
+$ cd ..
+$ cd zft
+$ ls
+95808 hpq.hgm
+$ cd ..
+$ cd ..
+$ cd msptbrl
+$ ls
+256069 hpq.hgm
+$ cd ..
+$ cd slpc
+$ ls
+dir djfww
+285380 djfww.gcm
+169898 hcqbmwc.gts
+40914 mnpnhpz
+188062 pwgswq.fld
+dir zrtm
+$ cd djfww
+$ ls
+94935 pwgswq.fld
+70655 qlqqmndd.zcb
+48528 zft.qvh
+$ cd ..
+$ cd zrtm
+$ ls
+160137 hcqbmwc.gts
+$ cd ..
+$ cd ..
+$ cd ..
+$ cd hvfvt
+$ ls
+dir cslthslv
+129407 prwq
+dir vrzfbtt
+$ cd cslthslv
+$ ls
+dir cpcfcc
+158361 hcqbmwc.gts
+$ cd cpcfcc
+$ ls
+dir zpgnczq
+$ cd zpgnczq
+$ ls
+158414 zft
+$ cd ..
+$ cd ..
+$ cd ..
+$ cd vrzfbtt
+$ ls
+185263 nqvvl
+$ cd ..
+$ cd ..
+$ cd phwgv
+$ ls
+253690 bzpcj.fcj
+dir wtbr
+168025 zdsh.tnq
+157840 zsdfqb.zbd
+$ cd wtbr
+$ ls
+dir lvgdb
+$ cd lvgdb
+$ ls
+177751 cpcfcc.dzr
+$ cd ..
+$ cd ..
+$ cd ..
+$ cd svw
+$ ls
+dir cpcfcc
+189430 hpq.hgm
+dir ntzbj
+13384 qlqqmndd.zcb
+10333 wdvqhwgl.trq
+161318 zwzp.jsn
+$ cd cpcfcc
+$ ls
+298999 hcqbmwc.gts
+290883 hpq.hgm
+dir qlnntp
+dir vpshs
+5547 wlrmg.bpc
+dir zft
+$ cd qlnntp
+$ ls
+168562 nqds.tqn
+$ cd ..
+$ cd vpshs
+$ ls
+246400 pwgswq.fld
+$ cd ..
+$ cd zft
+$ ls
+235634 hvfvt.hst
+$ cd ..
+$ cd ..
+$ cd ntzbj
+$ ls
+98777 qlqqmndd.zcb
+$ cd ..
+$ cd ..
+$ cd zft
+$ ls
+dir dhnzm
+299292 hvfvt.pvb
+dir ltfb
+dir mrvsjgsq
+dir ntr
+dir swmvhgd
+dir zrtm
+$ cd dhnzm
+$ ls
+267041 bbsj
+$ cd ..
+$ cd ltfb
+$ ls
+242136 bcqrmp.czf
+314862 dgdz
+203160 hcqbmwc.gts
+80422 hgvz
+dir qftjfqfv
+180815 sstl.wzg
+dir wmhm
+dir zft
+dir zszp
+$ cd qftjfqfv
+$ ls
+dir bmmw
+$ cd bmmw
+$ ls
+dir hvfvt
+318039 hvfvt.whc
+17057 pwgswq.fld
+$ cd hvfvt
+$ ls
+170348 brplf.wgv
+156783 hcqbmwc.gts
+$ cd ..
+$ cd ..
+$ cd ..
+$ cd wmhm
+$ ls
+178474 bcqrmp.czf
+dir cmsgv
+dir dcfvrtj
+225393 htjflrs.tlm
+dir hvfvt
+dir nlrs
+273173 nsmdd.glc
+151259 pwgswq.fld
+dir ztqvwjr
+$ cd cmsgv
+$ ls
+dir flgjbjg
+$ cd flgjbjg
+$ ls
+13971 cpcfcc
+20601 qlqqmndd.zcb
+$ cd ..
+$ cd ..
+$ cd dcfvrtj
+$ ls
+141992 djfww.djn
+118149 hpq.hgm
+dir qrmqslq
+$ cd qrmqslq
+$ ls
+105940 zrtm.vql
+$ cd ..
+$ cd ..
+$ cd hvfvt
+$ ls
+181962 hpq.hgm
+$ cd ..
+$ cd nlrs
+$ ls
+82705 vnfwjf.hhl
+$ cd ..
+$ cd ztqvwjr
+$ ls
+98257 pwgswq.fld
+83864 scv.pbp
+$ cd ..
+$ cd ..
+$ cd zft
+$ ls
+183072 rsbfsl.zsj
+$ cd ..
+$ cd zszp
+$ ls
+dir hvfvt
+$ cd hvfvt
+$ ls
+dir djfww
+dir dqdtgjtg
+dir hvfvt
+$ cd djfww
+$ ls
+117037 rnmbsq.zph
+259243 zrtm.znf
+$ cd ..
+$ cd dqdtgjtg
+$ ls
+dir lrbsvng
+59301 zft
+$ cd lrbsvng
+$ ls
+46301 bcqrmp.czf
+$ cd ..
+$ cd ..
+$ cd hvfvt
+$ ls
+223277 qlqqmndd.zcb
+$ cd ..
+$ cd ..
+$ cd ..
+$ cd ..
+$ cd mrvsjgsq
+$ ls
+160189 cpcfcc
+dir lzqf
+232626 pwgswq.fld
+dir rpmfcg
+$ cd lzqf
+$ ls
+135552 bcqrmp.czf
+48083 qlqqmndd.zcb
+dir rbg
+229086 rdswb.cjz
+204486 spbwfrwf.cmj
+$ cd rbg
+$ ls
+dir sjdwsbqq
+$ cd sjdwsbqq
+$ ls
+270621 rhv.shw
+$ cd ..
+$ cd ..
+$ cd ..
+$ cd rpmfcg
+$ ls
+227216 bld.jtn
+dir zft
+$ cd zft
+$ ls
+43056 vzc
+$ cd ..
+$ cd ..
+$ cd ..
+$ cd ntr
+$ ls
+dir cmtnqb
+dir djfww
+195371 wffvmql.lrv
+$ cd cmtnqb
+$ ls
+135380 pbng.vhq
+$ cd ..
+$ cd djfww
+$ ls
+dir fmvrrrq
+dir mbhrbss
+dir zrtm
+$ cd fmvrrrq
+$ ls
+dir cpcfcc
+79110 djfww
+300581 ftcdj.wcc
+$ cd cpcfcc
+$ ls
+234211 zsgsm
+$ cd ..
+$ cd ..
+$ cd mbhrbss
+$ ls
+149184 djfww.gwh
+185815 rhgw.rmj
+$ cd ..
+$ cd zrtm
+$ ls
+dir zft
+$ cd zft
+$ ls
+310043 bnwvt.fbg
+$ cd ..
+$ cd ..
+$ cd ..
+$ cd ..
+$ cd swmvhgd
+$ ls
+77547 djfww.jwr
+318547 drggg
+300962 pwgswq.fld
+$ cd ..
+$ cd zrtm
+$ ls
+229319 bflnffjj
+dir djfww
+142526 hvfvt
+232722 jprrf
+94024 ndmf.hdr
+dir vhdhn
+$ cd djfww
+$ ls
+30770 bcqrmp.czf
+$ cd ..
+$ cd vhdhn
+$ ls
+dir djfww
+48261 djfww.frg
+dir gqc
+316163 qlqqmndd.zcb
+$ cd djfww
+$ ls
+104095 cvjlthn.cfl
+223454 hgqwzh
+24715 pwgswq.fld
+283499 qlqqmndd.zcb
+dir zft
+224574 zlnwn
+$ cd zft
+$ ls
+100941 pwgswq.fld
+$ cd ..
+$ cd ..
+$ cd gqc
+$ ls
+156273 wpgwrdl
diff --git a/day7/uppga.c b/day7/uppga.c
@@ -0,0 +1,28 @@
+#include "common.h"
+
+uint64_t sum_sizes_leq(tn* cp, uint64_t leq)
+{
+ uint64_t r = 0;
+ size_t i;
+ for(i = 0; i < cp->children_n; i++)
+ r += sum_sizes_leq(cp->children[i], leq);
+ if(cp->size <= leq) r += cp->size;
+ return r;
+}
+
+int main(int argc, char** argv)
+{
+ char** lines;
+ size_t nlines = readlines(&lines, "input");
+
+ size_t i;
+ for(i = 0; i < nlines; i++) {
+ if(lines[i][strlen(lines[i])-1] == '\n')
+ lines[i][strlen(lines[i])-1] = '\0';
+ }
+
+ tn* root = parse_input(lines, nlines);
+ sum_sizes(root);
+ printf("%llu\n", sum_sizes_leq(root, 100000));
+ tn_cleartree(root);
+}
diff --git a/day7/uppgb.c b/day7/uppgb.c
@@ -0,0 +1,30 @@
+#include "common.h"
+
+uint64_t minok(tn* cp, uint64_t limit)
+{
+ uint64_t r = limit <= cp->size ? cp->size : UINT64_MAX;
+ size_t i;
+ for(i = 0; i < cp->children_n; i++) {
+ uint64_t tmp = minok(cp->children[i], limit);
+ if(tmp < r) r = tmp;
+ }
+ return r;
+}
+
+int main(int argc, char** argv)
+{
+ char** lines;
+ size_t nlines = readlines(&lines, "input");
+
+ size_t i;
+ for(i = 0; i < nlines; i++) {
+ if(lines[i][strlen(lines[i])-1] == '\n')
+ lines[i][strlen(lines[i])-1] = '\0';
+ }
+
+ tn* root = parse_input(lines, nlines);
+ sum_sizes(root);
+ assert(root->size + 30000000 >= 70000000);
+ printf("%llu\n", minok(root, (root->size + 30000000) - 70000000));
+ tn_cleartree(root);
+}
diff --git a/day8/Makefile b/day8/Makefile
@@ -0,0 +1,20 @@
+CC=clang
+UTILS=../utils/reading.o #../utils/stack_u64.o
+INCLUDES=-I../utils
+
+all: utils common.o uppga uppgb
+
+common.o: common.c common.h
+ $(CC) $(CFLAGS) -c common.c $(INCLUDES)
+
+uppga: $(UTILS) common.o uppga.c
+ $(CC) -Wall -o uppga uppga.c common.o $(UTILS) $(INCLUDES)
+
+uppgb: $(UTILS) common.o uppgb.c
+ $(CC) -Wall -o uppgb uppgb.c common.o $(UTILS) $(INCLUDES)
+
+utils:
+ make -C ../utils
+
+clean:
+ rm -rf common.o uppga uppgb
diff --git a/day8/common.c b/day8/common.c
@@ -0,0 +1,16 @@
+#include "common.h"
+
+uint8_t** grid(char** lines, size_t nlines, size_t* w)
+{
+ size_t i, j;
+ uint8_t** r = calloc(nlines, sizeof(*r));
+
+ *w = strlen(lines[0])-1;
+
+ for(i = 0; i < nlines; i++) {
+ r[i] = calloc(*w, sizeof(**r));
+ for(j = 0; j < *w; j++) r[i][j] = lines[i][j]-'0';
+ }
+
+ return r;
+}
diff --git a/day8/common.h b/day8/common.h
@@ -0,0 +1,11 @@
+#ifndef COMMON_H_
+#define COMMON_H_
+
+#include <stdio.h>
+#include <stdint.h>
+#include <assert.h>
+#include <reading.h>
+
+uint8_t** grid(char** lines, size_t nlines, size_t* w);
+
+#endif
diff --git a/day8/einput b/day8/einput
@@ -0,0 +1,5 @@
+30373
+25512
+65332
+33549
+35390
diff --git a/day8/input b/day8/input
@@ -0,0 +1,99 @@
+222100000013112132123310430431410000421233203434334433324302430012114211021123030010201312000120201
+101021021033011112103044112003343322403423454241342342345211525113333240020143443122030210310022011
+220101001133100310002411002043420103515231215523212315435342111245041142130232312400222030320100112
+200122221230321133044100332034021325535145544344545253525534243453412331214043304401230010020110000
+000011200031133111412421443430224551211135242142233535513155431423245220314304114203010112113003022
+200110301031330240043404212112151455211214554251222423224121251245551231544200332324141021101302320
+211313310001120421114110031311134411225441423121215412315242313455445215433103243003331323232021210
+113023232323114232323200154111555445211221521564442455324451241134422414442353242422024301202303200
+033103132121042304342321133113123442114234244262244362254636514423544554241131340043413001103230111
+222130001131222313011514241155115431453566353362523635234523544443331545242212110302120041131331000
+122003333203421424243423241241145242362425662245243454434463245655424513432355342413342304140323132
+200132001433233414535423533545455356266563252323664634454642325452632535414233213444024120224001312
+103022000024242042232345311151252366645245625425252254664223635666456554424455255314414201023100202
+011123314401132331522443121124243332365536553533653266524244535435555642241321424311440431140002313
+112211332222044342251223514432453246552433654362667575535222222434424332333535551325510210012402111
+012034031201422433433544333435332354236525757766675753775672443526635625666411211315313431001211021
+222131010444144222113122265646535633254344346447355664747364675464264442356435454343134203131301320
+130204300400253551553414543245455464767455566634465767776436634753554635546252415422554253212302111
+003420010011545433455324656653655336363754663777466766534773337737564264622226622152541532444043422
+222443443245214511144624625533466765654637646677673764377774656447545424634555552322232123102200221
+131401122122541311136443466423774374674674644356633456444637564653463756534425365511222235542400434
+020304120343231311655625465655375336347635537637356474737537736475747664453654642435444421312003441
+330343204414214144663432532273356366677365344448485644668544447556754747333244226622353444432431203
+013032001213332124643646542366473765434545644448468456647846863656675334773653446336233442425343443
+032304344311244225545253365465763653568645444468586475857554557364567345453456433425434524425320340
+404422443241453445422422553656467636467787445444464844587867767885464476337762322652643443152400310
+423240415535414656342334546645767686856678584786777647846875755758745674346466423542354114134214444
+011030431533245543654555435345765747564477644667658776568874577764754567666746242522425334235523011
+304141431155466443263644746373647747866875877747665747457575464455646775674543326443642441231224201
+131114441112334443562775355733455774775467784987985795575544877666455543676676766355422441315441324
+430314423542533443234733353445778486466878667959585558576994644485858886644666446446534452214325144
+234043255111363462227473347477688468584489685978769565888875968868778767543673677363352531435143524
+332514411423345463663744673467787665769687998556765798696889899888747474874533436436252246354342354
+343351353455545565635555344675547864877967899959657795679897665768887566875734464464265463133152220
+304315235446623534567454757568755564666595669996877688899968576566787884766634473546655234425154332
+102434355126466525455775354887868447559596877755866959597666867668558485674655477534335455431433112
+122435322353564665545357554686754498985569558877879689779956877758645856774754544465455555411345432
+205343122436524456576336444487867565768865559989677777796577669975668468746773345355325355462321544
+244421231222553435356653847788488675876678988776997676698897689969586845444476467776346464255425235
+011141212323222656564355748565568698959878768999769698979687856698985667477447735736764436662535445
+341532114624343674454664747878669755789998777768669876776979978586767967487477444333746325646435514
+332225232253533547565768678777599889889986786676898889796886795899776746658866733634625566222131221
+452115152353553475665558585658666677868888996889998779787687898769796898574684366444335464566131241
+222451343363565554437346767558895565959796776666688967696988666679956757766466653747344422662412441
+352312532554653753433645874848668779969867679887889979966988777858759985688847467477436644343221314
+253453523324622576773348855746776868699997976897788898798988697688759757656674457764653663435535551
+255215136645533637445568746577666855796996998878787787989997666766965555455644774737474254653535431
+224553242555543337334785854657996797787699767987987877987767789767987655676757876444754463423354514
+123154243466644666546775557579585989696788969989777778898979998897985697866556637766477643365644322
+554211453455627676754574468848856965688687898898898987897889687869558659748577474654465642432212231
+121545355642566434543444766876559558799969877778988788897996978967956568566568437553533324624643533
+343533523352453757643688556467889769997789877997988888888997869785799657747877636573466342443313343
+514522335642537537375788876657768698786777789799788789989868878986986599667677637644366254666343342
+445132523635445577344646447787655657998679778899778887789986767685689896766667567376634235626522255
+531432262653342445554787675779556895668677679888998898998979898688885658645488775453563263324444521
+244354252355562565357375758886677896998668697778978777786868797957956585645446465464342453536315311
+331332542346565453565468588687898988998899678777778888987879896766957964458684767674732342255112134
+323222553252555764467548647586787989698798867966879898766777967895559878445748535555772564352323121
+222112256556444766665645575857868775966987669678797778989996976999597964558764436354464354454115511
+231521425424626436644777445867799777875677879667696879686889969989898845765485563646336643234131352
+355133253664246535564564876446795699978678666879799996766969886966786964656655463556453424246325411
+032153423465433637445644746455668795767666979897978979967667987866677885867645774566445534632451125
+023153145454343367456365744778545786785687966678788897768987767885867756448666544363445625242522531
+433143232524343347377744757586847855967999597666986986999686668885676754478777454637243455342311532
+041445134126223465774744566767745475776968756578667896988697555595776655546733433735653653432132233
+221512433144443536474554676654665445558779696796579879876998998776465745558346764543545453644144545
+331424235262424426737544466746485788568786659757689559959759667768655887786744476475525364623425533
+320451531315362426576743675876464666456576667575695897756879976656668566874643454335445262114444554
+433151555354653533355456563775468744778576966965557755996597568885868445653464345446225342143132550
+214125323355543252463774664575887864646475575755776587586666976564488546433557465425532665321234540
+200323512352523254535467534457646558758856986957578658768964788848786647657766457454556542424151320
+321332134211123223226667643735764455548668485865685588886847485767774746455657633463665254121412001
+012234315531464554245247467735667568768477464845687764665675656887448367475433732636565224541321012
+301234542341223435424426747367366544565566848548747578766588788767885775664437356522235353533143014
+334003331234445455322432564335463367457486487588666685866765755644646453645643652462624434432442422
+042143134435444325324432335637663775578547578854666475667787688784544634336532242223445252453531242
+310411334152432163553225536747773333656667455878457766657566745435666777454323262242612514451104020
+240402042351343515263253256753473577367758467858666457875545437655464455452535563554421221153321201
+140230434512144443255324466566375735664375475557548858557333643346544766626556653552352331343211204
+103332424311424141626635455553663773455334335637373374565743454773345777455425656462325511551200242
+300034243213121311233252524644436354656563557344777363377675636366463362642532235453325525444412244
+212242021025345333222565653434654746356455755667665757547556664465433533346662654353424311001014101
+131101234311553242452666635432665533633753765643655666636643433754534354353642634345311333033143214
+230232130130231122325124444645225546335344735745337356445573656773545235424533233332544531130001441
+203302312432313112332152223225462333636474337343366375747734333244655463653321433443325513101324303
+220234041400202455245214462454254525365333654447453545675644632235454662344232215321554320103020310
+200010034012032125113513354322342432455256556433373774556434252645545426455143411452141404444030212
+100330134044341121214144343523422253634565324653336633436226523634446353531514354335531412332131232
+130332044322000001512111255442345646456454345262564366666436346533225534443132355523003421120002002
+113132210324301312214421141434544636364655266265645646422544566424244551313122432513114113023320010
+112132020021120122422112434111115365555664632265464656245333363252541131215331552444402413142001121
+203112202340410440414115311114515245122424246432322362425453662652145112443553123122131302001031212
+230300331323432142203321123243444245342565365466665664464243251544455253512331101201042041220200212
+023003202312212103443344553251225314354244313342234634552312313531432211135354024130442013121321330
+202322100120313004402231123343531111133245451514414545333322414215353123341412440243322310212031021
+221023032132103304434414013211335214155422221314144114325152225215522555512120322411330301131003022
+201103233233322020210340012040333235122454154134514325421433512223435543144431413040233113023112011
+221021131310123213123044244400331522512444434344354343132442132331145324334003431424001200033011112
+102201030320220211144211104323434023533353133112145253453525542112011403201223032223120103003122001
diff --git a/day8/uppga.c b/day8/uppga.c
@@ -0,0 +1,75 @@
+#include "common.h"
+
+int main(int argc, char** argv)
+{
+ char** lines;
+ size_t nlines = readlines(&lines, "input");
+
+ size_t w;
+ int i,j;
+ uint8_t** g = grid(lines, nlines, &w);
+
+ uint8_t f[nlines][w];
+ bzero(f, nlines*w);
+
+ // left
+ size_t m;
+ for(i = 0; i < nlines; i++) {
+ f[i][0] = 1;
+ m = g[i][0];
+ for(j = 1; j < w; j++) {
+ if(g[i][j] > m) {
+ m = g[i][j];
+ f[i][j] = 1;
+ }
+ if(m == 9) break;
+ }
+ }
+
+ // right
+ for(i = 0; i < nlines; i++) {
+ f[i][w-1] = 1;
+ m = g[i][w-1];
+ for(j = w-2; j > 0; j--) {
+ if(g[i][j] > m) {
+ m = g[i][j];
+ f[i][j] = 1;
+ }
+ if(m == 9) break;
+ }
+ }
+
+ // top
+ for(i = 0; i < w; i++) {
+ f[0][i] = 1;
+ m = g[0][i];
+ for(j = 1; j < nlines; j++) {
+ if(g[j][i] > m) {
+ m = g[j][i];
+ f[j][i] = 1;
+ }
+ if(m == 9) break;
+ }
+ }
+
+ // bottom
+ for(i = 0; i < w; i++) {
+ f[nlines-1][i] = 1;
+ m = g[nlines-1][i];
+ for(j = nlines-2; j > 0; j--) {
+ if(g[j][i] > m) {
+ m = g[j][i];
+ f[j][i] = 1;
+ }
+ if(m == 9) break;
+ }
+ }
+
+ uint64_t c = 0;
+ for(i = 0; i < nlines; i++) {
+ for(j = 0; j < w; j++) {
+ if(f[i][j]) c++;
+ }
+ }
+ printf("%llu\n", c);
+}
diff --git a/day8/uppgb.c b/day8/uppgb.c
@@ -0,0 +1,60 @@
+#include "common.h"
+
+uint64_t sscore(uint8_t** g, int i, int j, size_t nlines, size_t w)
+{
+ uint64_t u=0,d=0,r=0,l=0;
+
+ int k;
+ uint8_t m = g[i][j];
+ for(k = i-1; k >= 0; k--) {
+ u++;
+ if(g[k][j] >= m) break;
+ }
+
+ m = g[i][j];
+ for(k = i+1; k < nlines; k++) {
+ d++;
+ if(g[k][j] >= m) break;
+ }
+
+ m = g[i][j];
+ for(k = j+1; k < w; k++) {
+ r++;
+ if(g[i][k] >= m) break;
+ }
+
+ m = g[i][j];
+ for(k = j-1; k >= 0; k--) {
+ l++;
+ if(g[i][k] >= m) break;
+ }
+
+ return u*d*r*l;
+}
+
+int main(int argc, char** argv)
+{
+ char** lines;
+ size_t nlines = readlines(&lines, "input");
+
+ size_t w;
+ uint8_t** g = grid(lines, nlines, &w);
+
+ uint64_t f[nlines][w];
+
+ int i,j;
+ for(i = 0; i < nlines; i++)
+ for(j = 0; j < w; j++)
+ f[i][j] = 0;
+
+ for(i = 0; i < nlines; i++)
+ for(j = 0; j < w; j++)
+ f[i][j] = sscore(g, i, j, nlines, w);
+
+ uint64_t m = 0;
+ for(i = 0; i < nlines; i++)
+ for(j = 0; j < w; j++)
+ if(f[i][j] > m) m = f[i][j];
+
+ printf("%llu\n", m);
+}
diff --git a/day9/Makefile b/day9/Makefile
@@ -0,0 +1,20 @@
+CC=clang
+UTILS=../utils/reading.o ../utils/smallset.o ../utils/stack_u64.o
+INCLUDES=-I../utils
+
+all: utils common.o uppga uppgb
+
+common.o: common.c common.h
+ $(CC) $(CFLAGS) -c common.c $(INCLUDES)
+
+uppga: $(UTILS) common.o uppga.c
+ $(CC) -Wall -o uppga uppga.c common.o $(UTILS) $(INCLUDES)
+
+uppgb: $(UTILS) common.o uppgb.c
+ $(CC) -Wall -o uppgb uppgb.c common.o $(UTILS) $(INCLUDES)
+
+utils:
+ make -C ../utils
+
+clean:
+ rm -rf common.o uppga uppgb
diff --git a/day9/common.c b/day9/common.c
@@ -0,0 +1,37 @@
+#include "common.h"
+
+uint64_t parse(int* boundaries, char* dirs, uint64_t* times,
+ char** lines, size_t nlines)
+{
+ uint64_t tot = 0;
+ int cp[2] = {0,0};
+ bzero(boundaries, sizeof(*boundaries) * 4);
+
+ size_t i;
+ for(i = 0; i < nlines; i++) {
+ uint64_t tmp;
+ sread_next_u64(&tmp, lines[i]);
+ dirs[i] = lines[i][0];
+ times[i] = tmp;
+ tot += tmp;
+
+ if(lines[i][0] == 'R') cp[0] += tmp;
+ else if(lines[i][0] == 'L') cp[0] -= tmp;
+ else if(lines[i][0] == 'U') cp[1] += tmp;
+ else if(lines[i][0] == 'D') cp[1] -= tmp;
+ if(cp[0] < boundaries[0]) boundaries[0] = cp[0];
+ if(cp[0] > boundaries[1]) boundaries[1] = cp[0];
+ if(cp[1] < boundaries[2]) boundaries[2] = cp[1];
+ if(cp[1] > boundaries[3]) boundaries[3] = cp[1];
+ }
+
+ return tot;
+}
+
+uint64_t diagon(int* pos, int* boundaries)
+{
+ uint64_t xpos = (uint64_t) (pos[0] - boundaries[0]);
+ uint64_t ypos = (uint64_t) (pos[1] - boundaries[2]);
+ uint64_t xdim = (uint64_t) (1 + boundaries[1] - boundaries[0]);
+ return ypos*xdim + xpos;
+}
diff --git a/day9/common.h b/day9/common.h
@@ -0,0 +1,15 @@
+#ifndef COMMON_H_
+#define COMMON_H_
+
+#include <stdio.h>
+#include <stdint.h>
+#include <assert.h>
+#include <reading.h>
+#include <smallset.h>
+#include <stack_u64.h>
+
+uint64_t parse(int* boundaries, char* dirs, uint64_t* times,
+ char** lines, size_t nlines);
+uint64_t diagon(int* pos, int* boundaries);
+
+#endif
diff --git a/day9/einput b/day9/einput
@@ -0,0 +1,8 @@
+R 4
+U 4
+L 3
+D 1
+R 4
+D 1
+L 5
+R 2
diff --git a/day9/input b/day9/input
@@ -0,0 +1,2000 @@
+R 2
+U 2
+L 2
+U 1
+L 1
+U 1
+R 1
+L 2
+U 2
+R 1
+D 2
+U 2
+R 1
+D 1
+L 1
+R 1
+L 2
+U 2
+L 2
+D 1
+R 1
+U 2
+L 2
+U 2
+R 1
+D 1
+L 2
+U 2
+R 2
+L 2
+U 2
+R 2
+L 1
+U 2
+R 2
+D 1
+L 1
+R 2
+U 1
+R 2
+D 2
+L 1
+R 1
+U 1
+R 2
+L 1
+U 1
+R 1
+L 2
+D 2
+R 2
+D 1
+L 2
+R 2
+L 1
+R 2
+D 1
+R 2
+D 2
+L 1
+R 1
+U 2
+L 2
+R 2
+D 1
+R 2
+U 2
+L 1
+D 2
+R 2
+L 2
+D 2
+U 1
+R 2
+U 2
+R 2
+D 2
+R 1
+U 2
+D 2
+R 1
+L 1
+R 1
+U 2
+D 2
+R 1
+U 1
+R 1
+L 1
+U 2
+L 2
+D 2
+U 2
+D 2
+R 2
+D 2
+L 1
+U 2
+L 1
+R 1
+D 2
+L 1
+U 1
+D 2
+U 2
+D 2
+R 2
+U 1
+R 1
+U 2
+D 1
+R 2
+D 2
+L 3
+U 1
+D 2
+U 3
+R 3
+L 1
+D 2
+R 1
+D 3
+L 3
+R 1
+D 3
+L 3
+D 1
+R 3
+D 1
+L 1
+D 2
+R 3
+D 1
+U 2
+R 2
+L 1
+D 1
+R 3
+U 2
+L 3
+U 2
+D 2
+R 2
+D 3
+U 1
+D 3
+L 3
+R 2
+L 2
+D 3
+L 2
+U 3
+R 2
+D 1
+R 2
+U 3
+R 3
+U 3
+L 1
+R 3
+D 2
+R 1
+L 3
+R 1
+D 3
+L 3
+D 1
+U 2
+R 3
+U 3
+D 1
+L 2
+R 3
+L 1
+D 2
+L 3
+D 1
+L 3
+D 1
+U 2
+D 3
+R 2
+U 1
+L 3
+R 3
+L 2
+R 1
+L 2
+D 2
+R 3
+U 3
+R 3
+D 2
+U 3
+D 2
+R 3
+D 3
+R 2
+U 1
+L 3
+U 2
+R 2
+L 2
+U 1
+L 3
+D 2
+U 2
+R 1
+L 2
+D 2
+U 3
+R 2
+D 2
+L 3
+U 1
+L 1
+U 2
+R 2
+U 1
+D 2
+U 2
+R 3
+L 1
+U 1
+D 3
+U 4
+L 3
+D 2
+L 3
+U 4
+D 2
+R 4
+L 4
+U 2
+D 3
+U 2
+D 3
+L 3
+U 2
+D 3
+L 1
+U 1
+R 1
+L 4
+R 3
+D 3
+L 2
+U 3
+R 2
+L 1
+U 4
+D 3
+U 1
+L 2
+D 4
+L 1
+R 3
+D 4
+R 1
+L 1
+U 3
+L 3
+D 3
+R 3
+U 1
+L 4
+U 3
+R 3
+L 3
+U 2
+R 3
+L 3
+R 1
+D 3
+R 3
+L 4
+R 3
+D 4
+L 3
+U 2
+R 4
+L 1
+U 1
+R 4
+D 3
+U 1
+R 1
+D 1
+U 3
+R 2
+L 1
+D 1
+L 3
+D 4
+R 4
+U 4
+D 1
+R 3
+D 3
+R 3
+L 4
+R 4
+L 2
+R 2
+D 3
+R 4
+D 2
+U 4
+L 3
+D 1
+R 2
+U 2
+R 3
+D 1
+R 3
+D 1
+L 1
+U 4
+L 2
+U 4
+L 4
+U 3
+R 4
+L 3
+R 3
+L 4
+U 4
+R 4
+D 2
+R 2
+D 3
+U 4
+D 1
+U 1
+D 5
+U 3
+D 5
+U 5
+D 3
+L 3
+U 3
+D 3
+R 1
+D 3
+R 4
+U 4
+D 1
+R 5
+D 5
+R 2
+U 5
+L 2
+U 2
+D 2
+U 4
+R 1
+D 1
+L 2
+R 2
+D 1
+L 5
+R 5
+D 4
+R 5
+L 1
+D 2
+L 3
+U 2
+D 3
+L 1
+R 5
+U 3
+R 1
+D 3
+R 1
+U 1
+R 3
+U 2
+D 5
+L 5
+R 1
+U 3
+L 4
+D 2
+R 1
+D 3
+U 4
+R 3
+L 4
+U 2
+D 3
+U 1
+R 5
+D 3
+L 2
+U 3
+L 5
+U 3
+L 3
+D 5
+L 5
+U 3
+R 2
+D 5
+U 4
+L 5
+U 1
+D 5
+R 3
+D 1
+L 5
+R 2
+D 2
+U 5
+R 1
+D 2
+L 3
+D 2
+L 5
+D 2
+U 5
+L 2
+R 3
+L 3
+D 3
+U 2
+R 5
+L 1
+U 5
+R 5
+L 2
+D 5
+R 3
+L 2
+U 2
+D 3
+R 4
+L 1
+R 3
+D 5
+R 3
+D 4
+R 2
+D 5
+R 3
+L 3
+R 2
+U 2
+L 1
+R 6
+U 6
+L 6
+U 2
+R 6
+D 4
+U 1
+L 1
+R 1
+D 1
+L 6
+D 6
+U 4
+L 6
+D 3
+R 1
+U 1
+D 3
+R 3
+D 5
+U 1
+L 2
+R 6
+U 5
+D 6
+L 6
+R 2
+U 1
+D 1
+L 4
+D 5
+L 6
+U 1
+L 6
+R 5
+U 5
+D 3
+L 5
+R 2
+U 3
+D 1
+L 2
+U 2
+D 1
+L 5
+D 1
+U 5
+R 4
+L 2
+R 5
+D 3
+U 3
+R 2
+U 3
+D 6
+L 5
+R 1
+U 5
+L 1
+R 6
+D 6
+R 6
+L 1
+D 2
+R 5
+L 4
+D 3
+L 5
+R 4
+L 6
+U 1
+L 2
+U 3
+R 4
+D 3
+R 3
+L 1
+D 4
+L 2
+R 5
+D 2
+R 2
+D 5
+U 2
+L 4
+R 4
+U 4
+R 1
+D 3
+L 6
+U 5
+L 5
+D 6
+U 3
+D 6
+R 6
+D 3
+U 6
+L 6
+D 3
+L 6
+R 3
+D 2
+L 4
+D 5
+L 5
+D 2
+L 6
+R 1
+D 1
+L 4
+U 6
+R 1
+L 5
+D 7
+U 2
+R 6
+D 7
+L 2
+R 3
+U 1
+L 3
+R 2
+U 7
+D 7
+U 7
+D 4
+R 2
+L 7
+R 7
+L 5
+R 4
+U 5
+L 5
+U 6
+R 2
+D 3
+L 2
+U 6
+D 5
+R 2
+D 2
+R 5
+U 7
+R 3
+D 1
+L 5
+R 1
+U 3
+D 6
+U 6
+L 7
+U 4
+L 6
+D 1
+L 7
+U 4
+D 7
+L 1
+D 6
+L 2
+R 5
+L 7
+U 3
+D 2
+R 7
+L 2
+U 6
+L 3
+U 6
+L 5
+R 2
+L 7
+D 3
+L 7
+R 1
+L 1
+R 5
+D 6
+L 2
+D 5
+L 4
+D 3
+U 5
+D 1
+R 4
+U 1
+L 2
+R 3
+U 7
+D 6
+U 2
+D 4
+U 5
+D 5
+U 7
+R 2
+D 1
+U 2
+L 2
+U 3
+D 1
+R 4
+D 1
+R 3
+U 1
+R 7
+D 4
+R 3
+D 2
+L 2
+U 4
+L 2
+U 6
+L 4
+D 6
+U 3
+L 1
+U 4
+R 7
+D 6
+L 2
+D 7
+R 4
+U 5
+R 4
+D 5
+R 6
+D 4
+R 4
+U 2
+R 3
+L 7
+R 8
+D 8
+R 5
+U 2
+D 6
+L 2
+R 4
+U 3
+L 1
+R 2
+D 5
+L 1
+D 5
+L 5
+U 1
+R 8
+D 1
+U 1
+L 1
+R 8
+L 3
+R 6
+L 1
+U 3
+R 6
+L 5
+U 2
+L 8
+R 4
+U 4
+R 6
+U 5
+R 1
+L 2
+R 5
+D 1
+U 4
+L 3
+U 3
+R 1
+U 3
+R 8
+L 1
+U 2
+L 7
+D 6
+L 6
+R 4
+D 2
+R 2
+L 8
+D 4
+R 4
+U 4
+L 6
+D 3
+R 7
+D 8
+U 4
+R 4
+U 2
+L 8
+D 5
+L 4
+U 7
+D 8
+U 6
+R 6
+L 5
+D 5
+L 2
+D 1
+R 1
+D 4
+R 5
+L 7
+D 8
+U 2
+D 3
+L 5
+R 4
+L 7
+R 3
+L 1
+D 8
+R 5
+L 8
+R 8
+D 1
+R 4
+D 1
+L 2
+D 5
+L 7
+U 1
+L 4
+R 5
+L 3
+R 9
+D 9
+L 4
+R 6
+L 6
+R 1
+L 3
+R 5
+D 8
+L 1
+U 2
+R 8
+U 7
+D 6
+L 8
+D 1
+L 9
+D 5
+L 1
+D 6
+L 8
+R 2
+L 6
+R 4
+U 1
+R 6
+L 5
+R 5
+L 6
+R 8
+D 5
+L 4
+R 2
+L 7
+R 2
+U 9
+L 6
+R 2
+U 7
+D 4
+U 2
+L 2
+U 8
+R 8
+U 3
+R 6
+D 6
+L 2
+D 4
+L 4
+R 2
+L 1
+U 8
+D 2
+R 2
+L 1
+R 7
+L 8
+D 8
+L 4
+U 4
+R 5
+U 1
+D 8
+L 8
+R 9
+D 6
+L 1
+D 5
+L 9
+U 6
+D 6
+U 3
+D 5
+R 5
+U 9
+L 2
+R 5
+U 9
+L 1
+D 4
+U 4
+L 5
+D 6
+R 3
+L 6
+U 3
+R 4
+U 5
+L 5
+D 8
+L 6
+U 4
+D 1
+U 7
+D 2
+L 3
+R 7
+U 1
+R 4
+U 4
+R 9
+U 3
+D 2
+L 6
+R 9
+U 3
+L 8
+R 10
+U 3
+R 8
+D 8
+L 1
+U 4
+R 5
+U 8
+D 10
+U 10
+L 7
+D 5
+L 2
+R 7
+L 1
+U 10
+R 1
+D 1
+L 5
+R 7
+U 6
+L 3
+R 7
+U 4
+R 3
+U 3
+R 4
+U 8
+L 8
+D 6
+L 5
+U 10
+L 9
+R 3
+U 10
+D 9
+U 5
+D 10
+U 7
+D 6
+U 9
+L 8
+U 3
+D 6
+R 9
+U 9
+D 4
+R 8
+U 7
+R 6
+U 5
+R 5
+U 3
+D 4
+R 9
+L 7
+D 7
+U 1
+L 3
+R 4
+D 8
+L 4
+D 6
+U 1
+R 7
+D 4
+L 9
+D 2
+R 4
+U 10
+D 5
+U 6
+D 6
+R 5
+U 6
+D 6
+L 7
+U 4
+D 1
+L 6
+R 8
+L 7
+U 8
+L 2
+R 6
+L 9
+D 2
+U 9
+D 5
+U 10
+D 1
+R 9
+L 6
+D 7
+U 1
+D 4
+L 3
+R 7
+U 1
+R 6
+D 4
+R 1
+D 4
+L 8
+R 1
+U 10
+D 1
+U 5
+R 6
+U 5
+D 2
+U 10
+R 8
+L 7
+U 6
+L 4
+R 6
+L 7
+U 3
+R 4
+D 1
+L 4
+R 7
+D 2
+L 4
+U 3
+D 6
+U 10
+D 5
+R 8
+U 5
+L 9
+D 4
+L 4
+D 8
+U 9
+R 2
+U 4
+R 4
+U 9
+D 1
+R 7
+U 5
+L 2
+U 10
+R 4
+D 1
+L 3
+R 11
+D 7
+U 7
+D 7
+L 11
+U 2
+D 1
+U 1
+R 1
+U 3
+L 6
+U 10
+L 4
+U 5
+L 10
+D 1
+U 8
+R 7
+L 4
+U 7
+L 9
+U 6
+L 11
+U 3
+R 8
+L 6
+D 9
+L 9
+D 1
+R 7
+L 11
+D 9
+R 7
+U 2
+D 11
+L 4
+D 4
+R 11
+D 7
+U 2
+D 7
+R 2
+D 1
+L 6
+D 11
+R 3
+U 7
+L 10
+U 7
+D 2
+R 2
+U 1
+L 9
+R 11
+L 3
+R 7
+L 2
+D 11
+R 1
+D 4
+R 3
+L 10
+U 5
+D 3
+R 10
+D 8
+U 1
+D 2
+R 10
+L 8
+R 1
+D 8
+U 6
+R 8
+D 8
+L 2
+D 7
+U 4
+L 5
+R 4
+D 4
+U 7
+D 11
+U 11
+R 4
+L 6
+U 3
+L 10
+U 1
+L 11
+U 3
+D 6
+L 11
+R 4
+L 3
+D 12
+L 7
+R 9
+L 9
+U 10
+L 1
+D 6
+L 10
+U 3
+R 6
+D 5
+L 6
+R 8
+D 4
+R 6
+L 6
+D 9
+L 1
+D 11
+U 6
+L 3
+R 10
+U 12
+R 11
+D 10
+U 5
+R 6
+D 12
+U 12
+R 8
+U 5
+D 1
+R 12
+D 1
+R 7
+U 8
+D 5
+U 7
+D 3
+R 7
+D 8
+U 11
+R 2
+U 4
+L 2
+R 1
+L 3
+U 9
+L 5
+D 11
+R 10
+L 3
+U 3
+D 3
+R 1
+L 8
+D 6
+R 7
+U 11
+L 6
+D 1
+R 12
+D 8
+U 7
+R 2
+U 5
+R 4
+U 10
+L 8
+D 5
+U 10
+D 3
+L 6
+R 4
+L 9
+D 6
+R 7
+D 4
+U 10
+D 1
+L 6
+R 1
+L 7
+U 5
+L 9
+U 12
+L 7
+U 6
+D 6
+U 9
+L 7
+U 4
+D 5
+L 1
+U 5
+D 1
+L 10
+D 2
+R 3
+D 13
+U 11
+L 1
+U 1
+D 1
+R 12
+U 13
+L 5
+D 11
+L 9
+U 11
+L 2
+R 6
+D 7
+L 2
+U 5
+R 2
+U 10
+L 9
+D 7
+R 12
+D 10
+L 12
+D 8
+L 8
+R 12
+D 11
+U 12
+L 1
+U 2
+D 6
+R 3
+D 2
+U 9
+L 10
+R 4
+U 2
+D 10
+U 7
+R 6
+U 9
+R 4
+L 3
+U 13
+R 9
+U 6
+D 8
+L 5
+R 11
+L 6
+R 12
+D 5
+U 7
+R 11
+D 1
+L 9
+R 12
+U 2
+R 5
+U 1
+R 9
+U 6
+D 4
+R 2
+U 2
+D 5
+L 9
+R 6
+U 4
+L 6
+R 9
+L 4
+U 3
+L 9
+R 6
+L 5
+D 6
+L 3
+R 6
+L 3
+D 9
+U 5
+D 1
+R 5
+L 3
+U 9
+R 7
+L 8
+R 6
+L 7
+U 4
+D 13
+U 2
+L 1
+U 11
+R 8
+L 13
+D 1
+U 4
+L 13
+D 1
+L 8
+D 13
+L 2
+R 2
+D 1
+L 14
+U 7
+R 11
+L 1
+R 4
+L 5
+R 11
+U 7
+D 8
+L 3
+U 1
+L 12
+U 13
+D 9
+R 1
+L 11
+U 12
+D 5
+U 10
+D 10
+R 9
+L 1
+D 5
+R 7
+L 1
+D 13
+R 10
+U 2
+R 3
+L 14
+D 7
+R 12
+U 13
+L 2
+U 13
+L 3
+U 5
+L 11
+R 8
+D 11
+R 6
+L 11
+R 5
+L 3
+U 1
+L 5
+R 13
+L 12
+D 10
+R 8
+D 6
+L 1
+R 10
+U 5
+R 3
+D 11
+L 8
+R 4
+D 2
+L 1
+R 7
+U 3
+L 14
+R 3
+L 4
+R 13
+L 10
+U 3
+D 1
+L 11
+U 1
+D 6
+R 10
+U 1
+R 2
+L 7
+U 3
+L 5
+U 4
+D 7
+R 8
+U 12
+R 6
+L 2
+D 5
+L 11
+R 4
+L 4
+R 6
+L 3
+R 10
+U 4
+D 9
+U 1
+D 4
+L 12
+D 13
+L 1
+D 6
+R 8
+L 1
+D 9
+L 8
+U 3
+D 3
+U 2
+R 11
+U 10
+L 5
+D 11
+U 12
+D 3
+R 15
+L 1
+R 5
+D 9
+U 15
+D 2
+L 9
+U 9
+D 15
+R 4
+L 9
+R 8
+L 12
+D 5
+R 12
+U 9
+L 9
+U 7
+L 12
+R 11
+U 9
+L 15
+D 9
+L 4
+R 4
+U 13
+D 7
+R 7
+D 8
+U 5
+D 5
+L 15
+D 2
+R 8
+D 10
+R 5
+U 13
+R 1
+L 8
+D 12
+R 2
+L 4
+D 9
+L 9
+D 7
+R 5
+U 15
+R 9
+L 2
+R 8
+U 11
+D 15
+U 13
+D 5
+U 5
+R 11
+U 7
+R 11
+D 12
+U 6
+D 6
+L 8
+D 8
+R 14
+U 13
+R 11
+D 1
+R 4
+U 14
+R 11
+L 8
+D 2
+U 13
+R 15
+L 10
+D 2
+L 3
+R 9
+U 2
+R 8
+U 15
+R 3
+D 4
+L 7
+D 7
+R 1
+D 13
+R 1
+L 13
+U 9
+L 13
+U 10
+L 15
+D 5
+R 11
+D 3
+U 3
+R 4
+L 7
+R 1
+U 13
+R 9
+U 7
+R 10
+D 5
+U 7
+R 6
+L 14
+U 2
+R 8
+D 2
+U 16
+D 12
+R 11
+D 4
+L 8
+U 8
+L 13
+D 5
+R 4
+U 8
+D 15
+R 8
+D 13
+R 16
+U 4
+D 3
+U 5
+D 8
+R 16
+L 13
+U 3
+D 6
+L 9
+R 10
+D 6
+R 16
+D 15
+R 11
+L 8
+D 8
+U 4
+R 16
+D 1
+U 11
+L 15
+R 7
+D 2
+R 1
+D 4
+L 1
+U 15
+D 16
+R 3
+U 10
+D 9
+U 6
+D 15
+R 11
+L 6
+R 2
+U 14
+R 4
+L 15
+R 15
+D 16
+U 9
+D 2
+L 8
+D 15
+R 5
+U 13
+L 15
+D 1
+R 4
+U 14
+D 15
+L 15
+U 13
+R 16
+L 7
+R 4
+D 13
+L 15
+D 3
+L 7
+D 4
+R 12
+D 10
+U 8
+D 6
+L 13
+R 15
+U 12
+L 4
+R 16
+D 1
+R 14
+L 9
+D 13
+U 2
+D 9
+U 16
+L 15
+R 12
+L 14
+R 6
+D 1
+R 2
+L 15
+U 7
+L 16
+U 15
+D 11
+R 11
+L 3
+R 11
+L 15
+U 17
+L 14
+R 4
+U 15
+D 6
+L 2
+R 7
+L 16
+U 4
+L 14
+U 9
+L 7
+D 16
+R 4
+D 2
+R 15
+L 6
+R 6
+D 1
+U 5
+D 14
+U 4
+D 11
+R 5
+U 16
+L 3
+D 7
+R 10
+L 3
+D 8
+L 10
+U 1
+D 16
+L 6
+R 6
+L 14
+R 6
+U 11
+L 17
+D 7
+R 2
+L 12
+D 15
+U 16
+R 2
+U 3
+R 16
+U 12
+L 3
+U 5
+D 1
+R 12
+U 17
+D 11
+L 16
+U 13
+L 5
+D 1
+R 2
+L 10
+U 12
+D 7
+U 6
+R 4
+U 5
+L 3
+R 16
+D 1
+U 14
+R 15
+D 6
+U 14
+R 4
+L 6
+D 11
+R 16
+L 15
+U 7
+L 10
+R 5
+L 15
+R 12
+L 17
+U 5
+D 14
+L 6
+R 2
+U 5
+R 10
+L 8
+D 2
+U 17
+L 13
+D 17
+L 5
+R 11
+L 3
+U 11
+R 1
+L 3
+D 1
+L 7
+D 14
+R 13
+U 9
+D 7
+L 15
+U 5
+D 4
+R 7
+L 10
+D 6
+R 18
+U 5
+R 18
+U 6
+D 17
+U 8
+R 16
+D 12
+R 12
+D 9
+R 9
+U 4
+R 16
+L 1
+D 12
+L 12
+R 11
+D 15
+U 13
+L 8
+R 4
+L 1
+R 1
+D 11
+R 15
+D 3
+L 17
+D 17
+R 11
+U 13
+D 11
+R 4
+D 17
+U 8
+L 1
+D 2
+L 16
+D 6
+L 15
+D 17
+L 8
+U 5
+D 15
+L 15
+U 11
+D 9
+L 18
+U 18
+R 14
+L 4
+U 17
+R 11
+D 18
+U 2
+R 9
+D 15
+R 5
+L 13
+R 2
+L 18
+D 5
+U 14
+L 17
+R 3
+U 4
+R 15
+U 1
+D 15
+U 12
+D 17
+U 11
+L 3
+R 10
+U 13
+R 12
+L 10
+R 1
+D 4
+U 2
+D 14
+R 14
+U 5
+R 16
+U 17
+R 16
+U 18
+R 6
+U 5
+R 18
+U 12
+D 7
+R 9
+L 1
+U 15
+D 10
+L 4
+U 9
+L 3
+U 1
+R 12
+D 14
+U 13
+L 10
+R 8
+U 5
+D 7
+U 1
+L 13
+U 14
+D 18
+L 13
+D 12
+R 2
+L 6
+D 17
+L 18
+R 6
+U 4
+L 7
+R 8
+U 5
+D 1
+L 3
+U 10
+R 5
+D 7
+U 16
+R 12
+U 8
+L 18
+R 1
+L 11
+D 14
+L 19
+R 15
+U 14
+L 8
+R 14
+U 13
+D 18
+U 14
+L 14
+U 11
+L 10
+D 11
+L 11
+R 15
+L 12
+R 10
+L 9
+R 9
+L 9
+D 3
+R 9
+L 6
+R 8
+D 7
+L 18
+D 12
+R 3
+U 7
+R 18
+U 9
+L 14
+D 12
+L 10
+U 15
+L 11
+R 17
+D 7
+R 5
+L 3
+U 13
+D 7
+U 13
+R 16
+D 2
+L 7
+R 15
+L 14
+U 19
+D 3
+L 19
+D 11
+R 8
+D 6
+U 12
+R 5
+U 6
+L 7
+R 4
+L 3
+D 6
+L 17
+U 16
+D 11
+U 12
+D 4
+R 6
+D 10
+L 3
+D 15
+R 5
+L 6
+D 11
+U 17
+L 14
+D 15
+L 1
+D 6
+R 16
+D 11
+U 2
+D 2
+U 7
+D 10
+L 11
+D 19
+L 12
+D 3
+L 18
+U 3
diff --git a/day9/uppga.c b/day9/uppga.c
@@ -0,0 +1,86 @@
+#include "common.h"
+
+static inline int is_touching(int* hpos, int* tpos) {
+ if(abs(hpos[0]-tpos[0]) > 1 || abs(hpos[1]-tpos[1]) > 1) {
+ return 0;
+ }
+ return 1;
+}
+
+int make_move(int* hpos, int* tpos, char move, smallset* s, int* boundaries)
+{
+ switch(move) {
+ case 'U':
+ hpos[1]++;
+ break;
+ case 'D':
+ hpos[1]--;
+ break;
+ case 'L':
+ hpos[0]--;
+ break;
+ default:
+ hpos[0]++;
+ break;
+ }
+
+ if(!is_touching(hpos, tpos)) {
+ if(hpos[0] == tpos[0]) {
+ if(hpos[1] > tpos[1]) {
+ tpos[1]++;
+ } else {
+ tpos[1]--;
+ }
+ } else if(hpos[1] == tpos[1]) {
+ if(hpos[0] > tpos[0]) {
+ tpos[0]++;
+ } else {
+ tpos[0]--;
+ }
+ } else {
+ if(hpos[0] > tpos[0]) {
+ tpos[0]++;
+ } else {
+ tpos[0]--;
+ }
+ if(hpos[1] > tpos[1]) {
+ tpos[1]++;
+ } else {
+ tpos[1]--;
+ }
+ }
+ }
+
+ smallset_insert(s, diagon(tpos, boundaries));
+ return 0;
+}
+
+int main(int argc, char** argv)
+{
+ char** lines;
+ size_t nlines = readlines(&lines, "input");
+
+ char* dirs = malloc(nlines * sizeof(*dirs));
+ uint64_t* times = malloc(nlines * sizeof(*times));
+ int boundaries[4];
+ parse(boundaries, dirs, times, lines, nlines);
+
+ smallset s;
+ smallset_init(&s, (1 + boundaries[1] - boundaries[0]) * (1 + boundaries[3] - boundaries[2]));
+
+ int hpos[2] = {0,0};
+ int tpos[2] = {0,0};
+
+ size_t i,j;
+ uint64_t jl;
+ for(i = 0; i < nlines; i++) {
+ sread_next_u64(&jl, lines[i]);
+ for(j = 0; j < jl; j++) {
+ make_move(hpos, tpos, lines[i][0], &s, boundaries);
+ }
+ }
+
+ printf("%llu\n", smallset_cardinality(&s));
+
+ smallset_clear(&s);
+}
diff --git a/day9/uppgb.c b/day9/uppgb.c
@@ -0,0 +1,92 @@
+#include "common.h"
+
+static inline int is_touching(int* hpos, int* tpos) {
+ if(abs(hpos[0]-tpos[0]) > 1 || abs(hpos[1]-tpos[1]) > 1) {
+ return 0;
+ }
+ return 1;
+}
+
+int make_move(int* pos, size_t npos, char move, smallset* s, int* boundaries)
+{
+ switch(move) {
+ case 'U':
+ pos[1]++;
+ break;
+ case 'D':
+ pos[1]--;
+ break;
+ case 'L':
+ pos[0]--;
+ break;
+ default:
+ pos[0]++;
+ break;
+ }
+
+ size_t i;
+ for(i = 0; i < 2*npos-2; i += 2) {
+ int* hpos = &pos[i];
+ int* tpos = &pos[i+2];
+ if(!is_touching(hpos, tpos)) {
+ if(hpos[0] == tpos[0]) {
+ if(hpos[1] > tpos[1]) {
+ tpos[1]++;
+ } else {
+ tpos[1]--;
+ }
+ } else if(hpos[1] == tpos[1]) {
+ if(hpos[0] > tpos[0]) {
+ tpos[0]++;
+ } else {
+ tpos[0]--;
+ }
+ } else {
+ if(hpos[0] > tpos[0]) {
+ tpos[0]++;
+ } else {
+ tpos[0]--;
+ }
+ if(hpos[1] > tpos[1]) {
+ tpos[1]++;
+ } else {
+ tpos[1]--;
+ }
+ }
+ }
+ }
+
+ smallset_insert(s, diagon(&pos[2*npos-2], boundaries));
+
+ return 0;
+}
+
+int main(int argc, char** argv)
+{
+ char** lines;
+ size_t nlines = readlines(&lines, "input");
+
+ char* dirs = malloc(nlines * sizeof(*dirs));
+ uint64_t* times = malloc(nlines * sizeof(*times));
+ int boundaries[4];
+ parse(boundaries, dirs, times, lines, nlines);
+
+ smallset s;
+ smallset_init(&s, (1 + boundaries[1] - boundaries[0]) * (1 + boundaries[3] - boundaries[2]));
+
+ size_t npos = 10;
+ int pos[20] = {0};
+
+ size_t i,j;
+ uint64_t jl;
+ for(i = 0; i < nlines; i++) {
+ sread_next_u64(&jl, lines[i]);
+ for(j = 0; j < jl; j++) {
+ make_move(pos, npos, lines[i][0], &s, boundaries);
+ }
+ }
+
+ printf("%llu\n", smallset_cardinality(&s));
+
+ smallset_clear(&s);
+}
diff --git a/py/day19.py b/py/day19.py
@@ -0,0 +1,68 @@
+def affordable(mv, bp, s):
+ if mv == 1: # ore robit
+ return s[4] >= bp[0]
+ elif mv == 2: # clay robot
+ return s[4] >= bp[1]
+ elif mv == 3: # obsidian robot
+ return (s[4] >= bp[2] and s[5] >= bp[3])
+ elif mv == 4: # geo robot
+ return (s[4] >= bp[4] and s[6] >= bp[5])
+ else:
+ assert(mv == 0)
+ return True
+
+def perform(mvs, bp, special):
+ s = [1, 0, 0, 0, 0, 0, 0, 0]
+ i = 0
+ rmin = [9999999999]*4
+ for mv in mvs:
+ if not affordable(mv, bp, s):
+ return i
+ else:
+ s[4] += s[0]
+ s[5] += s[1]
+ s[6] += s[2]
+ s[7] += s[3]
+ if mv == 1:
+ s[0] += 1
+ s[4] -= bp[0]
+ elif mv == 2:
+ s[1] += 1
+ s[4] -= bp[1]
+ elif mv == 3:
+ s[2] += 1
+ s[4] -= bp[2]
+ s[5] -= bp[3]
+ elif mv == 4:
+ s[3] += 1
+ s[4] -= bp[4]
+ s[6] -= bp[5]
+ else:
+ assert(mv == 0)
+ if i >= special:
+ if i == special:
+ special_state = s.copy()
+ if rmin[0] > s[4]:
+ rmin[0] = s[4]
+ if rmin[1] > s[5]:
+ rmin[1] = s[5]
+ if rmin[2] > s[6]:
+ rmin[2] = s[6]
+ if rmin[3] > s[7]:
+ rmin[3] = s[7]
+ i += 1
+ return (special_state, [special_state[4+i] - rmin[i] for i in range(len(rmin))])
+
+def parse_line(line):
+ sl = line.split()
+ return (int(sl[6]), int(sl[12]), int(sl[18]), int(sl[21]), int(sl[27]),int(sl[30]))
+
+bps = []
+f = open("../day19/einput")
+for line in f.readlines():
+ if len(line) > 1:
+ bps.append(parse_line(line))
+
+print(bps)
+
+print(perform([0,0,2,0,0,2], bps[0], 4))
diff --git a/py/day20.py b/py/day20.py
@@ -0,0 +1,67 @@
+import sys
+import numpy as np
+
+sys.setrecursionlimit(15000)
+
+saved_u = None
+
+def u(i, j, s):
+ if saved_u[i,j] != 0xffff:
+ return saved_u[i,j]
+ (n, d, zero_index) = s
+ assert(i >= 0)
+ assert(j >= 0)
+ assert(i <= n)
+ assert(j < n)
+ if i == 0:
+ if j >= zero_index:
+ r = j-zero_index
+ else:
+ r = j+n-zero_index
+ else:
+ ti = (u(i-1, i-1, s) + d[i-1]) % (n-1)
+ if i-1 == j:
+ print("i = {}, ti = {}".format(i, ti))
+ if d[i-1] != 0 and ti == 0:
+ tip = n-1
+ else:
+ tip = ti
+ if i-1 == j:
+ r = tip
+ elif tip <= u(i-1, j, s) < u(i-1, i-1, s):
+ r = u(i-1, j, s) + 1
+ elif u(i-1, i-1, s) < u(i-1, j, s) <= tip:
+ r = u(i-1, j, s) - 1
+ else:
+ r = u(i-1, j, s)
+ saved_u[i, j] = r
+ return r
+
+
+d = []
+f = open("input20", "r")
+for line in f.readlines():
+ if line[-1] == "\n":
+ line = line[:-1]
+ d.append(int(line))
+print(d)
+n = len(d)
+its = 47
+saved_u = np.array([[0xffff]*(n+1)]*(n+1), np.ushort)
+print(saved_u)
+zero_index = d.index(0)
+s = (n, d, zero_index)
+print("n = {}, zero_index = {}".format(n, zero_index))
+
+for i in range(its):
+ for j in range(n):
+ up = u(i,j,s)
+ us = [u(i, j, s) for j in range(n)]
+ js = [x % n for x in [1000, 2000, 3000]]
+ su = sum([d[us.index(j)] for j in js])
+ print(su)
+# print([u(i, j, s) for j in range(n)])
+
+#us = [u(its, j, s) for j in range(n)]
+#js = [x % n for x in [1000, 2000, 3000]]
+#print(sum([d[us.index(j)] for j in js]))
diff --git a/py/einput20 b/py/einput20
@@ -0,0 +1,7 @@
+1
+2
+-3
+3
+-2
+0
+4
diff --git a/py/input20 b/py/input20
@@ -0,0 +1,5000 @@
+-2312
+5492
+793
+-773
+5453
+-2076
+-1728
+-7702
+4318
+8316
+-3366
+-3814
+9182
+-673
+-8201
+7847
+9691
+4044
+802
+-8114
+8944
+-2438
+-3460
+-6923
+-4847
+-7341
+2063
+-9848
+6702
+2560
+6058
+-7669
+7315
+-6427
+5165
+3147
+-1320
+4789
+6296
+-806
+1185
+-1445
+-982
+2759
+-8506
+-5959
+5683
+-6623
+-8571
+-5834
+-9022
+8729
+-7420
+-9812
+-9162
+-240
+7302
+2221
+-4352
+-4248
+5177
+9037
+-6880
+-2117
+9569
+-1037
+726
+2866
+-4587
+3384
+998
+9665
+3982
+3169
+4547
+612
+2857
+-2601
+-982
+-4267
+-740
+2817
+-818
+-8005
+-3697
+497
+-8039
+-116
+8438
+-8460
+2609
+709
+3590
+1323
+2202
+-1246
+-736
+-3992
+7811
+127
+-2609
+8314
+-5668
+-6449
+-6512
+3972
+-5998
+-7462
+4542
+-6350
+8424
+5046
+-3554
+6481
+-4521
+1307
+-172
+-7391
+79
+-179
+-7320
+9750
+-5916
+8531
+5522
+5133
+-1506
+4151
+-2793
+5448
+-2267
+998
+-6216
+3894
+-1297
+7112
+8486
+-6030
+-1815
+-1451
+4165
+828
+8678
+-1751
+-9528
+5056
+-9702
+9288
+8683
+-1924
+-6171
+-7050
+-9968
+-3909
+-9834
+-8325
+-2528
+-2247
+-1075
+6684
+6038
+-6309
+-3562
+2333
+3593
+-18
+-9857
+-4318
+6923
+-5266
+1408
+-7781
+2037
+-519
+4085
+7054
+-4111
+2817
+-5375
+870
+-8252
+4142
+3500
+-9371
+-2040
+-7381
+6216
+7143
+-6814
+673
+3104
+-1693
+6050
+-2416
+7112
+4114
+5367
+4566
+2560
+4361
+4131
+4337
+7876
+-3000
+-8724
+-2088
+6785
+-5326
+-7107
+3739
+-302
+9519
+-5331
+8759
+6867
+-9267
+4816
+-749
+-1980
+1830
+9715
+1634
+-6922
+-288
+4436
+63
+-156
+1185
+-5004
+-9093
+-8661
+8447
+233
+-854
+3154
+-5589
+-5490
+2321
+-1006
+3688
+6313
+4704
+6598
+430
+-7073
+-6571
+-3768
+6203
+8453
+8735
+-4070
+8059
+-4734
+-1827
+1330
+586
+-8858
+1938
+1366
+6031
+3744
+-7191
+8032
+3586
+-3196
+-460
+3032
+2387
+450
+1391
+-3905
+-2774
+6690
+-9103
+8220
+-6594
+8834
+-3559
+-9337
+2199
+-9026
+2904
+-8552
+499
+7727
+6519
+-17
+-3625
+-302
+4611
+9129
+9756
+6869
+-2262
+-4677
+3533
+19
+5877
+5224
+3783
+5992
+-2218
+-5097
+3956
+9335
+-5586
+-9441
+3252
+-4307
+-1111
+6509
+-116
+-4926
+-7394
+1270
+-1773
+6658
+3317
+-8704
+-3692
+6482
+2451
+7241
+-350
+-5042
+-9182
+2602
+9752
+-8475
+-5018
+-267
+-9360
+599
+917
+5210
+4388
+909
+-1063
+8311
+1831
+8235
+-9129
+-7420
+-284
+-1940
+4079
+-7284
+-4893
+4913
+-8602
+-59
+6105
+-4934
+1196
+-6947
+-1508
+-8961
+2112
+-6739
+-8401
+9750
+-3697
+85
+2240
+-5882
+-1900
+3783
+5747
+4388
+5225
+6858
+-3799
+6119
+8592
+-3328
+4716
+-6391
+-7721
+4813
+3223
+6303
+8780
+4400
+-7964
+8810
+8247
+8776
+-5738
+-2655
+-2036
+9906
+-6834
+92
+6695
+1740
+29
+-9758
+-7016
+-8170
+-7780
+4243
+-3391
+2989
+-7678
+2154
+-4515
+4475
+8011
+-3785
+-3518
+5532
+8387
+806
+-9546
+655
+804
+-5420
+4138
+8495
+8975
+-2559
+8202
+8268
+-6923
+1671
+-9892
+6337
+6205
+6024
+6038
+-3289
+4626
+4356
+-3104
+7633
+9404
+-3630
+-4041
+106
+-4493
+3651
+6983
+-5958
+819
+6105
+1910
+4645
+-1293
+-8747
+8655
+-6928
+9025
+1984
+-9959
+-9290
+-7834
+3588
+2967
+3048
+4730
+-8653
+-4434
+6105
+8028
+-4909
+-7865
+-6832
+-1267
+8129
+4131
+-9615
+-7137
+3956
+464
+-588
+5260
+2181
+-3581
+649
+8992
+-6427
+-3292
+-5641
+-8274
+-2283
+-3455
+1417
+7054
+3937
+-1797
+-615
+-2526
+6210
+6222
+-6007
+-3764
+-1743
+-3123
+9495
+8269
+3675
+1085
+-1859
+8578
+-1240
+-4734
+1196
+1332
+-3507
+-6268
+3380
+-6530
+3264
+-4958
+-7533
+8869
+2666
+-6780
+7739
+-4128
+-8229
+9624
+-8005
+-1897
+-9773
+8000
+-419
+269
+5048
+-5962
+4319
+6834
+-9624
+-5247
+-2683
+-9050
+-5335
+5244
+-3052
+929
+-3922
+-4806
+-7085
+4186
+-5127
+7790
+527
+-222
+4043
+9900
+4630
+5056
+-9425
+-2369
+-1442
+-7949
+5228
+7449
+3945
+726
+-1722
+-3439
+-1037
+-4998
+-5130
+5158
+-227
+-8075
+3917
+5228
+9382
+-7582
+787
+-2895
+-7385
+9750
+-8872
+-1263
+5877
+4398
+9200
+4061
+8059
+9960
+5756
+-3241
+-2283
+9568
+-5852
+-3630
+-2336
+-3596
+4649
+-7203
+4473
+-8025
+-9991
+-8721
+1307
+-5487
+4632
+1799
+2468
+2834
+2571
+-3894
+7319
+8466
+-7831
+-7428
+5475
+6296
+9191
+6193
+-843
+8566
+9398
+7317
+-3984
+-1886
+-5012
+4014
+-3554
+6002
+-5254
+8412
+-4059
+7761
+-7363
+9025
+-1960
+1905
+-304
+-2877
+7707
+-3120
+8969
+-545
+-9237
+885
+3830
+7085
+-8779
+9198
+4123
+517
+480
+-6380
+9713
+-2029
+-947
+-5205
+-9126
+-4653
+5254
+3153
+2067
+7872
+-3545
+1864
+9068
+4516
+6440
+-9167
+4281
+4859
+-6318
+-3155
+8699
+-5310
+-38
+-4889
+-1805
+-9405
+-1235
+3285
+1579
+1265
+-850
+259
+1513
+-1490
+7916
+-9000
+-7515
+2756
+831
+2387
+-6922
+-6299
+8992
+3336
+4473
+1728
+1366
+-2893
+-8891
+7818
+-3140
+2972
+1088
+2718
+9495
+64
+7527
+8638
+-8670
+6740
+-2971
+1849
+5365
+7997
+2941
+5528
+8065
+6973
+-5858
+1355
+6359
+-7757
+-3968
+-1985
+-3194
+1425
+-6928
+4616
+-1912
+-5892
+-9337
+-4007
+-1299
+5042
+3825
+-5517
+5056
+-9180
+-4646
+-843
+6038
+7750
+-7705
+1294
+8809
+6888
+-1634
+-8823
+-2995
+-7983
+-7333
+-7315
+2240
+-4881
+497
+-4026
+-6921
+714
+4513
+-2134
+-4600
+-4863
+7388
+-6344
+-8589
+9381
+-7674
+-9967
+-9237
+2679
+-8598
+-6741
+7739
+-7720
+-1899
+-5265
+-5665
+-2580
+-8820
+8550
+9121
+-1218
+8832
+-1776
+-4814
+-1570
+-7969
+-6529
+8232
+-4867
+-638
+-1263
+3918
+8720
+-6378
+-7501
+3894
+-663
+3894
+1264
+555
+-1139
+9538
+-7029
+4909
+1751
+-6800
+7761
+6810
+6708
+-3571
+7994
+9707
+5187
+-3084
+5458
+-5274
+-8246
+5730
+2425
+7931
+-6800
+-6008
+-2705
+-5151
+-6268
+-1054
+6176
+-6809
+7683
+-4342
+-7797
+-6430
+4127
+-3148
+7294
+6188
+8729
+3463
+3375
+5648
+788
+3996
+7650
+8952
+-7078
+-8155
+-6166
+-3726
+-2742
+3845
+1103
+-5164
+6507
+-2219
+4131
+9421
+-8277
+7068
+-8046
+833
+-684
+-6160
+-8604
+-6384
+-2081
+940
+3239
+1962
+3502
+3576
+-3320
+-335
+5644
+-200
+823
+8320
+-7803
+6209
+-7565
+1042
+769
+-5705
+7494
+-4419
+5726
+5198
+-6879
+3377
+-6890
+-6072
+-3633
+-100
+-8584
+2961
+-5839
+8191
+9055
+-5330
+-3082
+-8589
+-7126
+-9861
+7624
+8486
+-272
+-1092
+-3047
+9349
+6014
+8554
+-2986
+1425
+-2615
+-1855
+5442
+-8509
+9775
+-8855
+6313
+-8060
+-102
+8809
+2374
+5400
+7789
+-6100
+-1473
+-916
+-6715
+-1828
+-5649
+6314
+-1946
+-895
+8774
+5894
+-8284
+3825
+8737
+500
+-1468
+2542
+-7925
+7775
+9221
+-2916
+-9878
+-6427
+9800
+-468
+-8699
+9798
+9424
+8910
+8582
+-8806
+-4157
+8620
+-5136
+-952
+-9019
+-6947
+-601
+-5789
+-9535
+6028
+-8930
+8466
+-5689
+3254
+-4709
+4394
+2281
+3362
+2813
+-5808
+3420
+6002
+-9398
+9653
+5728
+9204
+-4846
+-7691
+-8087
+6772
+-451
+-2286
+2826
+5945
+-7702
+9713
+5468
+4660
+672
+-1854
+-3970
+1905
+3685
+6425
+5102
+-7462
+1913
+6360
+-8581
+6604
+9384
+9117
+2574
+4436
+-6263
+8516
+-2059
+6378
+-6492
+4242
+-9681
+-6126
+436
+5520
+9528
+3885
+1227
+-8501
+1230
+-6933
+-5230
+-9432
+-1313
+-2136
+-1379
+1439
+-2864
+2839
+3340
+-226
+-4206
+9121
+-9572
+8567
+-8298
+7244
+9526
+-8506
+-7922
+-901
+-523
+-6310
+2811
+2324
+-7384
+8812
+-916
+2580
+-2966
+9885
+-3400
+-6277
+-5818
+-663
+-7179
+7344
+6022
+2865
+-676
+1375
+8622
+1965
+-9990
+-4255
+5796
+-3903
+8008
+-78
+-4997
+-460
+8437
+-6563
+-5517
+-1827
+6257
+-5413
+-6169
+6869
+5890
+9791
+5425
+-7310
+7249
+1175
+4417
+-527
+4115
+-834
+9427
+6924
+731
+-1537
+-4632
+-1218
+3677
+-8488
+-946
+-5430
+580
+4976
+5132
+8448
+-3109
+4014
+-4493
+-5671
+6507
+3688
+-9214
+-2641
+3508
+7581
+-9640
+-2308
+3598
+4940
+-3843
+-7364
+-1693
+2367
+2589
+9435
+-7914
+-5655
+7388
+379
+6022
+1899
+2607
+-6226
+8992
+1231
+-8751
+-4158
+1888
+-2145
+-5874
+-5713
+-9526
+1060
+-3324
+-834
+8534
+-1807
+9906
+1217
+9946
+1892
+8556
+6182
+-2868
+7988
+-1555
+-9400
+2212
+1311
+6349
+-9405
+3703
+9120
+5284
+4672
+-8397
+-7984
+-5319
+-7955
+-1570
+6475
+-2479
+266
+-3865
+3550
+1313
+5476
+3052
+9659
+2696
+-8760
+6568
+-5512
+-4938
+7835
+-6933
+1821
+5033
+3504
+7070
+-2016
+1147
+-2652
+-4622
+-4126
+-9118
+6462
+1563
+3285
+8275
+-8593
+-4833
+-1318
+-6620
+-2818
+4893
+5076
+356
+-4435
+6210
+9037
+6929
+-6950
+-6710
+-1735
+3541
+-5278
+-1451
+8176
+885
+-9108
+-2591
+-1165
+660
+2387
+1829
+3490
+3048
+7244
+-6423
+3571
+-5055
+-1272
+-84
+6388
+2320
+-4569
+2382
+5900
+-7482
+7915
+5668
+9089
+9963
+-6007
+6337
+-5863
+-6139
+-1803
+-1863
+8283
+-8654
+-7952
+-6938
+-5541
+484
+-8487
+-3356
+-2433
+-9859
+-1960
+7112
+8010
+-7200
+9261
+5926
+-2610
+-7854
+6988
+-4258
+-9209
+-3029
+6578
+-1779
+-6575
+9899
+4561
+7564
+-6399
+-7750
+-1276
+-1242
+9793
+-1650
+400
+-4830
+-9533
+6806
+2157
+-5517
+-9506
+-1925
+-519
+5650
+-8327
+4683
+788
+7457
+-4476
+6695
+-4255
+7292
+760
+-8423
+1603
+-4258
+6097
+-567
+5582
+1323
+-3113
+9303
+-3025
+-8242
+6039
+8692
+2309
+-5558
+-916
+-7193
+5906
+-9774
+8231
+491
+8404
+-9325
+-9261
+4790
+-5419
+4394
+-2174
+-8130
+6327
+7412
+6495
+-5814
+6741
+-6791
+9147
+-828
+-619
+1841
+1120
+-9057
+123
+430
+-3828
+6360
+5831
+-5059
+-7599
+-6946
+-9640
+4733
+2834
+524
+-5316
+8832
+-1566
+-5477
+-4370
+1991
+6716
+8755
+-3455
+7821
+-90
+-8899
+-7101
+1785
+-2925
+1299
+9571
+-8319
+8304
+-1690
+-6509
+-5792
+4825
+6801
+-1638
+-4783
+4784
+-5668
+4170
+7228
+-2326
+9793
+-4041
+-9295
+7134
+-4845
+528
+3199
+-1632
+3372
+-5856
+-2582
+7039
+-7775
+-6401
+5747
+-6986
+2608
+5091
+-8261
+-8431
+-1591
+-6165
+4835
+6467
+312
+9873
+-6425
+-9224
+1633
+8856
+5961
+-4968
+8583
+-268
+-6396
+6791
+8721
+-2141
+-2248
+-9119
+4338
+-9103
+-3693
+-706
+-975
+3854
+-1136
+8930
+6511
+-445
+917
+-1024
+-3782
+8406
+2624
+-9544
+-4830
+-5255
+-9561
+-2948
+-1011
+9056
+8291
+3320
+-5316
+1148
+-8261
+1330
+-2145
+-9226
+-1257
+1905
+-3227
+-6728
+-6107
+7278
+-9645
+879
+-3758
+4980
+-7956
+6640
+4053
+-7842
+-6749
+363
+-6904
+-3055
+-768
+7220
+-5118
+6750
+7737
+-3422
+6328
+4844
+-2690
+1113
+-7072
+3528
+-4331
+-5164
+-4056
+-4821
+-982
+2502
+7885
+-8553
+9740
+5105
+-5824
+2693
+5459
+2462
+-3001
+9783
+6766
+-9286
+-6516
+2307
+-908
+-1325
+904
+-84
+-1526
+278
+7384
+655
+-4468
+1264
+4952
+-5002
+5700
+-9261
+-966
+-438
+-466
+-3756
+-9867
+-2088
+4125
+1930
+9294
+-1243
+-5604
+-2422
+-2385
+9296
+9426
+6767
+-6467
+8846
+-1315
+7568
+4391
+85
+-2167
+-9427
+-6613
+-2586
+2008
+4540
+9421
+-7046
+8466
+-2939
+6699
+-8174
+3384
+-2700
+3199
+-4011
+-8991
+-1129
+2216
+8273
+7977
+-3962
+-2334
+-2747
+7765
+1765
+-4471
+1863
+-6768
+-7752
+-5945
+8593
+-2225
+2550
+9650
+8842
+465
+6133
+-952
+7479
+5645
+4520
+-8873
+4429
+9857
+-4567
+-124
+6193
+-7916
+-1299
+1811
+-5195
+8974
+-8604
+6126
+-7579
+-7828
+8882
+-5002
+-6102
+3891
+-589
+-5697
+7519
+-1335
+-311
+-6777
+5704
+1962
+-4950
+9814
+5400
+610
+-2093
+7898
+-6492
+-1165
+-1063
+1658
+-7184
+-3384
+5101
+4733
+1231
+9255
+-712
+4122
+4402
+5443
+3877
+7541
+4473
+-3633
+-9959
+9260
+9177
+1788
+-5986
+-5165
+8969
+6031
+741
+-7417
+7002
+6992
+-4374
+-8995
+2832
+2250
+2221
+-2791
+-2287
+-9125
+-1692
+4930
+-443
+4349
+-8602
+3553
+9117
+8304
+209
+6650
+745
+1058
+-3994
+-7437
+8476
+-7390
+-6864
+2467
+1798
+-292
+-6487
+2954
+-3029
+1192
+-1955
+4256
+5615
+4335
+7948
+-7963
+-831
+8499
+-1778
+5063
+2069
+610
+6032
+1447
+6898
+2154
+-6397
+7996
+-7809
+-3279
+6789
+7245
+8794
+-7078
+-1434
+-3953
+-3029
+7262
+-4640
+4742
+-1063
+7790
+2320
+-1721
+6128
+-4219
+7482
+3385
+-2949
+-6830
+-1522
+-3530
+-9002
+-4798
+7347
+7847
+-8651
+9432
+1612
+-5705
+-9216
+-5384
+-2064
+7739
+7113
+6250
+7192
+2927
+7901
+-2990
+-736
+3892
+-2641
+7870
+5061
+4500
+278
+3569
+5059
+-8721
+9991
+1219
+-1289
+-6273
+-8618
+-9085
+6235
+-7551
+-2850
+-7188
+-9828
+2381
+-1298
+-5671
+-2114
+-3312
+-5589
+-394
+8484
+-4008
+3378
+-9841
+-3357
+6888
+4421
+-5959
+-2719
+-5031
+1945
+5058
+1732
+8774
+-9907
+9240
+3189
+-8103
+8526
+-7588
+6113
+-9506
+1096
+-7420
+5688
+-3131
+-8204
+4321
+1860
+-3439
+5902
+5484
+-7310
+7544
+-9184
+3579
+-8311
+9400
+-2046
+3613
+2834
+-3828
+4483
+-3687
+2474
+9175
+5682
+2134
+8178
+4669
+-8999
+4089
+3745
+6187
+-3255
+4496
+-4086
+-5667
+-4719
+-9530
+57
+-5557
+-1809
+4683
+-6874
+9649
+238
+-5274
+2548
+-1610
+2406
+6760
+3829
+-6658
+-7076
+-8907
+-8252
+4473
+-6559
+9751
+9946
+-1815
+-4719
+6440
+-3154
+-4584
+-8861
+5988
+-6730
+5975
+-6449
+3127
+6406
+7501
+-4504
+-5805
+-8832
+3352
+-3961
+-3453
+9800
+-8757
+-9250
+5575
+-1894
+-1130
+2529
+2060
+819
+8152
+-6329
+-6967
+-451
+-3261
+1670
+4090
+-6879
+-638
+-5435
+2187
+3891
+5504
+4337
+3137
+-9570
+2350
+9955
+5628
+8522
+-165
+-7442
+-5330
+8494
+-8458
+5667
+-3922
+-5440
+-7066
+7265
+-8704
+490
+-5609
+-768
+1537
+-7702
+5884
+-1198
+4784
+1935
+-9959
+3985
+-1213
+-518
+-7078
+-9683
+-4973
+-2189
+9598
+-4616
+7220
+3335
+8211
+7294
+-5295
+4813
+-3329
+2697
+5383
+-2611
+4052
+-9056
+5442
+-5822
+8230
+2860
+2797
+2893
+1320
+7805
+9598
+-6575
+1307
+-3383
+7434
+7853
+-6166
+2096
+-2921
+-8558
+2689
+-2719
+9225
+-2812
+-7176
+6243
+-7995
+-7186
+8770
+-953
+-3986
+9430
+-9280
+5951
+254
+9268
+1664
+6491
+8121
+-6876
+2805
+-265
+8954
+5634
+-4938
+-6880
+7449
+-9839
+6036
+4772
+-5325
+3763
+-3455
+-8766
+1458
+-605
+-6746
+7846
+-8180
+8340
+9269
+7054
+-5084
+-98
+9491
+2893
+-8571
+3179
+2972
+-9473
+1502
+9398
+-621
+1562
+-1657
+1670
+9896
+7344
+-9187
+-2085
+-2781
+342
+-9159
+6214
+802
+-2429
+-7600
+4489
+-7485
+-4674
+2709
+-446
+-8240
+9394
+8159
+-4058
+5910
+-1281
+9760
+-6626
+5440
+4697
+-5100
+6509
+4256
+-4904
+244
+1154
+-7067
+-4251
+-4759
+5617
+-8546
+8747
+5770
+-4909
+1447
+612
+-8622
+2866
+-2947
+-1800
+-8985
+-3800
+-6839
+-1256
+-8119
+6427
+8187
+-4392
+-2980
+-7103
+-2337
+5830
+-3644
+4052
+4591
+-2181
+6072
+6905
+5783
+-3905
+-9064
+-3083
+4615
+-3437
+1133
+3153
+-1922
+-4065
+-8069
+-6436
+7889
+4440
+-7021
+-638
+-5127
+8977
+2839
+6777
+7054
+-5443
+3666
+-9640
+-1863
+-2244
+-8397
+6744
+9748
+5783
+7727
+-6548
+7052
+-4846
+-7240
+8565
+-6165
+-9038
+2975
+-6850
+-8567
+-7842
+4297
+-474
+-5606
+-4723
+-203
+-4902
+6313
+92
+-784
+-5997
+-2915
+-6920
+-8873
+-5885
+85
+-3035
+8715
+3763
+-4255
+6210
+5214
+3284
+-5662
+-585
+2621
+3569
+8826
+-9532
+-9323
+1430
+159
+-1831
+-373
+-5837
+-6559
+2129
+-6731
+2932
+-9463
+7930
+-5585
+9567
+2601
+-6215
+-4804
+9927
+-8269
+-9660
+6692
+7859
+855
+-3444
+-545
+-1924
+3776
+6273
+7774
+400
+5129
+6999
+-8423
+-243
+8011
+7236
+-555
+9279
+2752
+4931
+4728
+8293
+6421
+4497
+3458
+-8929
+9792
+-1333
+-4216
+1379
+-6254
+8851
+9346
+8174
+5712
+1899
+4115
+4437
+-7151
+6917
+9104
+-5838
+-1454
+779
+8637
+7494
+-7076
+7365
+3931
+-2719
+8075
+-5323
+-7745
+9761
+-5792
+5746
+5575
+9704
+-9334
+-8704
+9364
+-4196
+4914
+3552
+-6741
+-7272
+3199
+6427
+-3097
+-2195
+-3535
+-5885
+-7161
+-4290
+-5912
+5957
+9337
+-6472
+9037
+5573
+2384
+2474
+5497
+5889
+-9663
+-5332
+5913
+-48
+3398
+6039
+-1025
+4567
+-1689
+-7643
+8403
+6422
+2666
+4681
+7571
+9306
+-4140
+8668
+5961
+1728
+9600
+4567
+-9947
+7947
+2311
+7683
+4036
+-9118
+-1440
+7701
+-718
+7252
+-5748
+8074
+9077
+1430
+309
+7223
+7241
+6924
+-1726
+2580
+323
+9592
+-147
+9734
+-6509
+-2141
+9899
+8912
+-9095
+-1534
+-1722
+-6731
+-4674
+-5668
+9543
+2181
+-5971
+-4285
+-5435
+8785
+6022
+3483
+3442
+-4311
+-9718
+491
+-234
+-6505
+-2233
+1054
+1843
+-8170
+3725
+9367
+-9708
+2884
+575
+1466
+-4904
+-7163
+-6509
+-9898
+-1035
+4218
+-3782
+-7972
+4094
+-4022
+7344
+3528
+6745
+-8677
+-564
+599
+-1588
+-638
+-2547
+7384
+-3223
+-8978
+-3131
+2367
+38
+4294
+2227
+-4687
+-8416
+-7749
+-901
+5156
+5381
+7208
+9451
+-1072
+-6165
+4274
+-9330
+-5692
+-976
+8507
+-4214
+3267
+-693
+4016
+-4859
+4131
+2624
+-2195
+-5747
+-3433
+-5309
+4909
+-1789
+1970
+1113
+6654
+9294
+580
+2701
+-3072
+-1058
+-450
+-3553
+8842
+-6902
+5849
+-8210
+3129
+-4568
+7319
+9289
+1953
+-2772
+3176
+7831
+-5215
+-7078
+-269
+-9613
+-5990
+140
+-3349
+-1868
+-6378
+7029
+3786
+9495
+4946
+-3908
+5746
+7246
+6543
+3375
+-6525
+3179
+4829
+-5690
+-4458
+-5067
+3563
+-9505
+8886
+-6046
+8975
+-9892
+4232
+-3386
+6748
+5560
+-5068
+-4307
+8256
+-4803
+6559
+-726
+7262
+3603
+-6032
+-1753
+1072
+-3515
+1160
+-4265
+8809
+7319
+-2341
+-4621
+-5593
+4672
+-7252
+7876
+-2824
+-2708
+151
+6484
+2609
+2708
+-9044
+-7454
+4473
+-3075
+-5664
+1659
+9212
+-8951
+-3382
+8762
+7569
+-2142
+-3045
+-7361
+110
+6810
+1104
+-373
+-4500
+-9051
+-3242
+2221
+5025
+-4297
+-6710
+7853
+-6452
+7998
+-9213
+-7520
+-6727
+5334
+1096
+678
+-4395
+7679
+-4022
+6257
+-3939
+9591
+8016
+-4342
+8010
+5402
+1423
+8834
+6389
+9001
+5102
+3868
+-7905
+8265
+-2083
+6772
+-8806
+-1136
+-5612
+-5127
+-7981
+-5655
+480
+-3419
+368
+-2090
+5293
+7052
+4686
+3386
+-708
+3991
+-684
+-2381
+4228
+-9954
+-9993
+4285
+-6467
+6787
+-3366
+-4653
+-3731
+-4257
+-1246
+3925
+2320
+1536
+-3196
+-1374
+-5465
+-7690
+-716
+1929
+859
+3442
+3500
+-6460
+7761
+5628
+-4119
+4069
+9037
+105
+9498
+8235
+-2437
+3472
+-5420
+-6518
+3972
+-7627
+-8503
+6050
+4393
+-8440
+1986
+2187
+-5589
+2686
+3888
+-9356
+-543
+2822
+5302
+-7034
+-7778
+9334
+-5462
+-267
+-6891
+-2707
+7407
+8805
+7388
+6184
+3346
+6847
+-5971
+-417
+-3326
+-1592
+5544
+-6800
+7034
+-5441
+-9441
+-6987
+1815
+5783
+6926
+-4314
+-9892
+-1500
+2904
+-1946
+-9074
+-7659
+-4333
+-3553
+-916
+3237
+-7151
+-6030
+-8337
+418
+-9384
+1192
+2558
+7496
+-7729
+8273
+9305
+3827
+7519
+2133
+1879
+1001
+258
+-3963
+119
+4186
+5239
+-7204
+7704
+9534
+-8682
+-4772
+-7978
+5929
+6107
+506
+1760
+5782
+5895
+-3687
+-78
+-7125
+-534
+-4774
+6218
+9585
+8200
+-5340
+-9302
+3559
+8846
+3552
+1671
+-5477
+-9118
+7790
+-3757
+8365
+7394
+8465
+7245
+3956
+-592
+2205
+-5882
+6476
+-5732
+-6477
+6713
+4709
+4714
+7356
+-1080
+-983
+-9975
+-8190
+-7574
+828
+-6316
+3515
+451
+1098
+5400
+238
+480
+-5998
+-4376
+1974
+9915
+-7151
+-128
+-5130
+-4423
+8491
+3122
+7110
+-9930
+-7341
+-1882
+-3439
+8231
+1407
+-6444
+-4772
+-8872
+-2853
+8031
+6313
+-9629
+4347
+-5487
+-1799
+-1225
+8026
+6920
+4427
+3467
+-2158
+909
+8977
+-5982
+3825
+-718
+7908
+4464
+-1220
+693
+8293
+-8873
+5243
+3511
+8604
+-5990
+-4492
+-4091
+5688
+1240
+664
+3712
+3048
+-9240
+-5267
+247
+-2010
+5327
+-2030
+8030
+-5240
+-3302
+480
+4323
+-8323
+-4590
+2769
+8506
+-1556
+-1827
+-6216
+-4879
+-156
+-1447
+5967
+-1840
+-5838
+7409
+8444
+-5008
+-7949
+6069
+284
+-9103
+-8612
+797
+5615
+-2375
+-9861
+2789
+5978
+-59
+4821
+7116
+4054
+2816
+-8543
+-1099
+9062
+5718
+9635
+6353
+-3312
+1227
+2144
+5770
+9824
+-2918
+-7958
+4640
+1036
+7693
+-951
+5293
+-4364
+6883
+-4395
+7615
+1097
+8269
+-9907
+5813
+-5369
+4001
+-4965
+-4567
+8939
+-145
+3003
+-6977
+8293
+1299
+9247
+-2988
+7170
+6638
+431
+-8887
+3279
+-946
+-4148
+6039
+2067
+-282
+-71
+8031
+425
+-6890
+878
+-1532
+820
+-8918
+-5336
+1989
+-7692
+-1915
+-684
+7818
+254
+7294
+7865
+4192
+-6782
+-6593
+-9534
+-6708
+7805
+-6548
+-5502
+-6471
+-3453
+-736
+-60
+450
+-2995
+4978
+3135
+1408
+7241
+-4262
+-1352
+1200
+5332
+-3276
+-8900
+3210
+317
+1659
+-8895
+-68
+1728
+7241
+-5572
+8605
+2181
+7379
+5184
+3720
+-7081
+-906
+8125
+-4793
+-387
+-9056
+-6572
+5129
+9554
+-206
+3680
+-1500
+8300
+9128
+-6752
+1001
+8338
+-2893
+3567
+314
+4180
+-7983
+5575
+4745
+-302
+5910
+5877
+9130
+-4624
+490
+-6477
+508
+-2262
+5063
+9995
+5492
+-8571
+-2076
+-7245
+7531
+-4395
+5668
+-8525
+9198
+5457
+5282
+-9627
+-8023
+-4275
+-6099
+-9415
+5771
+3678
+-6865
+417
+-1681
+-9044
+8269
+610
+-7461
+-7621
+-4022
+5225
+-4529
+9988
+-2569
+9810
+1996
+1283
+9364
+-7877
+6015
+-7076
+-352
+-9273
+-3114
+-9044
+8524
+1634
+6057
+-5687
+1947
+4940
+2461
+-5043
+-4571
+-5986
+4391
+-9838
+6912
+-5398
+-318
+-5024
+1465
+3817
+8656
+4389
+-4034
+4052
+7988
+-8598
+9693
+7317
+4356
+783
+-5211
+-1854
+3219
+-3521
+-6814
+-4709
+6055
+1394
+-10
+3384
+403
+9590
+4927
+1524
+1098
+-9975
+9585
+6222
+499
+148
+-5770
+-4801
+-8148
+-7928
+3359
+-7612
+3226
+-4709
+1527
+-2568
+-5296
+3739
+-9003
+-806
+1984
+2059
+7955
+7818
+5364
+793
+6822
+3946
+151
+-9630
+9630
+2324
+662
+3333
+-8448
+6754
+437
+-2029
+-4255
+6568
+8500
+-3622
+810
+9004
+8653
+1164
+-8115
+-1858
+-2642
+611
+-7246
+-8085
+-6299
+-4599
+5226
+-4384
+-1024
+-4938
+-1431
+-6083
+2496
+6922
+4660
+1912
+-8991
+-8297
+-6895
+-9607
+1696
+6072
+-3326
+-5078
+1355
+7649
+1118
+-3072
+-5738
+-4741
+3892
+-647
+-6566
+-2195
+3768
+-1397
+-4046
+-3118
+-8531
+4909
+-6367
+5292
+-3083
+151
+-591
+3367
+-8325
+6439
+-6505
+-7330
+2456
+8503
+-5579
+5852
+-7902
+-667
+-3492
+-6341
+7979
+8307
+-29
+-8265
+-2614
+-4590
+-7186
+-3785
+-3744
+3300
+5701
+3678
+-2580
+527
+-120
+-7978
+-5319
+7443
+-5475
+-1506
+-7191
+-9281
+-7356
+-2628
+7251
+-1997
+3924
+-5266
+-8651
+9217
+5305
+9111
+-2939
+7519
+-8554
+-5596
+-3718
+-9826
+5615
+-3270
+7568
+-901
+-7112
+-7598
+7930
+-1075
+2380
+-9192
+-9157
+-9773
+-9061
+-4003
+2896
+4243
+7496
+3191
+4741
+9293
+-8230
+9568
+5013
+-7046
+-9040
+-3302
+2822
+-3767
+-6571
+2286
+9978
+-5369
+-3987
+321
+-9841
+-9334
+-4786
+1332
+2154
+350
+-1841
+-397
+238
+-1815
+-8499
+-4930
+8627
+3968
+1148
+-2153
+-4273
+279
+119
+-3390
+-4077
+-7011
+-2595
+140
+7960
+-6277
+6223
+4957
+-3939
+6988
+-5028
+-9901
+1603
+-5892
+-775
+-9280
+3171
+-1522
+5108
+4891
+3685
+4661
+-7643
+-552
+8337
+-5832
+8644
+3003
+-9386
+6223
+8612
+787
+-3622
+9641
+3003
+-9341
+-7802
+9602
+-3767
+-8598
+7949
+723
+-4998
+-6073
+-5646
+4880
+-2046
+7167
+1100
+6188
+-2993
+5320
+-4615
+-5113
+2264
+6658
+1364
+8910
+-8873
+-9623
+-1256
+5575
+7718
+-8815
+-8254
+4073
+2488
+-7385
+-9406
+-1283
+-2330
+439
+-2260
+-3460
+-1411
+1800
+-1868
+8900
+2905
+-7883
+-8724
+-6531
+7876
+6834
+9389
+8247
+-1522
+-2524
+7145
+-8339
+5056
+7401
+-8273
+3776
+-6665
+8064
+8148
+2243
+-7815
+1924
+-3212
+-6806
+4323
+904
+-4695
+9209
+-6907
+1291
+1529
+-4561
+-7375
+-1211
+2558
+-2141
+5043
+6989
+-5202
+-2176
+-5916
+2884
+-6187
+-3430
+-2237
+-1213
+5977
+-6300
+3245
+8531
+-4257
+-9381
+802
+-78
+-4860
+7008
+-4722
+1110
+9955
+3907
+1910
+8930
+-2195
+-3785
+5610
+5135
+3491
+7948
+3403
+-338
+1694
+-8961
+-3504
+-8033
+-9811
+6823
+6748
+8362
+-5673
+5260
+5914
+-809
+4578
+-2719
+2755
+-42
+1258
+1601
+767
+-347
+7552
+4349
+5549
+-9012
+-4066
+-3864
+6657
+-4258
+7015
+5905
+3870
+-7769
+3896
+3956
+1996
+8506
+-1060
+-5314
+6853
+-7459
+-5834
+-9179
+9981
+-5594
+3705
+-799
+1788
+6874
+-4405
+2345
+-5994
+-9878
+425
+3474
+323
+-4786
+-7819
+-5507
+-8999
+1683
+-5020
+-8423
+-9015
+-1037
+909
+-1304
+9494
+-4815
+7341
+2170
+4724
+-9026
+-5085
+-4041
+-4282
+8747
+2902
+5352
+3576
+-8931
+1536
+-8880
+376
+6995
+1446
+2811
+4310
+9204
+-6879
+-9143
+-78
+-2334
+5345
+3317
+-9839
+-8793
+-833
+4699
+-2420
+-3265
+-8066
+3885
+-7660
+-7341
+13
+8711
+-2510
+-8420
+-3856
+9808
+1921
+-2644
+-6183
+-6786
+7739
+4036
+-5541
+-9182
+4427
+7008
+-4938
+-228
+-3505
+7569
+1683
+5763
+-728
+2236
+-943
+5351
+-8467
+101
+-7916
+-9075
+1983
+-8025
+5674
+9528
+-2621
+6098
+8770
+4600
+6519
+-8724
+-3047
+6462
+5293
+-9484
+8464
+106
+-2368
+-2455
+9659
+-3489
+8326
+7198
+5617
+-1513
+-2437
+3380
+7835
+-517
+-4778
+-6895
+-7224
+3200
+2324
+4704
+-7740
+4029
+-4071
+723
+3889
+-5732
+-1338
+-7655
+9258
+-4148
+-8233
+4544
+804
+9968
+-6880
+5772
+-6405
+3637
+2752
+-5041
+6317
+1884
+-2007
+-2908
+-8629
+-5600
+9867
+-421
+-6378
+-5810
+7684
+3456
+-7571
+-9877
+-5828
+-2763
+9288
+491
+8692
+-5648
+4501
+-4434
+-569
+-3339
+1118
+-961
+516
+5412
+-9462
+8219
+2882
+7319
+-4920
+-7027
+-3528
+1097
+4900
+8282
+4135
+4658
+8008
+-8843
+9656
+7044
+-3992
+-5136
+-3968
+-4330
+-3265
+9567
+-2542
+497
+-5318
+-18
+-6056
+-3651
+9104
+-6477
+-2719
+5268
+5570
+703
+8809
+-4719
+7949
+-2175
+3009
+6939
+9709
+4264
+-7758
+5746
+-9630
+4579
+4909
+3571
+8199
+8743
+6349
+-5785
+1889
+1893
+4256
+-2987
+4089
+2112
+-4104
+1333
+-3443
+-7134
+77
+4963
+4908
+-9050
+-7842
+7564
+-9229
+-6378
+2975
+-7823
+6418
+269
+522
+-6300
+6174
+7005
+-5378
+-7981
+-9356
+-9072
+2569
+8999
+-6390
+-5935
+-5057
+2360
+-8700
+-3348
+-90
+3191
+1789
+-8654
+7768
+-6404
+-8873
+-6821
+4562
+1085
+4429
+-9579
+-7957
+7294
+-427
+-7934
+2968
+1508
+-6905
+-5993
+-1688
+-8417
+1780
+9540
+-4450
+1536
+5184
+8111
+9877
+3466
+2279
+-5254
+-6850
+6936
+-5318
+-7691
+-6390
+5400
+6108
+8351
+-9275
+-6229
+-5441
+-9950
+-5475
+1480
+5686
+-8082
+-128
+9648
+5982
+9904
+1974
+-4077
+-9764
+-4525
+-5834
+6285
+6559
+-6806
+1577
+-7459
+7276
+839
+9633
+-7440
+9191
+4709
+-7421
+-5043
+-2217
+-5419
+8031
+9873
+4658
+-2961
+-3223
+3226
+2189
+6134
+1939
+-4390
+-1323
+-240
+-8850
+6122
+7885
+1991
+2271
+6261
+-8012
+-6213
+-3041
+4125
+6966
+-5882
+-6915
+-5345
+-3925
+709
+978
+6321
+7461
+2433
+7315
+-4675
+-656
+-8237
+-7938
+-340
+-5314
+-4571
+1699
+1525
+-6613
+-2064
+4562
+6285
+4192
+-173
+7710
+-7469
+-3785
+-2248
+4375
+8399
+-833
+-427
+5295
+-7999
+7236
+-5517
+-5989
+-6017
+965
+-3883
+-7937
+7707
+-1892
+-2085
+8111
+-7516
+9569
+8043
+532
+-1663
+8001
+-1162
+9170
+-7059
+-8235
+-6865
+-9272
+6119
+-3662
+3870
+1339
+6589
+-4588
+-4322
+1549
+-9520
+6393
+7102
+621
+9389
+-4111
+5768
+-3700
+3018
+-5154
+-8234
+8634
+-2928
+-6425
+1709
+3657
+-9595
+-8276
+-844
+-4257
+770
+-4722
+-3718
+5091
+-8724
+7964
+5288
+8921
+-4719
+527
+-6946
+5186
+3598
+5259
+4359
+4147
+9435
+5992
+-6929
+1058
+-9752
+-4909
+4756
+-1902
+837
+6293
+6326
+7847
+-8692
+-9016
+8851
+8842
+8743
+1989
+-3991
+-6232
+-9571
+425
+2666
+9009
+4745
+-1197
+2866
+-2479
+8453
+-6310
+9490
+-1892
+-1313
+-2941
+-5062
+-4521
+-4219
+6337
+-2011
+7727
+-205
+2094
+2780
+6791
+3547
+-9513
+7262
+-9526
+-1306
+8873
+342
+6483
+376
+1897
+9068
+-5133
+1822
+-6727
+-3922
+-2009
+3515
+4391
+-3029
+2778
+7117
+8232
+6898
+-1425
+7289
+1346
+462
+-5431
+3643
+-7627
+8974
+-5687
+-7501
+5783
+132
+1799
+-6425
+-8416
+-8904
+8380
+-6216
+-6391
+-5792
+-5770
+4126
+-9622
+8842
+-2096
+2929
+-1438
+-3156
+-2796
+-7415
+1924
+6898
+6991
+-4968
+-8032
+998
+-3780
+1969
+8453
+2515
+-1596
+-6004
+3195
+-5012
+4594
+141
+1449
+2834
+-5076
+5824
+34
+3463
+-736
+-5096
+691
+3876
+5463
+6703
+-1072
+3853
+-7937
+-8593
+9037
+-2492
+1952
+2293
+-4422
+-2151
+5214
+5234
+5988
+-8011
+4501
+8970
+8678
+8386
+4525
+8340
+-7246
+-2570
+-5829
+2271
+-6614
+-8375
+-4515
+9674
+-2724
+-7871
+3973
+594
+3875
+1614
+-8339
+1879
+-7555
+5093
+6353
+-5309
+-9118
+-7390
+0
+-7598
+-4177
+8634
+7534
+1556
+349
+-9441
+3579
+-4653
+-2416
+-2194
+-4484
+-6483
+-5383
+-78
+-5205
+-1242
+813
+3590
+6240
+-3736
+-7390
+-7632
+5321
+-6299
+-4615
+-2210
+6188
+2372
+7060
+-5986
+-1632
+3032
+-5612
+-5336
+-8543
+3502
+1695
+4391
+2387
+4547
+1110
+-3353
+-545
+804
+-1809
+-5353
+7904
+8120
+5855
+1657
+-6626
+-6422
+-4870
+-1404
+-6229
+-3968
+2585
+2060
+-1821
+1577
+810
+-8408
+-7540
+7897
+279
+6039
+6656
+-9330
+2591
+8567
+-5495
+7354
+7443
+8697
+-9959
+925
+3180
+-6647
+8556
+-1018
+-1293
+9569
+-2128
+-1431
+7483
+-3984
+-649
+-8978
+4285
+262
+-5191
+-2759
+4835
+-5834
+1294
+-3856
+3084
+-8885
+-2708
+-1693
+-8948
+-6021
+1629
+3961
+2760
+2861
+-6797
+5184
+8419
+-9162
+6810
+-8473
+9899
+9844
+-2044
+-9103
+-3183
+-8697
+5303
+7412
+8344
+5003
+5957
+6327
+-8799
+2425
+-5159
+1732
+7934
+5728
+-7328
+-605
+-8552
+-6232
+-9200
+-3586
+6145
+8498
+-2780
+649
+5957
+3744
+-9775
+7645
+7354
+1335
+4195
+-5747
+6484
+8567
+7851
+1910
+8259
+-3384
+-9657
+2189
+-7643
+-5612
+-3674
+-6521
+-4128
+2187
+-3000
+-9708
+3052
+6262
+-4863
+8010
+3371
+5220
+-38
+3744
+-3828
+-6773
+-2962
+2887
+497
+425
+7873
+4140
+8657
+2461
+-7654
+8640
+6365
+4225
+6829
+4186
+2301
+-2793
+-6554
+7241
+-7102
+659
+-7999
+9335
+-1223
+-7090
+6542
+-2019
+-873
+-9624
+6293
+6039
+-6108
+8204
+2860
+5098
+-7132
+9694
+-1973
+-1217
+-3264
+-7112
+8296
+-8850
+4014
+-1837
+480
+-7667
+8005
+4750
+1059
+-4798
+-187
+4728
+7007
+-2369
+505
+-590
+-1827
+9692
+-6294
+9115
+9756
+2380
+4533
+-8557
+6450
+9019
+9514
+-6594
+7060
+2477
+2259
+-5578
+-85
+7356
+6055
+7649
+-2742
+29
+-5146
+-7621
+-2829
+-2427
+-3827
+6197
+9143
+-9622
+-4062
+-6232
+-1470
+2591
+7104
+-206
+9517
+-8918
+4658
+-7199
+-48
+2662
+6782
+-4705
+-9459
+-3950
+-9057
+-2526
+4866
+5611
+-7128
+4238
+1706
+-9179
+-6611
+5615
+-3148
+5074
+-9463
+-4435
+266
+4733
+-1242
+4407
+5334
+-2856
+-3600
+2666
+9396
+-1224
+-7132
+1957
+-3651
+-8843
+-8699
+-6879
+-9957
+-648
+-8212
+6511
+-2657
+5351
+7541
+8556
+7344
+-3734
+-4679
+-9580
+8416
+-8
+3976
+-8397
+-2827
+3666
+-3230
+-9044
+-9821
+-3836
+-8100
+-1502
+-4011
+-4569
+9761
+-8261
+4533
+9424
+-9374
+-6630
+4941
+2496
+-1902
+1491
+-9374
+3398
+2018
+-9983
+-6165
+1750
+-5885
+-383
+-2319
+9426
+5058
+8016
+-8079
+-576
+7192
+5003
+-5885
+-414
+-6455
+2511
+662
+-2997
+9240
+2670
+6145
+-6745
+-3414
+-6450
+-2425
+-335
+2475
+3671
+-4809
+-5888
+-3508
+4522
+-2626
+2970
+9659
+4590
+-4730
+-4722
+-5018
+-916
+4268
+-7102
+-2070
+-5414
+3533
+-6170
+-2247
+-6590
+-7211
+5153
+1360
+-2995
+-9954
+-7684
+-2668
+-335
+9352
+-698
+-133
+-3571
+-3419
+-4821
+-4222
+1603
+-4835
+-2259
+1547
+-2244
+8811
+-151
+-1201
+1008
+2212
+-739
+-9308
+-3766
+8964
+-240
+4044
+8368
+1944
+6672
+7953
+3481
+-4273
+-3961
+-6222
+-9274
+5345
+5834
+-4737
+9009
+-7920
+1128
+8227
+6031
+-4925
+-1714
+-6649
+-460
+183
+9207
+-6046
+2196
+-5435
+2797
+9783
+5909
+1103
+-6800
+9507
+-9967
+7643
+-7489
+4104
+-8978
+8732
+8582
+8013
+-2724
+-9453
+645
+-5489
+-3939
+-5242
+3400
+6392
+3355
+-2111
+-6056
+-8164
+-3053
+-6399
+1921
+-9171
+-68
+-4051
+-5292
+-2462
+-4215
+4733
+-1397
+47
+-5508
+425
+-1883
+-4273
+-8058
+-3972
+7223
+5112
+2154
+-5770
+7949
+8859
+-6140
+876
+7153
+4082
+-1025
+4462
+3629
+7006
+-1790
+2221
+-4133
+-5881
+259
+720
+-6333
+-953
+-749
+1092
+-1037
+4657
+8842
+4075
+-163
+9342
+558
+-5932
+-2319
+-5168
+-8259
+4266
+1592
+2389
+6351
+8556
+6039
+-248
+-6163
+-116
+7369
+-5998
+-2572
+-5181
+-8613
+372
+-8880
+-9597
+4453
+-9775
+-2547
+9640
+-1404
+9001
+8351
+5364
+3377
+-5316
+7518
+1801
+7070
+-4133
+5740
+1146
+-5307
+-9975
+-3460
+7818
+-1809
+-6152
+-1204
+3292
+3734
+-7803
+4001
+-5202
+5747
+1526
+-3045
+-5540
+6697
+2618
+7086
+4230
+1282
+2755
+-5638
+-5562
+-108
+2600
+-4321
+-2492
+-9473
+5957
+-1133
+-892
+5765
+3675
+-6046
+5497
+-773
+7607
+1526
+-9037
+1789
+1944
+-4342
+-5042
+-7299
+-9663
+-472
+-6905
+-4902
+7109
+-6946
+-9443
+1957
+-1247
+3834
+1904
+4014
+9367
+-5834
+4013
+-3265
+-9544
+7826
+-5557
+3747
+1848
+-2747
+1763
+7110
+9740
+-6326
+1550
+-8806
+886
+-1692
+621
+-2318
+-2134
+8851
+-9455
+6829
+6212
+4231
+-9032
+5475
+1265
+-266
+-266
+-7812
+831
+6041
+-787
+178
+7112
+-753
+1676
+6785
+-3034
+-7140
+-6678
+1425
+3896
+-8604
+-4845
+-3478
+6291
+70
+8512
+-1011
+-6948
+4547
+8822
+9089
+-3883
+8273
+6755
+2170
+-7420
+8031
+-1800
+837
+-485
+-8679
+-3348
+5730
+9397
+-2344
+3651
+5514
+1688
+-5743
+8640
+-8667
+-9101
+372
+-2657
+-3782
+7262
+6058
+-7034
+-7193
+6004
+-1135
+-2223
+-7027
+-4662
+-1242
+2456
+-6222
+6197
+6695
+4025
+-7363
+3533
+9713
+-6273
+-7379
+1355
+-383
+-1882
+-9203
+7521
+-8303
+-4640
+-240
+4398
+-3756
+5300
+2396
+9107
+6837
+9589
+-8655
+-3455
+7931
+5288
+6212
+8644
+-4086
+-5556
+-3605
+6591
+8482
+-7391
+7898
+821
+-9683
+-2569
+-7078
+4879
+9921
+-9772
+-1675
+5588
+1058
+-860
+-7392
+-3218
+5499
+6216
+4473
+6210
+-5278
+132
+-1231
+2585
+-7112
+-3865
+4741
+1892
+4073
+4142
+3887
+-8210
+4239
+-3057
+-1247
+-197
+-8115
+-1883
+2029
+6337
+-5321
+-798
+7434
+2029
+-4894
+-7469
+5746
+3214
+-2885
+9598
+-3215
+-4772
+4645
+5263
+6055
+3744
+7774
+3461
+-4734
+6680
+-5585
+1891
+1542
+-7905
+-2908
+-425
+9432
+1695
+-8178
+3503
+-1293
+2028
+-9261
+-8178
+-8058
+8489
+-7812
+-3736
+-3056
+-6157
+8653
+-5405
+1096
+-333
+-9319
+3339
+1335
+4123
+4547
+-4432
+4946
+-3545
+3156
+2462
+9946
+51
+-1134
+6576
+-3436
+5617
+-6425
+-1506
+3201
+2905
+4238
+-5132
+5409
+6349
+2760
+491
+6999
+-6552
+4265
+-9103
+6039
+-9163
+-9496
+7860
+-3785
+13
+8842
+-4772
+-9622
+3261
+271
+-7660
+4662
+5858
+-8431
+-8779
+-559
+9284
+9303
+8780
+3892
+-7479
+8794
+-4622
+-5606
+3466
+-4134
+7344
+-2691
+3375
+-1133
+-2429
+-448
+3443
+-8201
+-3057
+6113
+-5562
+2311
+6427
+-5692
+403
+7459
+1549
+-1563
+1954
+-9166
+-5462
+2189
+853
+8443
+-9894
+-4630
+-2070
+-7034
+-2206
+723
+-1228
+-2484
+2467
+7607
+5293
+870
+-2064
+2329
+-873
+9483
+-6800
+353
+2028
+8549
+8964
+9408
+9007
+-8406
+-2484
+3870
+9519
+-5874
+5176
+-919
+-5452
+-1890
+-9887
+3275
+2816
+7647
+-1376
+742
+5574
+2305
+-9003
+9633
diff --git a/template/Makefile b/template/Makefile
@@ -0,0 +1,20 @@
+CC=clang
+UTILS=../utils/reading.o
+INCLUDES=-I../utils
+
+all: utils common.o uppga uppgb
+
+common.o: common.c common.h
+ $(CC) $(CFLAGS) -c common.c $(INCLUDES)
+
+uppga: $(UTILS) common.o uppga.c
+ $(CC) -Wall -o uppga uppga.c common.o $(UTILS) $(INCLUDES)
+
+uppgb: $(UTILS) common.o uppgb.c
+ $(CC) -Wall -o uppgb uppgb.c common.o $(UTILS) $(INCLUDES)
+
+utils:
+ make -C ../utils
+
+clean:
+ rm -rf common.o uppga uppgb
diff --git a/template/common.c b/template/common.c
@@ -0,0 +1,6 @@
+#include "common.h"
+
+size_t fn(char** lines, size_t nlines)
+{
+ return 0;
+}
diff --git a/template/common.h b/template/common.h
@@ -0,0 +1,11 @@
+#ifndef COMMON_H_
+#define COMMON_H_
+
+#include <stdio.h>
+#include <stdint.h>
+#include <assert.h>
+#include <reading.h>
+
+size_t fn(char** lines, size_t nlines);
+
+#endif
diff --git a/template/uppga.c b/template/uppga.c
@@ -0,0 +1,10 @@
+#include "common.h"
+
+int main(int argc, char** argv)
+{
+ char** lines;
+ size_t nlines = readlines(&lines, "input");
+ printf("#lines: %lu\n", nlines);
+
+
+}
diff --git a/template/uppgb.c b/template/uppgb.c
@@ -0,0 +1,9 @@
+#include "common.h"
+
+int main(int argc, char** argv)
+{
+ char** lines;
+ size_t nlines = readlines(&lines, "input");
+ printf("#lines: %lu\n", nlines);
+
+}
diff --git a/utils/Makefile b/utils/Makefile
@@ -0,0 +1,11 @@
+CC=clang
+CFLAGS=-Wall -g
+OBJS=reading.o stack_u64.o stack_str.o sd.o stack_sd.o ht.o smallset.o
+
+all: $(OBJS)
+
+.c.o:
+ $(CC) $(CFLAGS) -c $<
+
+clean:
+ rm -rf $(OBJS)
diff --git a/utils/ht.c b/utils/ht.c
@@ -0,0 +1,46 @@
+#include "ht.h"
+
+void ht_init_size(ht* t, const size_t alloc)
+{
+ t->nalloc = alloc;
+ t->nelts = 0;
+ t->entries = calloc(t->nalloc, sizeof(*t->entries));
+
+ size_t i;
+ for(i = 0; i < t->nalloc; i++)
+ stack_sd_init_size(&t->entries[i], HT_DEFAULT_STACK_SIZE);
+}
+
+void ht_init(ht* t)
+{
+ ht_init_size(t, HT_DEFAULT_SIZE);
+}
+
+void ht_clear(ht* t)
+{
+ size_t i;
+ for(i = 0; i < t->nalloc; i++)
+ stack_sd_clear(&t->entries[i]);
+
+ t->nalloc = 0;
+ t->nelts = 0;
+ free(t->entries);
+ t->entries = NULL;
+}
+
+int ht_lookup(ht* t, sd d)
+{
+ uint64_t h = sd_hash(&d);
+ size_t i = h % t->nalloc;
+ return stack_sd_lookup(&t->entries[i], d);
+}
+
+void ht_insert(ht* t, sd d)
+{
+ if(ht_lookup(t, d) != STACK_SD_LOOKUP_NOT_FOUND) return;
+
+ size_t i = sd_hash(&d) % t->nalloc;
+ stack_sd_push(&t->entries[i], d);
+
+ t->nelts++;
+}
diff --git a/utils/ht.h b/utils/ht.h
@@ -0,0 +1,73 @@
+#ifndef HT_H
+#define HT_H
+
+#include "stack_sd.h"
+
+#define HT_DEFAULT_SIZE 255
+#define HT_DEFAULT_STACK_SIZE 2
+#define HT_LOOKUP_NOT_FOUND (STACK_SD_LOOKUP_NOT_FOUND) // == -1
+
+typedef struct {
+ size_t nelts;
+ size_t nalloc;
+
+ stack_sd* entries;
+} ht;
+
+/**
+ * Intitialize a hash table.
+ *
+ * This initializes a hash table of <<alloc>> buckets, at the address
+ * pointed to by <<t>>. Note that this memory needs to be cleared.
+ *
+ * @param t pointer to the ht to be initialized
+ * @param alloc the number of buckets to allocate for
+ */
+void ht_init_size(ht* t, const size_t alloc);
+
+/**
+ * Initialize a hash table.
+ *
+ * This initializes a hash table of the default size which is
+ * HT_DEFAULT_SIZE number of buckets. Note that this allocates memory
+ * that needs to be ht_clear'd.
+ *
+ * @param t pointer to the th to initialized
+ */
+void ht_init(ht* t);
+
+/**
+ * Clear a stack.
+ *
+ * @param t the stack to clear
+ */
+void ht_clear(ht* t);
+
+/**
+ * Lookup a sd in the hashtable.
+ *
+ * Returns a nonnegative value if the sd is in the hash table (by value
+ * comparison rather than pointer comparison of data). The value is the
+ * index of the stack_sd in the hash bucket where the sd is found. If
+ * the sd cannot be found in the stack the value
+ * HT_LOOKUP_NOT_FOUND == -1
+ * is returned.
+ *
+ * @param t pointer to the hash table too look up in
+ * @param d the sd to look up
+ */
+int ht_lookup(ht* t, sd d);
+
+/**
+ * Insert a as into the hashtable.
+ *
+ * Inserts a sd into the hash table. Note that this does not copy the
+ * sd data, but only pushes the pointer onto the stack. The sd should
+ * therefore not be cleared until ht has been cleared.
+ *
+ * @param t pointer to the hash table to insert into
+ * @param d the sd to insert
+ */
+void ht_insert(ht* t, sd d);
+
+#endif
diff --git a/utils/reading.c b/utils/reading.c
@@ -0,0 +1,112 @@
+#include "reading.h"
+
+size_t readall(char** output, char* filename)
+{
+ FILE* f = NULL;
+
+ f = fopen(filename, "r");
+
+ if(f == NULL) {
+ perror("Error when opening file");
+ exit(EXIT_FAILURE);
+ }
+
+ char buffer[MAXIMUM_FILESIZE_BYTES];
+ size_t read_size = fread(buffer, 1, MAXIMUM_FILESIZE_BYTES, f);
+
+ if(read_size == MAXIMUM_FILESIZE_BYTES) {
+ perror("File is to big?!");
+ exit(EXIT_FAILURE);
+ }
+
+ *output = (char*) malloc(read_size + 1);
+ memcpy(*output, buffer, read_size);
+ (*output)[read_size] = '\0';
+
+ return read_size;
+}
+
+size_t readlines(char*** lines, char* filename)
+{
+ FILE* f = fopen(filename, "r");
+
+ if(f == NULL) {
+ perror("Error when opening file");
+ exit(EXIT_FAILURE);
+ }
+
+ size_t tl_nalloc = LINES_ALLOC_MIN;
+ size_t ntl = 0;
+ char** tl = calloc(tl_nalloc, sizeof(*tl));
+
+ char line_buffer[MAXIMUM_LINE_BYTES];
+ while(fgets(line_buffer, MAXIMUM_LINE_BYTES, f)) {
+ if(ntl == tl_nalloc) {
+ tl_nalloc <<= 1;
+ tl = realloc(tl, tl_nalloc * sizeof(*tl));
+ }
+
+ tl[ntl] = strdup(line_buffer);
+
+ ntl++;
+ }
+
+ tl = realloc(tl, ntl * sizeof(*tl));
+ *lines = tl;
+
+ return(ntl);
+}
+
+int read_next_u64(uint64_t* n, FILE* fp)
+{
+ int r,c=0;
+
+ // skip to next numerical char
+ while((r = fgetc(fp)) != EOF) {
+ if((int)'0' <= r && r <= (int)'9') break;
+ }
+ if(r == EOF) return EOF;
+
+ // read an unsigned int
+ *n = (uint64_t)(r - (int)'0');
+ c++;
+ while((r = fgetc(fp)) != EOF) {
+ if((int)'0' <= r && r <= (int)'9') {
+ *n = (*n) * 10UL + (uint64_t)(r - (int)'0');
+ c++;
+ } else {
+ break;
+ }
+ }
+
+ return c;
+}
+
+
+char* sread_next_u64(uint64_t* n, char* s)
+{
+ char* fc = s;
+
+ // skip to next numerical char
+ while(*fc != '\0') {
+ if('0' <= *fc && *fc <= '9') break;
+ fc++;
+ }
+ if(*fc == '\0') return NULL;
+
+ // read an unsigned int
+ *n = (uint64_t)(*fc - '0');
+ fc++;
+ while(*fc != EOF) {
+ if('0' <= *fc && *fc <= '9') {
+ *n = (*n) * 10UL + (uint64_t)(*fc - '0');
+ } else {
+ break;
+ }
+ fc++;
+ }
+
+ if(*fc == '\0') return NULL;
+
+ return fc;
+}
diff --git a/utils/reading.h b/utils/reading.h
@@ -0,0 +1,68 @@
+#ifndef READING_H
+#define READING_H
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdint.h>
+
+#define MAXIMUM_FILESIZE_BYTES 256000
+#define MAXIMUM_LINE_BYTES 256000
+#define LINES_ALLOC_MIN 2048
+
+/**
+ * Read all chars from a file.
+ *
+ * Reads an entire file (assuming its size is < MAXIMUM_FILESIZE_BYTES).
+ * This allocates memory that needs to be free'd.
+ *
+ * @param output pointer to the address where the allocated string
+ * should be written
+ * @param filename the name of the file
+ * @return the number of bytes read (excluding final null byte)
+ */
+size_t readall(char** output, char* filename);
+
+/**
+ * Read all lines from a file.
+ *
+ * Reads a file, line-by-line (assuming no line is longer than
+ * MAXIMUM_LINE_BYTES).
+ * Allocates memory for each line that needs to be free'd.
+ *
+ * @param lines pointer to the address where the list of pointers
+ * should be written
+ * @param filename the name of the file
+ * @return the number of lines read
+ */
+size_t readlines(char*** lines, char* filename);
+
+/**
+ * Read the next uint64_t from FILE ptr.
+ *
+ * This has no checks for overflows, if it doesnt fit it will have
+ * undefined behaviour. Returns EOF if EOF is found before any
+ * uints.
+ *
+ * @param n pointer to where to write result
+ * @param fp file pointer to read from
+ * @returns the number of characters read as part of u64
+ */
+int read_next_u64(uint64_t* n, FILE* fp);
+
+/**
+ * Read the next uin64_t from string.
+ *
+ * This assumes that the string is a well-formatted null-terminated
+ * string. Returns a pointer to the * first char after the uint64 in
+ * the string, or NULL if this is not a part of the string or if it
+ * failed to read an uint64_t.
+ *
+ * @param n pointer to where to write the result
+ * @param s the string
+ * @returns pointer to next char in string, or NULL
+ */
+char* sread_next_u64(uint64_t* n, char* s);
+
+
+#endif
diff --git a/utils/sd.c b/utils/sd.c
@@ -0,0 +1,70 @@
+#include "sd.h"
+
+void sd_init(sd* s, const size_t size)
+{
+ s->size = size;
+ s->data = malloc(s->size);
+}
+
+void sd_clear(sd* s)
+{
+ s->size = 0;
+ free(s->data);
+}
+
+static inline uint64_t murmur_u64(uint64_t h) {
+ h ^= h >> 33;
+ h *= 0xff51afd7ed558ccdL;
+ h ^= h >> 33;
+ h *= 0xc4ceb9fe1a85ec53L;
+ h ^= h >> 33;
+ return h;
+}
+
+uint64_t sd_hash(sd* s)
+{
+ uint64_t tmp = s->size;
+
+ size_t i;
+ for(i = 0; i < s->size; i++) {
+ tmp ^= ((uint64_t) s->data[i]) << (i % 4);
+ }
+
+ return murmur_u64(tmp);
+}
+
+int sd_cmp(sd* x, sd* y)
+{
+ if(x->size < y->size) {
+ return -1;
+ } else if(x->size > y->size) {
+ return 1;
+ }
+
+ return memcmp(x->data, y->data, x->size);
+}
+
+void sd_init_u64(sd* s, const uint64_t x)
+{
+ sd_init(s, sizeof(x));
+ memcpy(s->data, &x, sizeof(x));
+}
+
+uint64_t sd_conv_u64(sd* s)
+{
+ uint64_t r;
+ memcpy(&r, s->data, sizeof(r));
+ return r;
+}
+
+void sd_init_str(sd* s, const char* str)
+{
+ size_t len = strlen(str)+1;
+ sd_init(s, sizeof(*str) * len);
+ memcpy(s->data, str, len);
+}
+
+char* sd_get_str(sd* s)
+{
+ return (char*) s->data;
+}
+\ No newline at end of file
diff --git a/utils/sd.h b/utils/sd.h
@@ -0,0 +1,103 @@
+#ifndef SD_H
+#define SD_H
+
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+
+typedef struct {
+ size_t size;
+ uint8_t* data;
+} sd;
+
+/**
+ * Initialise a sized data.
+ *
+ * Allocates memory that needs to be sd_clear'd.
+ *
+ * @param s pointer where to write the sized data obj
+ * @param size number of bytes in the sd
+ */
+void sd_init(sd* s, const size_t size);
+
+/**
+ * Clear a sd.
+ *
+ * @param s pointer to the sd
+ */
+void sd_clear(sd* s);
+
+/**
+ * Computes a hash of a sd.
+ *
+ * This hash is a simple combination of xoring
+ * in all the bytes to a uint64_t in different
+ * positions, then computing the mix64 function
+ * known as murmur64.
+ *
+ * @param s the sd to get hash of
+ * @return hash of s
+ */
+uint64_t sd_hash(sd* s);
+
+/**
+ * Compare two sds.
+ *
+ * Compares the sd's pointed to by x and y. In the
+ * following sense: a < b if either a.size < b.size
+ * or a.data < b.data (in the memcmp order). If
+ * the sd are equal then 0 is returned.
+ *
+ * @param x pointer to first sd
+ * @param y pointer to second sd
+ * @return comparison number (lex order)
+ */
+int sd_cmp(sd* x, sd* y);
+
+/**
+ * Initialises a sd from a uint64_t.
+ *
+ * The size will be 8 bytes, and the order of the
+ * bytes is raw (host order). Allocates memory that
+ * needs to be sd_clear'd.
+ *
+ * @param s ptr to the sd to initialise
+ * @param x the uint64_t to initialize from
+ */
+void sd_init_u64(sd* s, const uint64_t x);
+
+/**
+ * Converts a sd to a uint64_t.
+ *
+ * Gets a uint64_t from a sd that has been created
+ * by sd_init_u64.
+ *
+ * @param s ptr to the sd to convert
+ * @return the uint64_t
+ */
+uint64_t sd_conv_u64(sd* s);
+
+/**
+ * Initializes a sd from a string.
+ *
+ * Copies a string into a sd, including the
+ * terminating null byte. Allocates memory that
+ * needs to be sd_clear'd.
+ *
+ * @param s ptr to the sd to be init'd
+ * @param str the string to copy into new sd
+ */
+void sd_init_str(sd* s, const char* str);
+
+/**
+ * Get string stored in sd.
+ *
+ * This returns a char* to the data stored in the
+ * sd. This assumes that the data is in fact a
+ * null terminated string.
+ *
+ * @param s ptr to the sd to get string from
+ */
+char* sd_get_str(sd* s);
+
+#endif
+\ No newline at end of file
diff --git a/utils/smallset.c b/utils/smallset.c
@@ -0,0 +1,97 @@
+#include "smallset.h"
+
+#define BIDX(x) (x/8)
+#define BMSK(x) (0x80 >> (x % 8))
+#define SIZE(b) ((b + 7) >> 3)
+
+void smallset_init(smallset* s, const size_t bits)
+{
+ s->bits = bits;
+ s->data = calloc(SIZE(bits), sizeof(*s->data));
+ assert(sizeof(*s->data) == 1);
+}
+
+void smallset_clear(smallset* s)
+{
+ s->bits = 0;
+ free(s->data);
+}
+
+void smallset_insert(smallset* s, const uint64_t x)
+{
+ assert(x < s->bits);
+ s->data[BIDX(x)] |= BMSK(x);
+}
+
+int smallset_lookup(smallset* s, const uint64_t x)
+{
+ assert(x < s->bits);
+ return s->data[BIDX(x)] & BMSK(x);
+}
+
+void smallset_intersection(smallset* out, smallset* a, smallset* b)
+{
+ assert(a->bits == b->bits);
+ assert(out->bits == a->bits);
+
+ size_t i;
+ for(i = 0; i < SIZE(out->bits); i++) {
+ out->data[i] = a->data[i] & b->data[i];
+ }
+}
+
+void smallset_tonstr(char* str, size_t n, smallset* s)
+{
+ int first = 1;
+ int u = snprintf(str, n, "{");
+
+ size_t i;
+ for(i = 0; i < s->bits; i++) {
+ if(smallset_lookup(s, i)) {
+ if(!first) {
+ u += snprintf(&str[u], n-u, ", %zu", i);
+ } else {
+ u += snprintf(&str[u], n-u, "%zu", i);
+ first = !first;
+ }
+ }
+ }
+
+ snprintf(&str[u], n-u, "}");
+}
+
+uint64_t smallset_getone(smallset* s)
+{
+ uint64_t i;
+ for(i = 0; i < s->bits; i++) {
+ if(smallset_lookup(s, i)) return i;
+ }
+
+ return SMALLSET_IS_EMPTY;
+}
+
+void smallset_empty(smallset* s)
+{
+ memset(s->data, 0, SIZE(s->bits));
+}
+
+uint64_t smallset_cardinality(smallset* s)
+{
+ uint64_t a;
+ uint64_t r = 0;
+ size_t i;
+ for(i = 0; i < SIZE(s->bits); i += 8) {
+ __asm__ volatile ("POPCNT %1, %0" :"=r"(a) :"r"(*((uint64_t*) &s->data[i])) :);
+ r += a;
+ }
+
+ uint64_t tmp = 0;
+ while(i < SIZE(s->bits)) {
+ tmp = (tmp << 8) ^ ((uint64_t) s->data[i]);
+ i++;
+ }
+ __asm__ volatile ("POPCNT %1, %0" :"=r"(a) :"r"(tmp) :);
+ r += a;
+
+ return r;
+}
diff --git a/utils/smallset.h b/utils/smallset.h
@@ -0,0 +1,119 @@
+/**
+ * Implementation of "small sets" (subsets of [n], where n is not big).
+ */
+#ifndef SMALLSET_H_
+#define SMALLSET_H_
+
+#include <stdio.h>
+#include <stdint.h>
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define SMALLSET_IS_EMPTY UINT64_MAX
+
+typedef struct {
+ size_t bits;
+ uint8_t* data;
+} smallset;
+
+/**
+ * Intializes a small set.
+ *
+ * The set is a subset of some fixed [n].
+ * Allocates memory that needs to be smallset_clear'd.
+ *
+ * @param s pointer to the smallset to be inited
+ * @param bits specifies that the set is a subset of [bits]
+ */
+void smallset_init(smallset* s, const size_t bits);
+
+/**
+ * Clears a set.
+ *
+ * @param s pointer to the smallset to clear
+ */
+void smallset_clear(smallset* s);
+
+/**
+ * Insert an element into a set.
+ *
+ * Inserts an element x \in [n] into a smallset. If the
+ * element is already in the set the set is unchanged.
+ * Assertions will fail of x \not\in [n].
+ *
+ * @param s pointer to the set to insert into
+ * @param x element to insert into the set
+ */
+void smallset_insert(smallset* s, const uint64_t x);
+
+/**
+ * Check if an element is in a set.
+ *
+ * Checks if the element x is in the set pointed to by
+ * s. Assumes that x \in [n] (or assertions will fail).
+ *
+ * @param s pointer to the set to check in
+ * @param x the element to check for
+ * @returns a nonzero value iff x is in the set
+ */
+int smallset_lookup(smallset* s, const uint64_t x);
+
+/**
+ * Compute the intersection of two sets.
+ *
+ * This assumes that all three sets are subsets of the
+ * same [n]. Otherwise assertions will fail. Note that
+ * any of the pointers are allowed to be equal.
+ *
+ * @param out pointer to the set where to write intersection
+ * @param a pointer to one of the intersect sets
+ * @param b pointer to the other intersect set
+ */
+void smallset_intersection(smallset* out, smallset* a, smallset* b);
+
+/**
+ * Writes the smallset to a string.
+ *
+ * The string buffer must already be allocated, and the
+ * parameter n indicates the maximum number of bytes that
+ * may be written to the buffer, including termingating \0.
+ *
+ * String is reprensented in trad notation: e.g.
+ * {}, {1,3}, {0,16,19}
+ *
+ * @param str pointer to the first char of the write buffer
+ * @param n limit on the number of bytes to be written
+ * @param s pointer to the smallset
+ */
+void smallset_tonstr(char* str, size_t n, smallset* s);
+
+/**
+ * Get an element that is in the set.
+ *
+ * Returns the smallest element from the set. If no element
+ * is in the set (i.e. it is empty) then this returns the
+ * SMALLSET_IS_EMPTY value (== UINT64_MAX).
+ *
+ * @param s pointer to the smallset to get elem from
+ */
+uint64_t smallset_getone(smallset* s);
+
+/**
+ * Empty a set.
+ *
+ * Empties a set by removing all elements.
+ *
+ * @param s pointer to the smallset to empty
+ */
+void smallset_empty(smallset* s);
+
+/**
+ * Get the cardinality of a set.
+ *
+ * @param s the set to get the cardinality of
+ * @return the cardinality
+ */
+uint64_t smallset_cardinality(smallset* s);
+
+#endif
diff --git a/utils/stack_sd.c b/utils/stack_sd.c
@@ -0,0 +1,63 @@
+#include "stack_sd.h"
+
+void stack_sd_init(stack_sd* d)
+{
+ d->nmemb = 0;
+ d->alloc = BASE_STACK_SD_SIZE;
+
+ d->data = calloc(d->alloc, sizeof(*(d->data)));
+}
+
+void stack_sd_init_size(stack_sd* d, const size_t size)
+{
+ d->nmemb = 0;
+ d->alloc = size;
+
+ d->data = calloc(d->alloc, sizeof(*(d->data)));
+}
+
+void stack_sd_clear(stack_sd* d)
+{
+ d->nmemb = 0;
+ free(d->data);
+ d->data = NULL;
+}
+
+void stack_sd_push(stack_sd* d, sd x)
+{
+ if(d->alloc <= d->nmemb) {
+ d->alloc <<= 1;
+ d->data = realloc(d->data, d->alloc * sizeof(*(d->data)));
+ }
+
+ d->data[d->nmemb] = x;
+ d->nmemb++;
+}
+
+sd stack_sd_get(const stack_sd* d, const size_t i)
+{
+ return d->data[i];
+}
+
+sd stack_sd_getlast(const stack_sd* d)
+{
+ return stack_sd_get(d, d->nmemb-1);
+}
+
+sd stack_sd_pop(stack_sd* d)
+{
+ if(d->nmemb == 0) return STACK_SD_EMPTY_POP;
+
+ sd r = stack_sd_getlast(d);
+ d->nmemb--;
+ return r;
+}
+
+int stack_sd_lookup(stack_sd* d, sd s)
+{
+ int i;
+ for(i = 0; i < d->nmemb; i++) {
+ if(sd_cmp(&d->data[i], &s) == 0) return i;
+ }
+ return STACK_SD_LOOKUP_NOT_FOUND;
+}
diff --git a/utils/stack_sd.h b/utils/stack_sd.h
@@ -0,0 +1,97 @@
+#ifndef STACK_SD_H
+#define STACK_SD_H
+
+#include <stdlib.h>
+#include <stdint.h>
+#include "sd.h"
+
+#define BASE_STACK_SD_SIZE 256
+#define STACK_SD_LOOKUP_NOT_FOUND (-1)
+#define STACK_SD_EMPTY_POP ((sd) {.size = 0, .data = NULL})
+
+typedef struct {
+ size_t nmemb;
+ size_t alloc;
+
+ sd* data;
+} stack_sd;
+
+/**
+ * Initialization of stack.
+ *
+ * Initialises memory for the stack. Use clear.
+ *
+ * @param d pointer to the address where to write the new stack
+ */
+void stack_sd_init(stack_sd* d);
+
+/**
+ * Initialization of stack, with size.
+ *
+ * Initialises memory for the stack. Use clear.
+ *
+ * @param d pointer to the address where to write the new stack
+ * @param size initial size of stack alloc
+ */
+void stack_sd_init_size(stack_sd* d, const size_t size);
+
+/**
+ * Clear a stack
+ *
+ * @param d pointer to the stack to clear
+ */
+void stack_sd_clear(stack_sd* d);
+
+/**
+ * Pushes a sd pointer onto the stack.
+ *
+ * Note that this does not copy the sd data, it just pushes the sd
+ * struct including the pointer to the stack.
+ *
+ * @param d pointer to the stack
+ * @param x the sd to push
+ */
+void stack_sd_push(stack_sd* d, sd x);
+
+/**
+ * Gets the element at index i in the stack.
+ *
+ * @param d pointer to the stack
+ * @param i the index to get element at
+ * @return the value of the sd at index i
+ */
+sd stack_sd_get(const stack_sd* d, const size_t i);
+
+/**
+ * Get the last (top) element of a stack.
+ *
+ * @param d pointer to the stack
+ * @return the value of the sd at the top
+ */
+sd stack_sd_getlast(const stack_sd* d);
+
+/**
+ * Pop an element of the stack.
+ *
+ * Note that popping never decreases the amount of memory allocated.
+ * If memory is an issue the stacks have to be destroyed and replaced.
+ * Returns STACK_SD_POP_EMPY if stack is empty.
+ *
+ * @param d pointer to the stack
+ * @return the value of the popped sd
+ */
+sd stack_sd_pop(stack_sd* d);
+
+/**
+ * Lookup a sd on a stack.
+ *
+ * Returns the first index on the stack at which a sd appears. Returns
+ * STACK_SD_LOOKUP_NOT_FOUND (== -1) if element is not in stack. It
+ * compares the sd elements (i.e. not only the pointers).
+ *
+ * @param d the stack to lookup in
+ * @param s the sd to look for in the stack
+ */
+int stack_sd_lookup(stack_sd* d, sd s);
+
+#endif
diff --git a/utils/stack_str.c b/utils/stack_str.c
@@ -0,0 +1,46 @@
+#include "stack_str.h"
+
+void stack_str_init(stack_str* d)
+{
+ d->nmemb = 0;
+ d->alloc = BASE_STACK_STR_SIZE;
+
+ d->data = calloc(d->alloc, sizeof(*(d->data)));
+}
+
+void stack_str_clear(stack_str* d)
+{
+ d->nmemb = 0;
+ free(d->data);
+ d->data = NULL;
+}
+
+void stack_str_push(stack_str* d, char* x)
+{
+ if(d->alloc <= d->nmemb) {
+ d->alloc <<= 1;
+ d->data = realloc(d->data, d->alloc * sizeof(*(d->data)));
+ }
+
+ d->data[d->nmemb] = x;
+ d->nmemb++;
+}
+
+char* stack_str_get(const stack_str* d, const size_t i)
+{
+ return d->data[i];
+}
+
+char* stack_str_getlast(const stack_str* d)
+{
+ return stack_str_get(d, d->nmemb-1);
+}
+
+char* stack_str_pop(stack_str* d)
+{
+ if(d->nmemb == 0)
+ return STACK_STR_EMPTY_POP;
+ char* r = stack_str_getlast(d);
+ d->nmemb--;
+ return r;
+}
+\ No newline at end of file
diff --git a/utils/stack_str.h b/utils/stack_str.h
@@ -0,0 +1,69 @@
+#ifndef STACK_STR_H
+#define STACK_STR_H
+
+#include <stdlib.h>
+#include <stdint.h>
+
+#define BASE_STACK_STR_SIZE 256
+#define STACK_STR_EMPTY_POP (NULL)
+
+typedef struct {
+ size_t nmemb;
+ size_t alloc;
+
+ char** data;
+} stack_str;
+
+/**
+ * Initialization of stack.
+ *
+ * Initialises memory for the stack. Use clear.
+ *
+ * @param d pointer to the address where to write the new stack
+ */
+void stack_str_init(stack_str* d);
+
+/**
+ * Clear a stack
+ *
+ * @param d pointer to the stack to clear
+ */
+void stack_str_clear(stack_str* d);
+
+/**
+ * Pushes a string (char pointer) onto the stack.
+ *
+ * Note that this does not copy the string, it just pushes the pointer to the stack.
+ *
+ * @param d pointer to the stack
+ * @param x the string (char pointer) to push
+ */
+void stack_str_push(stack_str* d, char* x);
+
+/**
+ * Gets the element at index i in the stack.
+ *
+ * @param d pointer to the stack
+ * @param i the index to get element at
+ * @return the value (the char pointer) of the element at index i
+ */
+char* stack_str_get(const stack_str* d, const size_t i);
+
+/**
+ * Get the last (top) element of a stack.
+ *
+ * @param d pointer to the stack
+ */
+char* stack_str_getlast(const stack_str* d);
+
+/**
+ * Pop an element of the stack.
+ *
+ * Note that popping never decreases the amount of memory allocated.
+ * If memory is an issue the stacks have to be destroyed and replaced.
+ *
+ * @param d pointer to the stack
+ */
+char* stack_str_pop(stack_str* d);
+
+#endif
+\ No newline at end of file
diff --git a/utils/stack_u64.c b/utils/stack_u64.c
@@ -0,0 +1,46 @@
+#include "stack_u64.h"
+
+void stack_u64_init(stack_u64* d)
+{
+ d->nmemb = 0;
+ d->alloc = BASE_STACK_SIZE;
+
+ d->data = calloc(d->alloc, sizeof(*(d->data)));
+}
+
+void stack_u64_clear(stack_u64* d)
+{
+ d->nmemb = 0;
+ free(d->data);
+ d->data = NULL;
+}
+
+void stack_u64_push(stack_u64* d, const uint64_t x)
+{
+ if(d->alloc <= d->nmemb) {
+ d->alloc <<= 1;
+ d->data = realloc(d->data, d->alloc * sizeof(*(d->data)));
+ }
+
+ d->data[d->nmemb] = x;
+ d->nmemb++;
+}
+
+uint64_t stack_u64_get(const stack_u64* d, const size_t i)
+{
+ return d->data[i];
+}
+
+uint64_t stack_u64_getlast(const stack_u64* d)
+{
+ return stack_u64_get(d, d->nmemb-1);
+}
+
+uint64_t stack_u64_pop(stack_u64* d)
+{
+ if(d->nmemb == 0)
+ return STACK_U64_EMPTY_POP;
+ uint64_t r = stack_u64_getlast(d);
+ d->nmemb--;
+ return r;
+}
+\ No newline at end of file
diff --git a/utils/stack_u64.h b/utils/stack_u64.h
@@ -0,0 +1,67 @@
+#ifndef STACK_U64_H
+#define STACK_U64_H
+
+#include <stdlib.h>
+#include <stdint.h>
+
+#define BASE_STACK_SIZE 256
+#define STACK_U64_EMPTY_POP UINT64_MAX
+
+typedef struct {
+ size_t nmemb;
+ size_t alloc;
+
+ uint64_t* data;
+} stack_u64;
+
+/**
+ * Initialization of stack.
+ *
+ * Initialises memory for the stack. Use clear.
+ *
+ * @param d pointer to the address where to write the new stack
+ */
+void stack_u64_init(stack_u64* d);
+
+/**
+ * Clear a stack
+ *
+ * @param d pointer to the stack to clear
+ */
+void stack_u64_clear(stack_u64* d);
+
+/**
+ * Pushes a uint64_t onto the stack.
+ *
+ * @param d pointer to the stack
+ * @param x the uint64_t to push
+ */
+void stack_u64_push(stack_u64* d, const uint64_t x);
+
+/**
+ * Gets the element at index i in the stack.
+ *
+ * @param d pointer to the stack
+ * @param i the index to get element at
+ * @return the value of the element at index i
+ */
+uint64_t stack_u64_get(const stack_u64* d, const size_t i);
+
+/**
+ * Get the last (top) element of a stack.
+ *
+ * @param d pointer to the stack
+ */
+uint64_t stack_u64_getlast(const stack_u64* d);
+
+/**
+ * Pop an element of the stack.
+ *
+ * Note that popping never decreases the amount of memory allocated.
+ * If memory is an issue the stacks have to be destroyed and replaced.
+ *
+ * @param d pointer to the stack
+ */
+uint64_t stack_u64_pop(stack_u64* d);
+
+#endif
+\ No newline at end of file
diff --git a/utils/test/Makefile b/utils/test/Makefile
@@ -0,0 +1,34 @@
+CC=clang
+CFLAGS=-Wall -g -I/usr/local/include
+LDFLAGS=-lcunit -L/usr/local/lib
+TEST_OBJS=\
+ test_reading.o \
+ test_stack_u64.o \
+ test_stack_str.o \
+ test_sd.o \
+ test_smallset.o \
+ test_stack_sd.o \
+ test_ht.o
+OBJS=\
+ ../reading.o \
+ ../stack_u64.o \
+ ../stack_str.o \
+ ../sd.o \
+ ../smallset.o \
+ ../stack_sd.o \
+ ../ht.o
+
+all: utils tests
+
+utils:
+ make -C ../
+
+tests: tests.c $(TEST_OBJS)
+ $(CC) $(CFLAGS) $(LDFLAGS) -o tests tests.c $(OBJS) $(TEST_OBJS)
+ ./tests
+
+.c.o:
+ $(CC) $(CFLAGS) -c $<
+
+clean:
+ rm -rf tests $(TEST_OBJS)
diff --git a/utils/test/test_ht.c b/utils/test/test_ht.c
@@ -0,0 +1,75 @@
+#include "test_ht.h"
+
+void test_ht_init()
+{
+ ht h;
+
+ ht_init(&h);
+ CU_ASSERT(h.nelts == 0);
+ CU_ASSERT(h.nalloc == HT_DEFAULT_SIZE);
+ CU_ASSERT(h.entries != NULL);
+
+ ht_clear(&h);
+
+ ht_init_size(&h, 23);
+ CU_ASSERT(h.nelts == 0);
+ CU_ASSERT(h.nalloc == 23);
+ CU_ASSERT(h.entries != NULL);
+
+ ht_clear(&h);
+}
+
+void test_ht_insert()
+{
+ ht h;
+ ht_init_size(&h, 16);
+
+ sd elts[17];
+
+ size_t i;
+ for(i = 0; i < 17; i++) {
+ sd_init_u64(&elts[i], i);
+ ht_insert(&h, elts[i]);
+ CU_ASSERT(h.nelts == i+1);
+ }
+
+ sd tmp;
+ sd_init_u64(&tmp, 12);
+ ht_insert(&h, tmp);
+ CU_ASSERT(h.nelts == 17);
+
+ for(i = 0; i < 17; i++) sd_clear(&elts[i]);
+
+ ht_clear(&h);
+}
+
+void test_ht_lookup()
+{
+ ht h;
+ ht_init_size(&h, 32);
+
+ sd elts[17];
+
+ size_t i;
+ for(i = 0; i < 17; i++) {
+ sd_init_u64(&elts[i], 2*i);
+ ht_insert(&h, elts[i]);
+ }
+
+ sd nelts[2*17];
+ for(i = 0; i < 2*17; i++) {
+ sd_init_u64(&nelts[i], i);
+ if(i % 2 == 0) {
+ int index = ht_lookup(&h, nelts[i]);
+ CU_ASSERT(index <= 17);
+ CU_ASSERT(index >= 0);
+ } else {
+ CU_ASSERT(ht_lookup(&h, nelts[i]) == HT_LOOKUP_NOT_FOUND);
+ }
+ }
+
+ for(i = 0; i < 17; i++) sd_clear(&elts[i]);
+ for(i = 0; i < 2*17; i++) sd_clear(&nelts[i]);
+
+ ht_clear(&h);
+}
diff --git a/utils/test/test_ht.h b/utils/test/test_ht.h
@@ -0,0 +1,11 @@
+#ifndef TEST_HT_H
+#define TEST_HT_H
+
+#include <CUnit/Basic.h>
+#include "../ht.h"
+
+void test_ht_init();
+void test_ht_lookup();
+void test_ht_insert();
+
+#endif
diff --git a/utils/test/test_reading.c b/utils/test/test_reading.c
@@ -0,0 +1,63 @@
+#include "test_reading.h"
+
+void test_reading_readall()
+{
+ char* read;
+ size_t n = readall(&read, "testfile1.txt");
+
+ CU_ASSERT(n == 49);
+ CU_ASSERT(strcmp(read, "Hello, this is a test file.\nIt contains two rows.") == 0);
+
+ free(read);
+}
+
+void test_reading_readlines()
+{
+ char** read;
+ size_t n = readlines(&read, "testfile1.txt");
+
+ CU_ASSERT(n == 2);
+ CU_ASSERT(strcmp(read[0], "Hello, this is a test file.\n") == 0);
+ CU_ASSERT(strcmp(read[1], "It contains two rows.") == 0);
+
+ size_t i;
+ for(i = 0; i < n; i++) free(read[i]);
+ free(read);
+}
+
+void test_reading_read_next_u64()
+{
+ FILE* fp = fopen("testfile2.txt", "r");
+
+ uint64_t r;
+ CU_ASSERT(read_next_u64(&r, fp) == 4);
+ CU_ASSERT(r == 4711);
+ CU_ASSERT(read_next_u64(&r, fp) == 2);
+ CU_ASSERT(r == 65);
+ CU_ASSERT(read_next_u64(&r, fp) == 4);
+ CU_ASSERT(r == 1337);
+ CU_ASSERT(read_next_u64(&r, fp) == 1);
+ CU_ASSERT(r == 1);
+ CU_ASSERT(read_next_u64(&r, fp) == 1);
+ CU_ASSERT(r == 0);
+
+ fclose(fp);
+}
+
+void test_reading_sread_next_u64()
+{
+ char tst[] = "foobarm4711asd65,1337.1\n0";
+ char* n = tst;
+ uint64_t r;
+
+ CU_ASSERT((n = sread_next_u64(&r, n)) != NULL);
+ CU_ASSERT(r == 4711);
+ CU_ASSERT((n = sread_next_u64(&r, n)) != NULL);
+ CU_ASSERT(r == 65);
+ CU_ASSERT((n = sread_next_u64(&r, n)) != NULL);
+ CU_ASSERT(r == 1337);
+ CU_ASSERT((n = sread_next_u64(&r, n)) != NULL);
+ CU_ASSERT(r == 1);
+ CU_ASSERT((n = sread_next_u64(&r, n)) == NULL);
+ CU_ASSERT(r == 0);
+}
diff --git a/utils/test/test_reading.h b/utils/test/test_reading.h
@@ -0,0 +1,12 @@
+#ifndef TEST_READING_H
+#define TEST_READING_H
+
+#include "../reading.h"
+#include <CUnit/Basic.h>
+
+void test_reading_readall();
+void test_reading_readlines();
+void test_reading_read_next_u64();
+void test_reading_sread_next_u64();
+
+#endif
diff --git a/utils/test/test_sd.c b/utils/test/test_sd.c
@@ -0,0 +1,97 @@
+#include "test_sd.h"
+
+void test_sd_init()
+{
+ sd s;
+ sd_init(&s, 12);
+
+ CU_ASSERT(s.size == 12);
+
+ size_t i;
+ for(i = 0; i < s.size; i++) s.data[i] = 0x00;
+ for(i = 0; i < s.size; i++) {
+ CU_ASSERT(s.data[i] == 0x00);
+ }
+
+ sd_clear(&s);
+
+ sd_init_u64(&s, 13);
+ uint64_t tretton = 13;
+ CU_ASSERT(s.size == sizeof(uint64_t));
+ CU_ASSERT(memcmp(s.data, &tretton, sizeof(uint64_t)) == 0);
+
+ sd_clear(&s);
+
+ char* mystr = "this is a test";
+ sd_init_str(&s, mystr);
+ CU_ASSERT(s.size == strlen(mystr)+1);
+ CU_ASSERT(memcmp(s.data, "this is a test", s.size) == 0);
+
+ sd_clear(&s);
+}
+
+void test_sd_cmp()
+{
+ char* strs[4] = {"bc", "abc", "abd", "abcd"};
+
+ sd ss[4];
+ size_t i;
+ for(i = 0; i < 4; i++) {
+ sd_init_str(&ss[i], strs[i]);
+ }
+
+ CU_ASSERT(sd_cmp(&ss[0], &ss[1]) < 0);
+ CU_ASSERT(sd_cmp(&ss[0], &ss[2]) < 0);
+ CU_ASSERT(sd_cmp(&ss[0], &ss[3]) < 0);
+ CU_ASSERT(sd_cmp(&ss[0], &ss[0]) == 0);
+ CU_ASSERT(sd_cmp(&ss[1], &ss[2]) < 0);
+ CU_ASSERT(sd_cmp(&ss[1], &ss[3]) < 0);
+ CU_ASSERT(sd_cmp(&ss[3], &ss[2]) > 0);
+
+ for(i = 0; i < 4; i++) {
+ sd_clear(&ss[i]);
+ }
+}
+
+void test_sd_hash()
+{
+ char* strs[4] = {"bc", "abc", "abd", "abd"};
+
+ sd ss[4];
+ size_t i;
+ for(i = 0; i < 4; i++) {
+ sd_init_str(&ss[i], strs[i]);
+ }
+
+ CU_ASSERT(sd_hash(&ss[0]) != sd_hash(&ss[1]));
+ CU_ASSERT(sd_hash(&ss[0]) != sd_hash(&ss[2]));
+ CU_ASSERT(sd_hash(&ss[0]) != sd_hash(&ss[3]));
+ CU_ASSERT(sd_hash(&ss[1]) != sd_hash(&ss[2]));
+ CU_ASSERT(sd_hash(&ss[1]) != sd_hash(&ss[3]));
+ CU_ASSERT(sd_hash(&ss[2]) == sd_hash(&ss[3]));
+
+ for(i = 0; i < 4; i++)
+ sd_clear(&ss[i]);
+}
+
+void test_sd_conv_u64()
+{
+ sd s;
+ sd_init_u64(&s,0xdeadbeeffeedbaaf);
+ uint64_t c = sd_conv_u64(&s);
+ CU_ASSERT(c == 0xdeadbeeffeedbaaf);
+ sd_clear(&s);
+}
+
+void test_sd_get_str()
+{
+ sd s;
+ char* str = "hello world!";
+ sd_init_str(&s, str);
+ char* mystr = sd_get_str(&s);
+
+ CU_ASSERT(mystr != str);
+ CU_ASSERT(strncmp(str, mystr, 13) == 0);
+
+ sd_clear(&s);
+}
diff --git a/utils/test/test_sd.h b/utils/test/test_sd.h
@@ -0,0 +1,13 @@
+#ifndef TEST_SD_H
+#define TEST_SD_H
+
+#include <CUnit/Basic.h>
+#include "../sd.h"
+
+void test_sd_init();
+void test_sd_cmp();
+void test_sd_hash();
+void test_sd_conv_u64();
+void test_sd_get_str();
+
+#endif
diff --git a/utils/test/test_smallset.c b/utils/test/test_smallset.c
@@ -0,0 +1,173 @@
+#include "test_smallset.h"
+
+void test_smallset_init()
+{
+ smallset s;
+ smallset_init(&s, 17);
+
+ size_t i;
+ for(i = 0; i < (17+7)/8; i++) {
+ CU_ASSERT(s.data[i] == 0);
+ }
+
+ smallset_clear(&s);
+}
+
+void test_smallset_insert()
+{
+ smallset s;
+ smallset_init(&s, 17);
+
+ smallset_insert(&s, 3);
+
+ CU_ASSERT(s.data[0] == 0x80 >> 3);
+ CU_ASSERT(s.data[1] == 0x00);
+ CU_ASSERT(s.data[2] == 0x00);
+
+ smallset_clear(&s);
+}
+
+void test_smallset_lookup()
+{
+ smallset s;
+ smallset_init(&s, 17);
+
+ smallset_insert(&s, 3);
+ smallset_insert(&s, 15);
+ smallset_insert(&s, 4);
+
+ CU_ASSERT(smallset_lookup(&s, 0) == 0);
+ CU_ASSERT(smallset_lookup(&s, 1) == 0);
+ CU_ASSERT(smallset_lookup(&s, 2) == 0);
+ CU_ASSERT(smallset_lookup(&s, 3) != 0);
+ CU_ASSERT(smallset_lookup(&s, 4) != 0);
+ CU_ASSERT(smallset_lookup(&s, 5) == 0);
+ CU_ASSERT(smallset_lookup(&s, 6) == 0);
+ CU_ASSERT(smallset_lookup(&s, 7) == 0);
+ CU_ASSERT(smallset_lookup(&s, 8) == 0);
+ CU_ASSERT(smallset_lookup(&s, 9) == 0);
+ CU_ASSERT(smallset_lookup(&s, 10) == 0);
+ CU_ASSERT(smallset_lookup(&s, 11) == 0);
+ CU_ASSERT(smallset_lookup(&s, 12) == 0);
+ CU_ASSERT(smallset_lookup(&s, 13) == 0);
+ CU_ASSERT(smallset_lookup(&s, 14) == 0);
+ CU_ASSERT(smallset_lookup(&s, 15) != 0);
+ CU_ASSERT(smallset_lookup(&s, 16) == 0);
+
+ smallset_clear(&s);
+}
+
+void test_smallset_intersection()
+{
+ smallset a, b, s;
+ smallset_init(&a, 17);
+ smallset_init(&b, 17);
+ smallset_init(&s, 17);
+
+ smallset_insert(&a, 3);
+ smallset_insert(&a, 4);
+ smallset_insert(&a, 15);
+ smallset_insert(&a, 5);
+ smallset_insert(&a, 7);
+
+ smallset_insert(&b, 3);
+ smallset_insert(&b, 4);
+ smallset_insert(&b, 15);
+ smallset_insert(&b, 6);
+ smallset_insert(&b, 9);
+ smallset_insert(&b, 10);
+
+ smallset_intersection(&s, &a, &b);
+
+ CU_ASSERT(smallset_lookup(&s, 0) == 0);
+ CU_ASSERT(smallset_lookup(&s, 1) == 0);
+ CU_ASSERT(smallset_lookup(&s, 2) == 0);
+ CU_ASSERT(smallset_lookup(&s, 3) != 0);
+ CU_ASSERT(smallset_lookup(&s, 4) != 0);
+ CU_ASSERT(smallset_lookup(&s, 5) == 0);
+ CU_ASSERT(smallset_lookup(&s, 6) == 0);
+ CU_ASSERT(smallset_lookup(&s, 7) == 0);
+ CU_ASSERT(smallset_lookup(&s, 8) == 0);
+ CU_ASSERT(smallset_lookup(&s, 9) == 0);
+ CU_ASSERT(smallset_lookup(&s, 10) == 0);
+ CU_ASSERT(smallset_lookup(&s, 11) == 0);
+ CU_ASSERT(smallset_lookup(&s, 12) == 0);
+ CU_ASSERT(smallset_lookup(&s, 13) == 0);
+ CU_ASSERT(smallset_lookup(&s, 14) == 0);
+ CU_ASSERT(smallset_lookup(&s, 15) != 0);
+ CU_ASSERT(smallset_lookup(&s, 16) == 0);
+
+ smallset_clear(&s);
+}
+
+void test_smallset_tonstr()
+{
+ smallset s;
+ smallset_init(&s, 25);
+
+ char buffer[256];
+
+ smallset_tonstr(buffer, 256, &s);
+ CU_ASSERT(strncmp(buffer, "{}", 2) == 0);
+
+ smallset_insert(&s, 1);
+ smallset_tonstr(buffer, 256, &s);
+ CU_ASSERT(strncmp(buffer, "{1}", 3) == 0);
+
+ smallset_insert(&s, 12);
+ smallset_tonstr(buffer, 256, &s);
+ CU_ASSERT(strncmp(buffer, "{1, 12}", 6) == 0);
+
+ smallset_clear(&s);
+}
+
+void test_smallset_getone()
+{
+ smallset s;
+ smallset_init(&s, 17);
+
+ CU_ASSERT(smallset_getone(&s) == SMALLSET_IS_EMPTY);
+
+ smallset_insert(&s, 3);
+ smallset_insert(&s, 15);
+ smallset_insert(&s, 4);
+
+ CU_ASSERT(smallset_getone(&s) == 3);
+
+ smallset_clear(&s);
+}
+
+void test_smallset_empty()
+{
+ smallset s;
+ smallset_init(&s, 17);
+
+ CU_ASSERT(smallset_getone(&s) == SMALLSET_IS_EMPTY);
+
+ smallset_insert(&s, 3);
+ smallset_insert(&s, 15);
+ smallset_insert(&s, 4);
+
+ CU_ASSERT(smallset_getone(&s) == 3);
+
+ smallset_empty(&s);
+
+ CU_ASSERT(smallset_getone(&s) == SMALLSET_IS_EMPTY);
+
+ smallset_clear(&s);
+}
+
+void test_smallset_cardinality()
+{
+ smallset s;
+ smallset_init(&s, 7*50);
+
+ uint64_t i,j;
+ for(i = 0; i < 50; i++) {
+ for(j = 0; j < 7; j++) {
+ smallset_insert(&s, i*7 + j);
+ }
+ CU_ASSERT(smallset_cardinality(&s) == 7*(i+1));
+ }
+ smallset_clear(&s);
+}
diff --git a/utils/test/test_smallset.h b/utils/test/test_smallset.h
@@ -0,0 +1,16 @@
+#ifndef TEST_SMALLSET_H
+#define TEST_SMALLSET_H
+
+#include <CUnit/Basic.h>
+#include "../smallset.h"
+
+void test_smallset_init();
+void test_smallset_insert();
+void test_smallset_lookup();
+void test_smallset_intersection();
+void test_smallset_tonstr();
+void test_smallset_getone();
+void test_smallset_empty();
+void test_smallset_cardinality();
+
+#endif
diff --git a/utils/test/test_stack_sd.c b/utils/test/test_stack_sd.c
@@ -0,0 +1,141 @@
+#include "test_stack_sd.h"
+
+void test_stack_sd_init()
+{
+ stack_sd s;
+ stack_sd_init(&s);
+
+ CU_ASSERT(s.nmemb == 0);
+ CU_ASSERT(s.alloc == BASE_STACK_SD_SIZE);
+ CU_ASSERT(s.data != NULL);
+
+ stack_sd_clear(&s);
+
+ stack_sd_init_size(&s, 4);
+
+ CU_ASSERT(s.nmemb == 0);
+ CU_ASSERT(s.alloc == 4);
+ CU_ASSERT(s.data != NULL);
+
+ stack_sd_clear(&s);
+}
+
+void test_stack_sd_push()
+{
+ stack_sd s;
+ stack_sd_init_size(&s, 4);
+
+ sd topush[5];
+ size_t i;
+ for(i = 0; i < 5; i++) {
+ sd_init_u64(&topush[i], i);
+ stack_sd_push(&s, topush[i]);
+
+ CU_ASSERT(s.nmemb == i+1);
+ }
+ CU_ASSERT(s.nmemb == 5);
+ CU_ASSERT(s.alloc == 8);
+
+ CU_ASSERT(memcmp(s.data, topush, sizeof(*topush) * 5) == 0);
+
+ for(i = 0; i < 5; i++) sd_clear(&topush[i]);
+ stack_sd_clear(&s);
+}
+
+void test_stack_sd_get()
+{
+ stack_sd s;
+ stack_sd_init(&s);
+
+ sd topush[20];
+ size_t i;
+ for(i = 0; i < 20; i++) {
+ sd_init_u64(&topush[i], i);
+ stack_sd_push(&s, topush[i]);
+ }
+
+ sd tmp;
+ for(i = 0; i < 20; i++) {
+ tmp = stack_sd_get(&s, i);
+ CU_ASSERT(tmp.size == topush[i].size);
+ CU_ASSERT(tmp.data == topush[i].data);
+ }
+
+ for(i = 0; i < 5; i++) sd_clear(&topush[i]);
+ stack_sd_clear(&s);
+}
+
+void test_stack_sd_getlast()
+{
+ stack_sd s;
+ stack_sd_init_size(&s, 8);
+
+ sd topush[20];
+ size_t i;
+ for(i = 0; i < 20; i++) {
+ sd_init_u64(&topush[i], i);
+ stack_sd_push(&s, topush[i]);
+ }
+
+ sd tmp = stack_sd_getlast(&s);
+ CU_ASSERT(tmp.size == topush[19].size);
+ CU_ASSERT(tmp.data == topush[19].data);
+
+ for(i = 0; i < 5; i++) sd_clear(&topush[i]);
+ stack_sd_clear(&s);
+}
+
+void test_stack_sd_pop()
+{
+ stack_sd s;
+ stack_sd_init_size(&s, 8);
+
+ sd topush[20];
+ size_t i;
+ for(i = 0; i < 20; i++) {
+ sd_init_u64(&topush[i], i);
+ stack_sd_push(&s, topush[i]);
+ }
+
+ sd tmp;
+ for(i = 0; i < 20; i++) {
+ tmp = stack_sd_pop(&s);
+ CU_ASSERT(tmp.size == topush[19-i].size);
+ CU_ASSERT(tmp.data == topush[19-i].data);
+ }
+
+ tmp = stack_sd_pop(&s);
+ CU_ASSERT(tmp.size == STACK_SD_EMPTY_POP.size);
+ CU_ASSERT(tmp.data == STACK_SD_EMPTY_POP.data);
+
+ tmp = stack_sd_pop(&s);
+ CU_ASSERT(tmp.size == STACK_SD_EMPTY_POP.size);
+ CU_ASSERT(tmp.data == STACK_SD_EMPTY_POP.data);
+
+ for(i = 0; i < 5; i++) sd_clear(&topush[i]);
+ stack_sd_clear(&s);
+}
+
+void test_stack_sd_lookup()
+{
+ stack_sd s;
+ stack_sd_init_size(&s, 8);
+
+ sd topush[20];
+ size_t i;
+ for(i = 0; i < 20; i++) {
+ sd_init_u64(&topush[i], i);
+ stack_sd_push(&s, topush[i]);
+ }
+
+ sd tmp;
+ sd_init_u64(&tmp, 13);
+ CU_ASSERT(stack_sd_lookup(&s, tmp) == 13);
+ sd_clear(&tmp);
+ sd_init_u64(&tmp, 22);
+ CU_ASSERT(stack_sd_lookup(&s, tmp) == STACK_SD_LOOKUP_NOT_FOUND);
+ sd_clear(&tmp);
+
+ for(i = 0; i < 5; i++) sd_clear(&topush[i]);
+ stack_sd_clear(&s);
+}
diff --git a/utils/test/test_stack_sd.h b/utils/test/test_stack_sd.h
@@ -0,0 +1,14 @@
+#ifndef TEST_STACK_SD_H
+#define TEST_STACK_SD_H
+
+#include <CUnit/Basic.h>
+#include "../stack_sd.h"
+
+void test_stack_sd_init();
+void test_stack_sd_push();
+void test_stack_sd_get();
+void test_stack_sd_getlast();
+void test_stack_sd_pop();
+void test_stack_sd_lookup();
+
+#endif
diff --git a/utils/test/test_stack_str.c b/utils/test/test_stack_str.c
@@ -0,0 +1,78 @@
+#include "test_stack_str.h"
+
+void test_stack_str_init()
+{
+ stack_str t;
+ stack_str_init(&t);
+
+ CU_ASSERT(t.nmemb == 0);
+ CU_ASSERT(t.alloc > 0);
+ CU_ASSERT(t.data != NULL);
+
+ stack_str_clear(&t);
+}
+
+void test_stack_str_push()
+{
+ stack_str t;
+ stack_str_init(&t);
+
+ uint64_t i;
+ char buf[2*BASE_STACK_STR_SIZE][256];
+ for(i = 0; i < 2*BASE_STACK_STR_SIZE; i++) {
+ snprintf(buf[i], 256, "%llu", i);
+ stack_str_push(&t, buf[i]);
+ }
+
+ CU_ASSERT(t.alloc == 2*BASE_STACK_STR_SIZE);
+ CU_ASSERT(t.nmemb == 2*BASE_STACK_STR_SIZE);
+ for(i = 0; i < 2*BASE_STACK_STR_SIZE; i++) {
+ CU_ASSERT(strncmp(buf[i], t.data[i], 256) == 0);
+ }
+
+ stack_str_clear(&t);
+}
+
+void test_stack_str_get_getlast()
+{
+ stack_str t;
+ stack_str_init(&t);
+
+ uint64_t i;
+ char buf[2*BASE_STACK_STR_SIZE][256];
+ for(i = 0; i < 2*BASE_STACK_STR_SIZE; i++) {
+ snprintf(buf[i], 256, "%llu", i);
+ stack_str_push(&t, buf[i]);
+ }
+
+ for(i = 0; i < t.nmemb; i++) {
+ CU_ASSERT(stack_str_get(&t, i) == buf[i]);
+ }
+ CU_ASSERT(stack_str_getlast(&t) == buf[2*BASE_STACK_STR_SIZE-1]);
+
+ stack_str_clear(&t);
+}
+
+void test_stack_str_pop()
+{
+ stack_str t;
+ stack_str_init(&t);
+
+ char* strs[3] = {"hello", "world", "this is a msg"};
+
+ stack_str_push(&t, strs[0]);
+ stack_str_push(&t, strs[1]);
+ stack_str_push(&t, strs[2]);
+
+ CU_ASSERT(t.nmemb == 3);
+ CU_ASSERT(stack_str_pop(&t) == strs[2]);
+ CU_ASSERT(t.nmemb == 2);
+ CU_ASSERT(stack_str_pop(&t) == strs[1]);
+ CU_ASSERT(t.nmemb == 1);
+ CU_ASSERT(stack_str_pop(&t) == strs[0]);
+ CU_ASSERT(t.nmemb == 0);
+ CU_ASSERT(stack_str_pop(&t) == STACK_STR_EMPTY_POP);
+ CU_ASSERT(t.nmemb == 0);
+
+ stack_str_clear(&t);
+}
diff --git a/utils/test/test_stack_str.h b/utils/test/test_stack_str.h
@@ -0,0 +1,12 @@
+#ifndef TEST_STACK_STR_H
+#define TEST_STACK_STR_H
+
+#include <CUnit/Basic.h>
+#include "../stack_str.h"
+
+void test_stack_str_init();
+void test_stack_str_push();
+void test_stack_str_get_getlast();
+void test_stack_str_pop();
+
+#endif
diff --git a/utils/test/test_stack_u64.c b/utils/test/test_stack_u64.c
@@ -0,0 +1,72 @@
+#include "test_stack_u64.h"
+
+void test_stack_u64_init()
+{
+ stack_u64 t;
+ stack_u64_init(&t);
+
+ CU_ASSERT(t.nmemb == 0);
+ CU_ASSERT(t.alloc > 0);
+ CU_ASSERT(t.data != NULL);
+
+ stack_u64_clear(&t);
+}
+
+void test_stack_u64_push()
+{
+ stack_u64 t;
+ stack_u64_init(&t);
+
+ uint64_t i;
+ for(i = 0; i < 2*BASE_STACK_SIZE; i++) {
+ stack_u64_push(&t, i);
+ }
+
+ CU_ASSERT(t.alloc == 2*BASE_STACK_SIZE);
+ CU_ASSERT(t.nmemb == 2*BASE_STACK_SIZE);
+ for(i = 0; i < 2*BASE_STACK_SIZE; i++) {
+ CU_ASSERT(t.data[i] == i);
+ }
+
+ stack_u64_clear(&t);
+}
+
+void test_stack_u64_get_getlast()
+{
+ stack_u64 t;
+ stack_u64_init(&t);
+
+ uint64_t i;
+ for(i = 0; i < 2*BASE_STACK_SIZE; i++) {
+ stack_u64_push(&t, i);
+ }
+
+ for(i = 0; i < t.nmemb; i++) {
+ CU_ASSERT(stack_u64_get(&t, i) == i);
+ }
+ CU_ASSERT(stack_u64_getlast(&t) == 2*BASE_STACK_SIZE-1);
+
+ stack_u64_clear(&t);
+}
+
+void test_stack_u64_pop()
+{
+ stack_u64 t;
+ stack_u64_init(&t);
+
+ stack_u64_push(&t, 13);
+ stack_u64_push(&t, 16);
+ stack_u64_push(&t, 17);
+
+ CU_ASSERT(t.nmemb == 3);
+ CU_ASSERT(stack_u64_pop(&t) == 17);
+ CU_ASSERT(t.nmemb == 2);
+ CU_ASSERT(stack_u64_pop(&t) == 16);
+ CU_ASSERT(t.nmemb == 1);
+ CU_ASSERT(stack_u64_pop(&t) == 13);
+ CU_ASSERT(t.nmemb == 0);
+ CU_ASSERT(stack_u64_pop(&t) == STACK_U64_EMPTY_POP);
+ CU_ASSERT(t.nmemb == 0);
+
+ stack_u64_clear(&t);
+}
diff --git a/utils/test/test_stack_u64.h b/utils/test/test_stack_u64.h
@@ -0,0 +1,12 @@
+#ifndef TEST_STACK_U64_H
+#define TEST_STACK_U64_H
+
+#include <CUnit/Basic.h>
+#include "../stack_u64.h"
+
+void test_stack_u64_init();
+void test_stack_u64_push();
+void test_stack_u64_get_getlast();
+void test_stack_u64_pop();
+
+#endif
diff --git a/utils/test/testfile1.txt b/utils/test/testfile1.txt
@@ -0,0 +1,2 @@
+Hello, this is a test file.
+It contains two rows.
+\ No newline at end of file
diff --git a/utils/test/testfile2.txt b/utils/test/testfile2.txt
@@ -0,0 +1,2 @@
+4711ashdha65---1337asd
+addasda1asdl0asd
diff --git a/utils/test/tests.c b/utils/test/tests.c
@@ -0,0 +1,87 @@
+#include <stdlib.h>
+#include <assert.h>
+#include <stdio.h>
+#include <CUnit/Basic.h>
+
+#include "test_reading.h"
+#include "test_stack_u64.h"
+#include "test_stack_str.h"
+#include "test_sd.h"
+#include "test_smallset.h"
+#include "test_stack_sd.h"
+#include "test_ht.h"
+
+CU_pSuite add_suite(char* name, CU_InitializeFunc pInit, CU_CleanupFunc pClean)
+{
+ CU_pSuite pSuite = NULL;
+
+ if (CUE_SUCCESS != CU_initialize_registry()) exit(CU_get_error());
+
+ pSuite = CU_add_suite(name, pInit, pClean);
+ if (NULL == pSuite) {
+ CU_cleanup_registry();
+ exit(CU_get_error());
+ }
+
+ return(pSuite);
+}
+
+void add_test(CU_pSuite s, char* desc, CU_TestFunc fn)
+{
+ if(NULL == CU_add_test(s, desc, fn)) {
+ CU_cleanup_registry();
+ exit(CU_get_error());
+ }
+}
+
+int main() {
+ if (CUE_SUCCESS != CU_initialize_registry()) return CU_get_error();
+
+ CU_pSuite s_all = add_suite("suite_all", NULL, NULL);
+
+ add_test(s_all, "reading - readall()", test_reading_readall);
+ add_test(s_all, "reading - readlines()", test_reading_readlines);
+ add_test(s_all, "reading - read_next_u64()", test_reading_read_next_u64);
+ add_test(s_all, "reading - sread_next_u64()", test_reading_sread_next_u64);
+
+ add_test(s_all, "stack_u64 - init()", test_stack_u64_init);
+ add_test(s_all, "stack_u64 - push()", test_stack_u64_push);
+ add_test(s_all, "stack_u64 - get_getlast()", test_stack_u64_get_getlast);
+ add_test(s_all, "stack_u64 - pop()", test_stack_u64_pop);
+
+ add_test(s_all, "stack_str - init()", test_stack_str_init);
+ add_test(s_all, "stack_str - push()", test_stack_str_push);
+ add_test(s_all, "stack_str - get_getlast()", test_stack_str_get_getlast);
+ add_test(s_all, "stack_str - pop()", test_stack_str_pop);
+
+ add_test(s_all, "sd - init()", test_sd_init);
+ add_test(s_all, "sd - cmp()", test_sd_cmp);
+ add_test(s_all, "sd - hash()", test_sd_hash);
+ add_test(s_all, "sd - sd_conv_u64()", test_sd_conv_u64);
+ add_test(s_all, "sd - sd_get_str()", test_sd_get_str);
+
+ add_test(s_all, "smallset - init()", test_smallset_init);
+ add_test(s_all, "smallset - insert()", test_smallset_insert);
+ add_test(s_all, "smallset - lookup()", test_smallset_lookup);
+ add_test(s_all, "smallset - intersection()", test_smallset_intersection);
+ add_test(s_all, "smallset - tonstr()", test_smallset_tonstr);
+ add_test(s_all, "smallset - empty()", test_smallset_empty);
+ add_test(s_all, "smallset - cardinality()", test_smallset_cardinality);
+
+ add_test(s_all, "stack_sd - init()", test_stack_sd_init);
+ add_test(s_all, "stack_sd - push()", test_stack_sd_push);
+ add_test(s_all, "stack_sd - get()", test_stack_sd_get);
+ add_test(s_all, "stack_sd - getlast()", test_stack_sd_getlast);
+ add_test(s_all, "stack_sd - pop()", test_stack_sd_pop);
+ add_test(s_all, "stack_sd - lookup()", test_stack_sd_lookup);
+
+ add_test(s_all, "ht - init()", test_ht_init);
+ add_test(s_all, "ht - insert()", test_ht_insert);
+ add_test(s_all, "ht - lookup()", test_ht_lookup);
+
+ /* Run all tests using the CUnit Basic interface */
+ CU_basic_set_mode(CU_BRM_VERBOSE);
+ CU_basic_run_tests();
+ CU_cleanup_registry();
+ return CU_get_error();
+}