commit 3775ab7a1c13ffeed791ba882144da622b5e543b
Author: olikru <olikru@tkruger.se>
Date: Fri, 5 Jan 2024 21:56:38 +0100
god hjul
Diffstat:
230 files changed, 21659 insertions(+), 0 deletions(-)
diff --git a/.clangd b/.clangd
@@ -0,0 +1,2 @@
+CompileFlags:
+ Add: [-xc, -std=c99, -I../utils, -std=c99, -pedantic, -Wall, -Werror, -Wstrict-prototypes, -Wmissing-prototypes, -Wmissing-declarations, -Wshadow, -Wpointer-arith, -Wcast-qual, -Wsign-compare, -O2, -fstack-protector-all, -Wtype-limits, -fno-common, -fno-builtin, -I/usr/local/include, -I/usr/local/include/flint, -I/usr/local/include/igraph]
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
+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 b/README
@@ -0,0 +1,22 @@
+Advent of Code '23
+==================
+
+Mine (krutimyltan2's) solutions for the challenges in Advent of Code
+2023. 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,5 @@
+* Add unit tests for sread_next_i64.
+* Add unit tests for new utils (wdg, graph, fheap etc.)
+* Redo day20, but with a general, non-shitty heuristic solution.
+* Redo day23 by implementing dynamic programming solution to
+ longest simple path problem.
diff --git a/day1/Makefile b/day1/Makefile
@@ -0,0 +1,30 @@
+CC=clang
+CFLAGS+=-std=c99 -pedantic -Wall -Werror -Wstrict-prototypes
+CFLAGS+=-Wmissing-prototypes -Wmissing-declarations -Wshadow
+CFLAGS+=-Wpointer-arith -Wcast-qual -Wsign-compare
+CFLAGS+=-O2 -g
+CFLAGS+=-fstack-protector-all -Wtype-limits -fno-common
+CFLAGS+=-fno-builtin
+CFLAGS+=-I/usr/local/include
+CFLAGS+=-I../utils
+#LDFLAGS=
+
+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) $(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)
+
+utils:
+ make -C ../utils
+
+clean:
+ rm -rf common.o uppga uppgb
diff --git a/day1/common.c b/day1/common.c
@@ -0,0 +1,3 @@
+#include "common.h"
+
+size_t fn(char **lines, size_t nlines) { return 0; }
diff --git a/day1/common.h b/day1/common.h
@@ -0,0 +1,12 @@
+#ifndef COMMON_H_
+#define COMMON_H_
+
+#include <assert.h>
+#include <reading.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+size_t fn(char **lines, size_t nlines);
+
+#endif
diff --git a/day1/input b/day1/input
@@ -0,0 +1,1000 @@
+6798seven
+six8b32csscsdgjsevenfivedlhzhc
+fcvvkvjjnhfivesixfiveninesxlvnhfckc54
+feightwo4twofivefour
+cgpzm2sevenone68636
+498879
+fivetwo2plltvdfourhhgrfn
+onertxzlzdnxn2seven
+ninethree4v1five
+5pnnss16lzbsmcckeightdseven
+jthree249four2cjzqmmbrqnnine
+foursixfourfbgvqm1rchdlmzhtzqqfjzpmln
+twojtwoscbrtgmnqzvbfbzvrtkxhmf76nine
+2fourtwo
+svxz8bjvt5zzvjzhkmtmnnft92
+threetffnjvkfh81nineqqshzdf2vtjfqjtbdv
+seven1drfivethreedpqflxgdshlzmmnrb
+7sggjxkcxfourthreefourtwos3nine
+39t6rvkbdnfpssj6djnfbqklkgfsqbf
+3four2zcfvtplkrbeight274
+one7sixninesix
+kkxmtmdthree6jrj6
+81sevenmnine1llbqrsprc
+5nine9qgjceight
+three1sdmq9sevenfournine
+khnlbmzhvlsix3
+nineone6onesixvlnlxeightfive
+schplznseveneightnlcxgr7four
+6one1djcdmpdrgq3two
+fourzhpnphmq52r813four
+scsxjthreefoureight2fivepfmpfj8
+69xvbxfffmr7one8gmch8
+one8tfpgrdhm
+2gxmhtfrbrkpdvlvsmdqrktxtrpssbrv933
+4vfrtkdqlbtwordlbppsssp
+2cjmtvnzpbkdcq5twofourtwo
+2three5onetwogpfqtszbjh
+hgvnine9four996
+37142745
+four73
+8552ztclnd
+onevmpd76eighth
+threethree8
+bgtwonedrmc35
+23one
+9lpxzhkck2five3qone9zgxzrzd
+hs1
+92xhflsixltpqprpfggbzrvmfqone4
+eight9sevenpcxvl6two1
+rceightwo6jc1nvllxsstqgnlhtl4
+tlnhlsixfn3lbdlqztmkthreedllfourone
+74five
+dcfpstvxnd52kdqhlht
+7onenine
+2twothreehdzssrt1
+eightseveneight54xflfspthreefsfbtbslx
+4ffsfsvkxslvp
+939flgbmvzpvfsmtcsix3
+742
+qcfive72plvnd7
+5hhd8onejbsfklmpzcgffivenine
+twodsmjkhdxjdgktlrteightseven2cttnpjsv
+31kptdmtwojrgp
+dnnmrflcft92
+7gtglplfkrnine85xm7
+voneightznktfvmxlhnine1seven4z
+24sevenncdmcpkrvnxlbeightsixlrvns
+38prmrxcm5
+4vhncsevenjgvjllppvcfmvrlsdtkqcldpq
+81phvtb
+5l7twoeightlr
+8xfqbnone5
+62737sixfourdfqvdcone
+seven1two
+79qncxqcj1one3
+69four3two7six2six
+six499
+gknlkqvntvmsjzlfb7one
+honeightmjlmvmbxsmjzg77
+6seven15
+five59two91
+gmhhtq9368gtsdg
+nlmbvxckjtwofourfjnine47threefive
+93eightnpkjf26one4
+qcslmgkkgbsnrr6ninennr
+8381three2threeone
+7hnqndhs8
+qd65
+twogtlrqrlvfourfour5qsixdjhvqvdlljnvbtkq
+6seven8ldvkz
+gf14sevenrv
+2fourpkzdklbvm2
+four26jsrbsrxdlmzntsxgg
+tghcz8fourthree
+threethree8hzlvpjzxcdfvcpjbmc942
+jktsix2cprnhkkktjcvkvtkdggvrscf
+dzhh82
+nine8tsix
+9fivernlsl6jvfrljzjg
+52d
+threethree556nine
+g2twoblhhptzdqbbnnrpseven5
+jfive8
+eighttwotwofiveqdfr9
+kqxncc74sjttqklx3lxpffbdlthreetwooneightnb
+1xpvjzvplfjdsjqrtmzbknine
+five4r6five
+72eight
+1kzvxckdbjjpprrqn4eight6onebsdmrcxqznjtbnh
+htwocglz3jggvkcbzvtconeeight7
+twozspgcxf5bhx
+ntglpd1six1bv1
+5zxgrdlhkmzsix47t43
+kfrnghxgfzpjxmstwofourkzvcsksixfive1
+grnd423
+8f
+1xcqchtnsix4tvtffone
+bxlbtwotwoeight9twoseveneight
+7ldngmndg96pjnfour
+five4threexp
+mtwonexp7nine3z9
+8kg95ninesixtwonem
+sixpmvfoursevenz8m
+vrszvbtvtr28pzcjxkztzhvmtqvhnqf3
+1gsbtwopjkrrqc1one
+tbmsix93
+n4
+kffgtgcl866364
+one4qgkzthpmeight8eightfourkdcnpxv6
+cfhlmng21five
+8lhcseven9vksfgpvlnfq3bglktc
+twocc2rpflzhqseventhree
+six1fourfivefive5onesnpz
+1ffqfxh75flgjqcx
+fourthree1twortvlvcsvs2
+8rxrpvxthreestbbpcszhnbrsfour
+6qdkshgrsjxxsvpmnjxnzmcone71fckgjbrsnq
+8568three2eight
+1khdqskj
+onebdfour6
+dpcpqnineqjnfzffsb5tj1ccm4four
+nsrvffqhd67sixtwoseventwohdgh3
+nvsscfour973fsngxbm6
+93zzrgmsqtlckzrnbbk4seven
+3seventhreexpfrrfpfiverv7
+threeeightfourfoureightnine1one8
+7onethreefour33cghone
+sevenfivesixseven2
+jgbgmcx76qc
+zxbpvj7
+21xlcgpshvth96fourtwokcvmhcdtxnm
+foursix2
+6three9nine4sevennine
+dqnhdnine3
+seven58vzcxqmffive7
+xdmeightwomncvnkdkpxtwoonenineseven1tclckshvptwo
+gsdff22fivethreebn
+one7gd
+jcz8xxfdlphz5threepzmjqzfb39qllhvcqj
+fivesvjdbqlvgnvkcklszeightcjhdjxdvchfive9
+9sfgxbtcgbk
+six4zvfivelxfghffvq9bfkshrkmbn
+sdtxjnnjjp3fivejsll5
+tpeightwozhzqxjstneightsixgbjlmsjfls6tlc
+668ninenine
+three7two
+gtskqnine1seven862mm
+487jsqqfkzfcs2lthng7five
+gjks7
+lfnqzjphssevenone2qvfiveninexhr
+fvfgnddffhjjfour9six9
+ttkmtncjc9five5eight3
+3seven24426four
+two9jnd5eight
+threeonevmzqdxvjlqxgzqone1hcpqsd43
+tfzzzjjbx7oneeightbqthree
+68onerrpvsixvkmnrndq
+jbjljljmtwoqgt3kpvdkdsixone
+kxvbxzzxrfour2slfjkkgq555gxfsix
+three9tsthree
+eighttbtdg2sevenxsqsq
+seven213jbqmvmvvhsixrfqhlfive
+nsvcdhkbdmxqbkthree28ztjtlsqprcplmx
+4lntqfk4tkmmgkvrcninenineonelpjtq
+221eightqfp7eightzshhl
+vppzgrsix1fmvpcpkvsvppspqcsixone
+5lhcrxclclcsix4
+qhone2mhhxqqdl73seven5
+5three9hdnfrgfjsfive7
+grcfbvfkj4
+487mzcgxvxqgx
+four8nine3four3lpqnclxzzbmjztbhdfdjfive
+3six6kbrvjjsndlxvsz5qcfmtzsqlmqbrn
+klcx6eightsix2onesixthree
+8ztdfdglxhjxmmvktwolsrr5six7
+9two66three
+6threesixtgnznd
+ggglpldvkkhgmrgt3
+9kktwo3srdtpskbbx446
+7xmrfkbsr5nzqfgseveneightcbshpfour
+six5eightseven5gzsjfthree21
+2897cgv
+dffvs7zrlrvlkjcfourjxsndkzq4
+eight22blzxvvshgtqlqpqhsixctp
+three8bgjhkvnbdvbttblp1fivenxslnseven
+3one21x73twongdnb
+kfzzhhctgrlznqcdvzshlfive56pdqx
+cfsthhgvgfddmsjn83sjrrkxzl
+four99tfvbtxgfqrlhcdktmp
+3rfhfgcf8six2
+onexsbxqmqkj3hrblqnfrseven
+hfgnvtdzzb51gtljm9eight
+zprhsph3
+sixsevennine2four715nine
+fzxzkcvcxl4
+lcnkqqsrtwogcbvxrtfp2five5three2
+7ninesix9jxhrdqrpr94
+lxpqxseven2three
+mnsjjgdlltwodrcfltwo8vninemqlfqsgccl3
+sevennfkfvxsqr7twotwonedb
+7twonpkjfjmgqxsxpdtninetpsfjlqvv
+seventhree328sixscxmpqjlxftwo
+3qpxvglmpcgxzrseven9
+6onemqrvdmckhmdrzxzkxbjthreeeighttwoql
+sevenfdpqqzpbflflgph698eight9
+fivedbntvzzdq36two3
+8six3fivefivefivesevenpxqpxrjqseven
+sixtwoqt4
+tmcfive4zkxhvlrvfzhkczpkvbxk1
+rbrnxxbfxmbqscltvsixone79three
+88sixzqntjsfhqj6three43
+pmcfsrpknvbfhrzlvlcffjmfive32323
+97rtggjhvvdfive
+vtdljvqht1fivefivetwo
+88rqtpdz5nine
+rtwone725
+sghfour2eightgrgpsmfxpchmmpndccgzfzz
+kpgrhmtkxzzmdpcdzeighteight2
+5bfhbmffeight6
+8fqtr17czztqgfour4lx
+9xnbmgqgvrtwonevs
+1zqsvmcqsxjtp
+twollzsslxc37sixoneightp
+6bbgl76
+58zntvhvgdnh2
+three54
+fftdddqnninesevenone76
+6ddqzjoneeighttwothree
+56threetcp46
+21six3m
+214onethreesp6six
+652three6
+lvc1onefiveone
+6ddrgglstz
+twothreerjpb2four55
+eight8eightwoh
+fivefqckddnine7one61zlkjgxjtqq
+gzneightwovlsdvcmvj3qhbfmkdnvqone99
+92sixgxsix
+64eightxb2six
+51fivepbxrzkdzjhsixoneightmt
+ninem3nlpdtonefivethree6six
+lvxf3nine1eight
+vvbvfvtninefive5onezgtsjplxc
+qltld5p9tgpmkzrf4
+71six
+2threergjrcqsixhgjtdkjpqnglzgdpqntnqtzcfcbb3
+7xfj5btrml3two
+979nzpjkcthcl13tnfour
+one1jseven6three7five
+tppnljghmhxplmnjgfmpfourtkffqcghxx9four9
+396
+onettfdjdd5msplxhlqvv12
+7mrqgcxbbtwo6seven5oneonesix
+hjnq8vbshrbxeight9sixlxznhqgcc
+sixzq9nnq4lxzhzmzjmnbtfbkf
+vfjhmf3ksgnlzzhsdtwotg9eight
+ddztjmr453qghvzrtsgf
+55lzcrzseven39
+onecggvnjfpone27qrzcrxvp6
+286hfzchgcgtcqhr
+ngeighteightfive5mbdn
+l1five
+712onekndmfive6ntrmsk8eightwop
+hqgfive512fourhgrm
+vpdvhpkngnntqptmsevenoneseven619
+ninesevenckpjpxszfv1jzxtptvrdkfourfour
+tjlcs5onetxfkq6hzfklslthreeeight
+mxjrssqxt7one7hnffgqcgsthree
+onefsxjsnzxncsix1rr
+four725deight
+sgssrlckfourprpsix5rktmjhxksgmvdqmnkndjls
+75eightr6three
+6threesixx1sixsixcbxxcxvnhsgl
+4fiveeightkj9fivemqzvcc
+ncgqljseveneight61nbcv
+three83pnineskc
+fivehninesevensix5
+five617twosr6nine
+ncjjfvzzmghgq8
+2n48twodpnpgq
+qpgnxtvhq1jcvtxlfkfour6eighttwoztzddkmpbk
+fivevhfxpjtmdj2ninesevennine9two
+fivejtxmg4hbctmpnntlpbzfmxqgthreejbjdb
+4xgrzszmhx
+28four78tmrkfndeighteightwonq
+zvnxmbtjqzblnine3five
+slmt6onetwo5sixfour
+bthreenine3five
+3fxjfivevcdmmphtrccptz
+8fourksxxsixsevenseventwofour
+fpxvbdgqxzdzxone7threeptgzhhqmkxmseven
+9six654
+foursix6559
+9fvsdcbmmghfive8one8oneone
+dlxcsjmcjpmmjr64onegtkkqkmhkl1
+pxkqbgdfour89
+nn88
+6sixthree
+1zxszmgmfg9drnjzd
+eight8onetvgzfzfjqlqtwo2dfhtwo
+kcgzq8cxdqphsglsixfivefourdbsjjmdtnxrzt
+4threenine3dpflrrtmt
+one83five
+8sixthreetwonez
+3fxnhqrrseven
+seven4onetwo
+fourbvnvbnineqggx5twovbdzztqccjhqqqnine
+qzcdgvninejbrfoursixseven24
+vknqxgpgxnl2mrmbxprseven
+kfggmlcht8sevenfourkbtdzstpsnine
+kxzhchjh77sixmvtceight4seven
+five17
+eightdgkcrphqsndn7fivevkstrsprktqdrdxqslmjtz
+2njqktntzjtwo7
+four66
+975eightnczdclht
+twofour1mlbpb6d
+ddleightwo64
+2239gksfnlvtg1
+jqrmqdkv1mhsjbqhhhjrvftwofour6
+fjglfourone74nlxzmxfkbn3three
+6pseven1
+1nscmsconek3
+r182nine23
+rqvstbf5seven1
+mmtrqgddjone2
+n23fivelvprvxstrct5
+loneightgmlqfl7nineqrtmzdbbjmnfivepqhgtmb
+sixfivefourtwoone3
+five39hjjcjktlcsixfive7eight
+sixeightthree5three
+5threeninebnbgxvnmfknp2dhbdb7nine
+5cpljvtxtpbvzbdrdvsdgc23sixtwo
+4fiverlflt549
+two1onefoursixmzm
+4eightjksktjdvxsckgllpzdvblssix
+xsxkj81vkstvjjtm5sevenfive
+8943qxpcfqpnqtwo
+58qnrthreethree1eight5
+6gqcfk
+49lxnllkqrdgcxdrfv
+94nine7six8nine
+55six6dgshxnn
+sixthreeeightfourbgnhsnjone1
+nine3qmpnnzldoneddthreethree
+14ljmrtmhmeight8
+onetwo4eight31loneighttc
+jnkg8lbjjvclcvmbseven3tdvnmrp
+7qxklg
+7dtwosixthree6
+sevenfivesixsgltjpcnthree2
+15rzct
+tfn4ninevt74nine
+1fiveseven68hztpthreexlbbgbqffvthree
+svqjgxnmxlpfjc95
+nine9bn3njvhp9eight2
+92six1threeeightwot
+sixfour2nine
+nine1bstseven45snndcpmtbq
+onesix4rkrglcvmvb
+tjccltxqljfourcfbtcqtjd1
+fourgqjb7sixeightseven6
+6four99nine8dfjp2dhzsfgt
+7kfgzrxgm7
+3nn3
+eightfzqvgrr1skhnqntgvv
+8fmghkjzmrkpthcrk6eight9two1
+qgvgggrmnine3rl9rnf
+seven6jvjfkr
+ninetwofourlsbdlmlnsixb9
+khqtjbkpdvrdnine6three
+pzninebmxq1onefourqtztvzlxf
+seven1sixcjcbfv3ninenine
+ngtsvjgmcg5mssqdgtsdrqff
+1vshninetwolfbfhckb1vfkxv
+1six3five
+93hsvjggzqcgjbqjvpnine6
+dtwo4onefpthree18
+4fourfive
+nnplsdmt962
+five83rzgdpc322threesix
+3hcqbfiveppvzvtcbjnvqjz
+khh4one2sg
+pdtltjqgqzfive8sixone9vhnzbvfnxz
+xtrxkfive83three
+three75kjjxsixfivefive5scjbbflf
+ljfcdxktbnmvbspglnjfive483
+eightonespmnrznpptmjvh68eight8
+qznqkgvkhlssszmdlvjdjjtbgz2
+6sixfourfbxrxfbv9hldlseven
+3qzjrffxdthreeoneightbc
+three4tfseven2sb
+nine87rvkdgmpt
+84threetwobjfzvncrkfour
+eightsix9plxkppkgpzkfive
+2eight4526
+hdmqlgnphg1two11
+ninekxlrjmmkm34sfvrdlb76lkbzprhnchrz
+9one26txfggnctgfive
+7pzrqmfivev
+ddqknbqxnrxlcrhcmhmr5
+eightsix121twohbtkjqljkprzdsmnv
+7eight2twoqblcpqqfckfour1
+cbnpcjljfninenine9
+73eight3eightzfzjs
+szfsgstdmtwo2sixjkgxrxbtpdbkt
+one722
+76eightrvs
+five6two7rcss5eightone
+9ckcnzponebnpjlznbrfxnkvfpsevenonebz3
+sixninedbtpcrz148tzvbhxjk
+5zlpdbxk72twotlp6qbkpvjx
+3three4sjgfjzzone8xmeight
+56tkmpbmsix5seven7
+nineeighttqrntnvxrrbkpftwovclttztwo7two
+bsxdzgxkcx5five6twoqlbqgjzbc
+five22hhlpfiveeight8vrkjcstx6
+2psmkkxflgfoursixhjmdxfccbxqb
+25kljltwoneggk
+3fhtjzffgfph8twozr
+eightsevenfbzlr7rqfivefour
+one3fourninerl49rlvgnmtlcp
+vrzcnn79txgxf5five2cftclqsg8
+kbbptjpbvvzcxrsix45prvjcq
+one3ninefour2vcpdfkbnineeight
+lx1
+1oneqphkrtwojczlpmcjseven38oneightgm
+xsnzjbzfmb685ninezmgzfkzvpzj5six
+547six
+21five6z9
+5nqcsix1seven9
+nine4fbfprrfivevdvjphcqkfourthree
+9243five
+84zmtwothree
+5c
+17three
+5gvfxttjch74eight
+ninegs7hxmgmrzsx
+dzxzfknlk5ddgsbsh
+475cbbqscvfive
+twovjtkcxpxlvqhvgsqfzmthreecg1rctndlmm
+nine7eight
+eightoneninethreebccrmone9six
+twohbjxlfxdd4462
+2fivesixdrcmbksthree
+24sevenk7
+3sixsix28
+four66vvjvqhhbhr4
+seven4fourfourprhplxheightxkgvgghlseven4
+ninegtsqsnk7fourzlmnv9
+gpr3q5twoninebqnr6
+rxhkdtwo8three2
+jljtwonesevenkckbv9four
+4scdjjmkpf33
+vjfourzrlthreeseventbbzrm8n
+two1fourxqlfqbhszveightrqcsprdonenine
+mmppkfd745ninexfour
+fxeightwo5tftddm8onexpeight
+xdbmf415cq92dhmmc
+nine3onedcvqdvhtqninepczfhhgbmzeight2
+ffsix6seven5ninelg
+xtzsnzlvvztq64zhkklcgjrfourlztxlbtgxn9qcx
+six1nbqxmq2nxhtvrnrbsflzlztghfzjgfnhmeightone
+558
+xnhsbblmlp9sevensix
+jz8eightonemrbchzmhrjcv
+3twoktr
+6fourtwosixthree
+sixfivefour7
+ljbx2nine63four
+889g7sixtwoone7
+four4one7cztqmheightwompd
+ctqnhkqzxgtxrgfzvone45eightfbvjlgkc
+8eight35two5
+6pvzljrvseven5eight
+7zhgjds1
+mxv7dtbsbzfive
+4sqhcsjb6
+954threeoners
+63three9zltqkmpbqqpd
+6sjknine6phmcxrv1three
+threeoneprqcmzrbjjvlvsf2
+gbgfr2fivehsplpdnccxkfz
+ninefnpxtgzhzvdnr7rftghqrhpv
+seven2fourfive2
+8sixeight
+gcfjqqgbcdp33five42q
+fourfourbkrj3fourfivevlpvqbkgvxcfnlnbs
+tcgzqgqq77two
+nvzgmddmhseven1zbdfjrt17
+seven8fiveninethree48
+7five8
+nine3twoeightfgdkbtph
+dzlblf4ninetwoqqj4onetvpbbfdcbvtwo
+mcmbfvszjltlzdg7zxzzlrrvfbthreeninethreefdtsvclt
+8mzcseventwoeight9kjchpd
+sgpddvmkntwo9two
+sevencgqkbcsh5
+13nine723twofour
+twodpdvppxntseventwooneseven1
+9jjpxjpxdxxkqjseven
+4seven1five
+2nineckczklc5h
+threekplnxmcjffhpfdhhhvsvsx62zrmbcpgj
+35
+8gthree
+nineffourninethree6two8
+1vsmthree67fourchzmone
+bxnrzblqnv9xprtmvnfivevkdvqmvfhgxconezvzjlxgjhp
+xtqsevenfive7fourmclszsmnqz5
+vrxnrvfivegjlqrbdtkksz9
+ninefszbsfnhbzzqhbkvxjfive7sixfive5q
+eight38nklfskv3sb
+5six4three
+onezhpqfxgsz3stfsldzdhh
+qdtwone72
+fttvpkjsf8
+8twodxeightbltlrvjjbs
+sixninesixfourxzvf5
+85twokqdh2skxgnnnnsevenzg
+lsjqvnfive4eightjbjceight3
+5eightnineglvjmdgjvt4
+cfhxfnvnsixfour8twosixsixtwo
+hmp27seveneightsix
+5two6
+d37sixeighteight
+9fdbkdm86two
+4threefbsjzzkthree723
+dgzvfszqpkfpxmvqf7onethree
+eight2fkskmljrg12kschgbrbtgmkbdzseven
+5sbdhqrsftwoqlfqblrvgghbps6ln
+2pkmljtwospqdnflmj
+nine1eighthgccrfourseven9
+eightjbptmtmmvsevenseven6fourfive
+6threeseven6eightdsbpjzc9jsmtxdfour
+4ninextnv
+threeqjrdnfjlpnine55
+1psdrj3g2msfsjktgkv61
+sevenfive9xhdcthreenine9jctjthree
+636
+2threeseven
+nnxzzcgrhcgtz4ttnfive
+seven9sixone2fbbdfqtdfg
+4jgdxjqtbqzprpjdbjc2fivethreeonexlgkxtsdmcrrh
+4threepvzzhkmlmbhzhmtb
+m5xgplrjqlztvg9
+59s68ninerrhkrkxnzm
+hknsnsf6
+trgpkmkbtlslmpqtdxfourxjspnnmhdtg1nvfxpllcrrbzjrhrstn
+92twoj7two4six
+tseven377
+p49five2
+kpffiveeightcsbjz39
+8sdmbrxbk
+1vxknsvdqnsixkfsevenzqlr9
+fiveznrsqthpbddfcpbvhhhjctp9
+plbcxgkd4tmprsxn84hdrninetwo2
+twoqzqxbkm23brhsppdnvksixtwok
+8one5
+six45tdxfmcr6
+onesix4
+fxrl57561ktxfsg
+89nine54fiveeight
+three62three5one
+6mjqxh4scvddlls
+nflfourzrrgpvftoneseven43
+7sixtf
+sixxhxkvgnbz3rbdnvgf
+ckq745ninepqk
+1snlkqn
+ninetqvcllfvcfs62qtt6seven
+59khlmz
+eightdndsvdcqneight9twonenf
+zgcnqqmlgsmfzqbkllvsknsevensix5
+8qqxshjnnsp
+xfvttdnxhz4sixsjkqhpfszn212three
+fivelssnmckseven4ftqt
+2qsqpjmcbtvxjgqhhk
+tztwone749ninelncrmvthfourpgcbxzxvs
+4threecgnjpthnsgxhxbffour8eightsvmjkg5
+458sixseven6one1smkjk
+seven4fourrgqffqthree7
+jhpxqpspbsevenhpfnrpdvfoureight5nsbsfscjlzfive9
+sldxjjnjt5dlhdtrmsixxlmgxhvpscqqthree74
+8pvfhtpghtwo6
+nfknjlfive8
+eight7sevenseven9pdvhsevendzpxpghzr
+9fgdrgsgdhtwo7238
+8nfjgxpcbbmjrhh9765dnlbsfddhf
+tkqfc7sixsixsixggqsevenzrjrxtrnh3
+fivesix9zmxpjk
+four1kvhvnhjcgz
+one6sixthreenh4
+onesixfourtzkjjlnine1kq8
+1xkl
+8six5zbonevbtbmvtjvlfive
+zmggmrj9eight
+5sixeight23
+19twobshhmblpkp68
+7fivethree22four9tghbrr2
+gc3
+6qdkjxgpseveneight1seven
+7sevenfivegpllcnbvf3khjsqtwoner
+3fivefive417
+seventhreefthree96hbrjfxlkrninetwo
+vhnlzrv4gbdldncbgqrfd5
+gfjzvfchlzrnf8fivesixthreeninesevenrsfptjcrb
+6nineninelllzx
+sevenckthree1
+8one77four8sixnsmbhbp
+ltcfm386
+bcncpxhhgbdtxh19kqkpffqx6
+pr95
+eightsix7gbtwofourvclrmgfvph4
+four6bgzbcthree1kjhkvlh
+lbffslczqninesevenr6z
+three6lpjrgbfivexzfkprdf
+31kmnnffourtwo7dkmmlrdsm
+six7fivenbljxg6onesevenzmknhdfive
+32five5sggfive
+two4four
+xlf4rtftmttzk4fhrcbxmxlsjzfour
+fivecxrsccjsgdfpfdgpfsix3sevenqgntlgvds
+pbdmldone1s
+threekpzzth3fivernp
+glglvsnineckckdblscv2one9two3
+52cvnxlxqdoneone
+kjdvcklltsttlncvgrfive9fkspxfhchml
+sfxxlhkbhqnvskxd2five
+three3ninevndkz2two
+3two9six9sixfiveoneightf
+36xq
+twoeight76
+3kfsr1tworhvpqn7zmrp3nine
+tvvtqdcx8eight6three6fqsmnd6
+3three7
+2five3eight
+tmzhzsninetjjpmqdrkh6seven8threenine
+dsvnxx6
+8xzllsdpvrjszlhlmrrsixfourninefzncn9pkgdtlb
+four2eight4bdxhqxnjlfg3hkbkp
+onehcnf9
+twosixktskmcppzx4
+xzeightwo1doneseven7sevensix1
+fourgbdz85nine
+21xrsphxlr711mjeight
+one654four
+six4sevenxl
+sixmqhtms6zp99
+497twofour3two
+6twoxrjvzhldhfour69twofjjtskmzvls
+px98skfppldqkpsix
+7qxone8kzzdlqdmsixtzrhrzrhpeight
+6eightmdsbrvhnine
+onesixjxzx1jbfnjhm3
+threerbslfnzsbtjxfcmtxzjtvbdjnqj2
+4lbmlrptworkpdtfvnfour
+2threelkvzmghvdm
+6vrvcbbqv77
+gczqmslninepphpbvd896
+seven77nsnzeight5vzgvmfrxd
+seven46fourfive1ninechrlthdhvnfn
+sp2xngkbkqbpvqgd57onenine
+7oneonenine38hpqntxsz1hxvc
+nine3sixvrsrvfrseven4
+seventsvmxxn5sixgm1kdbrkcdfive
+5eightnfblfbxrkrrmflg5
+fourxltzjthree2
+steightwojllrms39threesixvjxflgzkm
+25ckxsgcgxjf
+lpsztggf4nine73two5
+drktgkbkxlqlfvhvr8onesix1qbgjjtcf71
+4eights14five
+jqjbzqvxcjqjjjhjjk8llseven1knphmcvnjcsfdzp
+9qrthreeeightnqpnninexgprcrdsn1rgjt
+59snmrlfxhsix
+1286
+72five81gnc3
+sixtffnjthreevmhc64one
+three96fournine4ninezr
+lrzcgsgdll99
+qftkzxrlone8sixeightfour
+eight7seveneight
+kzkoneightfbptzkfive2sgbcnxg92
+v5hdone
+onevzfour75cmzkfhklp
+cxklnb9fivetbkgjdcvjhqgnmdgrjkmfjqqbjtrzqfdreight3
+six6twotwolmggvvxrtwo72
+2kcrxxbzkssixnddqsqsk
+rpjglmp8onelvzbgvbjxdthreeonelvxdtqnz
+sevennine6bvdtwo
+16mseven3twojv
+hhconeightxrnfvbqhseven3vs
+sixnine17
+2lcssbzf1three3eightbvqrsmbh
+5onezrsvkbpnsix7zjggs4
+3eightfive
+cpgtwoneonerhgncphbfsrfplbfhxrmmpfive6
+4vbsrvggrzxxcxzeighttwo
+52nine5
+7fourkczfpeightnine3eight
+zzleightwo2onecfdsqthreejbcthreerbngllphhsixgp
+3sixntzmjnrrone
+3threeeight6bqcsdklzpfmbgxxtjs
+rrbjsghzclnine833
+cfbrmlhqvtpxtpdbbcjj6eight
+6twoqmhkgpktkdprrqxpbphjn
+cmfv1eight41
+fsfdjhbeightfoursevenpmqlcf6mvfive
+qmvq9sevenseven7
+1sevenjqrsevenfmrsncppbr1six
+1eightvcpbnsqhcv56eightzthree
+five8dnxkdbsxvd
+3l76cbpbdvsix
+vdvnbr1xzlssevenszdktcqfsqxtv4
+sixtwo9qngsslvmbv39eight
+66fjjnc3threexqdctdtkseightbqpphzzm
+hsqcqb1sjkdhhdltoneeight5one
+1llpgqdfgseightfvssfive
+znqqgtlmvxnlcgxr4fourscgzzhz
+eight9onetx5vzvqln8gxblpkmtkhcl
+eightczhdvmrlm5pmnlnlnine5hxzmlzntdmqldbnfive
+one16shmhxdvzbh73dsvgvtpddls
+5lph98flssjhz
+2psmflmhcbsrvzfive176
+qzqz8sevenone
+fmhgvseven7fivejdqcsznnone
+415dsgfivethreexlfzccgn
+qplzvmmhbh598ghnhrmzvxblxncdkrfntvzdtvqr
+8fdkghntwophfnpzjllfr9
+6rfstqcmdvq9
+nmcdsbclthreeonekxnrvqgjxpsevenfour3seven
+one72rqpfourdcqrlqpcthree
+onefour6
+eightoneqqrc18
+nine3nrscbxlx4fchjdgnlvvfrnf7jfffbggjt
+four8twofivesbpgjnt
+8sixtwojhjvhfive
+ninefg8xrvpbpgbklkbfrqgdloneeight
+pbdggcfoureight5rdsssnj
+gxqzltbzfbhfdcqeight3dggjvh9xg9jxq
+fm6ninesix
+1four8xkdjzkfthone77
+fourfourseven514
+2vfq9vfzxfmsfrxjxhfqrpc
+zckzxj45onep
+nine925
+nineone1eightsixkcd8ndvhj5
+fourfoureighthbhrnsix5seven
+mpr9sevenzm5
+two415
+two2ddgkzt66sevenmdzhdzhdmzjmvrrnd
+vntvkmtqm252
+bktbrctxtwoqbjls7
+seventwo26
+22threezlhpkpmzsnbshpgt
+1pktkpfppxbjf8
+one1jzlvq
+24fivek4
+84two
+1sevensixeight13pvp2
+xvndrn85k5nr6nzgcdhlzvf8
+ninefour1
+rhztwosix7
+eight4five5sevenlzbhmsprsj
+7seven1kmzsjl8jpdssncpvcjxczdvsk4six
+zcmpfqzfxlfsxkmscs4lctqonepjkg4nine
+8onesevenzlxflf9four
+threefoursix3five
+292mhsbgktzmlqk1fourone4
+pnnftwo5
+kpjmxmseven6
+fiveonetwoqbptwo4hmzhhfmvfqbgjk
+one4bkzjstxgrv2dvzbdfztfive7three9
+monetwo6fbxbphkpdtwo2ninenvphvnxhxk
+6mgmbthree9bnine3seven5
+eightvsfnsdkgh7fourninernvkrfcx
+fourxglll561
+3eightsixeight72six7
+4fiveflsgrgznjfbsvgvbrgnm
+763
+nine57qmhfgctmnp
+eight579xgpsr
+sbpbb215jnsfoursix
+dfghm9mrcpfthree974
+bh7threeqvhttfqt
+seven7kssmdclhfd
+qdltfdhsvz5threekftjfdqbn
+four8dxncfjhvpsxdseven3kcpmpfvnfb
+nine1eightwox
+vvcfdjlpcrfnnmbcx4eight9mtcfqqqfl5fourfive
+qbcxpccssl9kvqtjncjdxsrpp8sixbnmq
+sixonexjgqthdnrpfivetgnxqv1
+eightthree33ngpkqtqgtkmcfgqqgj313
+onezfnlseven1
+2threefhcs
+3nineeightzmpvjqrvcb1tkmchzjtsrfllv
+58cjnxhzfknnkj4ninezvskrvrc
+hthree16zdtbfnlx
+tzqcksevenfour3foursix5
+qbbzz1threesevenone
+onegfzhlthree12
+gpjjzfiveone21qbrjdrz7
+xcpjznj54fivesevenfiveq
+gsevenflcgfcmqtrzstrmnine9two
+7nrsmkbqffnnvfpjgb
+tfhnnmpbzq67six
+52jhltfzqhfprmtgbmhg
+vchpblqmsvffourzkndtsg7
+eightsevenvgfpttr62hmfzf4f
+eight4four1tsvfq
+4sevensix
+vrkmjrrxnbgjbxfqxllp17four1bdm6
+2kqfd4threefour5
+44m
+foursevenrxzjfftwo5twothree
+eight4xbxqplmknhjhzm9fivetwozjrzjp
+twojtjvdmgkjsstbdgl3bhhhzvllm6qxpzxjbgn
+sixeight3sevenone
+sixfour5m5
+fqlftfrtsj9
+rpjlhht2xxnnkqktkxteightsevensix
+five3vbklfdmpsevenone2thxcmzktlz
+fivefour7lxhg
+49gcb8fqc3fnstcnmdneighttwo
+2vd
+6tfpxszrkdsgphdsblkqfk
+43rjxkfgdm4gkxnvdfxs
+6225eight3
+8one35four3
+prsevennineeightfour8
+twozqdxfg363zczthree
+eight9vcncjcbxhnfeight
+meightjdg2vp73
+seventhree9dzdhprp
+btwoninegnfpfhxkvv3
+threegkxmmxzsmblsjfds8seven
+crbbpggzbfsjb8kqqgk9fourflghlzbgseven
+sixsix85eight5
+nmrvnmgdrtwo8three
+gqntwoneseven95eight1vtthdng1cgvxlvstgm
+oneqcftjqnxckthreegtsxfjbrmv2
+threekdfzqhqeight54four7twonep
+525xtwomtcgmfhbjninepkpjjsf
+1sevenxvgjdznvnjftwolvmjmg
+ppbgncvclfive45
+three6386qxzsvxpbz4onejt
+szxc93tfh
+zdxgxlj9nine
+9kkmgczf
+4six3six97qcxxgmppgkll
+6fivethreefourtwo
+nine9qpngcdftwo1seven7kzsjxqbggxone
+sevenninegfjkxkbptwo7nine3xjgsxh
+6srqfplffour81threefive3
+869
+nnsjzlrjcsnpd7zcfive
+fivenmndbmjngpsvkjsbqxvncm6qjzcktnsevennlxpbkchk
+three4eightwol
+2gnbninedt
+1twoninefour8
+5lb
+cdczlxgxpdqvkcqbfivet3
+nxxxreight158mvrhngveight
+811dsqsscjgfive2
+nine8nine16gxqxcj6three
+dqjdfksftwohrrhzlcxd12vblpmsqrrfourshg
+345dstjsbllcnine
+4three6vnzfssrqrg
+mlcmlvlmcseven72mcqlzfnpm2
+ninegflbrbv6twosvfive
+nineninerjmnhlthreenine3
+zvsqxdggl9dxppmcmc389fourvpeight
+2fiveeighthtfvpndpn8mt3two
+33tshvcbgtggone6
+1sevenfivextsfpsix
+frmhtjxcnztfhtgtr5
+8jjsclsqgfourthree7lvct75
+62vqnhqct4
+2jlvv55
+lszrone3eight19ggpnine
+8fivexxxrkzrppslbf8threexsskbkjcc
+pvpxjrnnp11rmgfhbpbninesmbfpcpseven
+seven8pfzgsbgjqtneight
+rdksixnzmxgppj6qkftmcthgl9
+32three1
+bnxd75
+mzlcnxgdddfpqkp6hjjpnnine31
+135gnzr9brblpnk
+vvninerkskndtjq8zst4sixnine
+fivexdstdtfshcchblmknlneight5fncvl
+7mhjsq7ninetwo3tbnkglngltwo
+threeninesix5567
+2four14fzrsjr
+9sixkl9
+rftbrjfour4
+onemtjqqdrtjgkbv1plcgtxtwoonefoureight
+6fourqsgfkqdnspzstbrhzxbthreeqxrshrfdbk1jrxptfhjfld
+sevensix9
+one75two9fourxdjmzjv
+one8rbvxt
+skzg13
+ninesevent3
+mcrgx49qbpzcqqbx
+threebsevensix9nine54six
+1bjgnlhtxgx
+71crfour
+3nkjflkqpjz61gzsffxlncmxg8
+rhppr943fourmmjm
+rvmthreevbvxqhrhglvrh869
+6sixfivexgshnkmx26
+3srgvnbcsreighttfnjcs782
+87ninenjhxpnrhljkvnms3
+foursix1rfgvmxqfrninekthjjk
+fourtqbjqcmsgnine1twoxgvqdhbnloneeight
+hhzdrttjvbzdngnqv2
+kbm71
+qzmtwonexlzbv2eightfrjmhld6
+27mdxfj49kzkzdspbxvktm
+three8cvfqmntngvmhddgqdgonetjgnnzggjz9xqlxffgsc
+ckd3fourtwo5vzv
+lhbvlseven41bdrkzmshkxone
+6fourthreefourthreeskhdk
+377dtljbhvfdr4ngqdqfbfournsnt
+rvbkddqrfm8rpfive
+1ninethree
+zjhbkjrb5qvtjbcgpkvksbsszpqjfcrgrcqggdtc
+73nine9pslhnpmxjjfourthree
+91nine5xndjkx7
+four17crgvnqtwoxqxfcsbbbsjlsjhsfll
+five9twobqlgcdpk4
+pblrzfive7ninetzfiverhlslrsone
+7bltone
+3eightthree16
+nineone54hspfngxzhzh
+7sixzxqlsqqsvfouronethree6
+8kklgfmqvntwonine9
+dznsskrrfchdnm2fxcvqvf3eight
+cmfkrlslhgzprgkfive6seven
+4threethree
+threesix2fkzsjkr6six
+8bcqmshjlnfivecrjtcsznrfive
+11nine3six
+326one1zvdzc
+1sjttzbstpx6sgfzpgdltxseven15bvrbmccbzkbgdnkkhpd
+9bbpksbnpdm
+3rtcztcr
+bk1sevenjbmncfiveninejp
+seven62hjvttpk
+rsnqnlgfgrxk8sfxhrlgmc1jnjgctclr7
+3sbmxlshf5five4
+8nprjs
+three89
+four399ljmdptjbgkthree
+cthxllrzbseveneight7four
+3gzvsfnxfive
+pjbgbnine1rphbcrhgnine2
+56fourcsfpfnntpkfcsqkkp6oneightlsv
+fourmn5kqgvk
+96twoseven
+2bk
+8nineninesevenvxfnqlsrnxbr
+fivetnxmljplldd3six
+qtzcgtlh9
+gtnkglkd3twoqgqhj6dpfgqtpptg
+7jvxsltntrksjzsix
+three95fivebpvtzh
+3kxxfvsseven
+157xvtnfkqnsbvpxlrdmjszrpmpfive
+7threeseventwo7twoseven5
+rcmzjxg1csdhdkvfhxppsixfivethree
+nvgfnine38onezdbhhgtmshc
+2ngoneninex
+1eight57ggvqjmsixonefour
+dhq7hzhmbzdhzjxhdtwo32
+ggdone3nbmsthreefourninefiveoneightpr
+fourvzgnfnhkkp2
+j47three8sevenfivenfkd
+twotwo4seven1fqklblqbdxcmtch
diff --git a/day1/uppga.c b/day1/uppga.c
@@ -0,0 +1,37 @@
+#include "common.h"
+
+#include <stdlib.h>
+
+static int is_numeric(const char c) { return ('0' <= c) && (c <= '9'); }
+
+int main(int argc, char **argv) {
+ char **lines;
+ size_t nlines = readlines(&lines, "input");
+
+ size_t i;
+ char *cc;
+ char fc[3];
+ char ci;
+ int x = 0;
+ for (i = 0; i < nlines; i++) {
+ cc = lines[i];
+ ci = 0;
+ fc[1] = '\0';
+ while (*cc != '\0') {
+ if (is_numeric(*cc)) {
+ *(fc + ci) = *cc;
+ if (ci == 0)
+ ci++;
+ }
+ cc++;
+ }
+
+ if (fc[1] == '\0')
+ fc[1] = fc[0];
+
+ fc[2] = '\0';
+ x += atoi(fc);
+ }
+
+ printf("%d\n", x);
+}
diff --git a/day1/uppgb.c b/day1/uppgb.c
@@ -0,0 +1,75 @@
+#include "common.h"
+
+static int get_digit(const char *c) {
+ if (*c == '\0')
+ return -1;
+
+ if (('0' <= c[0]) && (c[0] <= '9'))
+ return (int)(c[0] - '0');
+
+ if (strncmp(c, "one", 3) == 0)
+ return 1;
+ if (strncmp(c, "two", 3) == 0)
+ return 2;
+ if (strncmp(c, "three", 5) == 0)
+ return 3;
+ if (strncmp(c, "four", 4) == 0)
+ return 4;
+ if (strncmp(c, "five", 4) == 0)
+ return 5;
+ if (strncmp(c, "six", 3) == 0)
+ return 6;
+ if (strncmp(c, "seven", 5) == 0)
+ return 7;
+ if (strncmp(c, "eight", 5) == 0)
+ return 8;
+ if (strncmp(c, "nine", 4) == 0)
+ return 9;
+
+ return -1;
+}
+
+static int get_first_digit(const char *c) {
+ const char *cur = c;
+ int digit;
+
+ while (*cur != '\0') {
+ digit = get_digit(cur);
+ if (digit != -1)
+ return digit;
+ cur++;
+ }
+
+ return -1;
+}
+
+static int get_last_digit(const char *str) {
+ size_t len = strnlen(str, 500);
+ const char *cur = str + len;
+ int digit;
+
+ while (cur >= str) {
+ digit = get_digit(cur);
+ if (digit != -1)
+ return digit;
+ cur--;
+ }
+
+ return -1;
+}
+
+int main(int argc, char **argv) {
+ char **lines;
+ size_t nlines = readlines(&lines, "input");
+
+ size_t i;
+ int first, last;
+ int x = 0;
+ for (i = 0; i < nlines; i++) {
+ first = get_first_digit(lines[i]);
+ last = get_last_digit(lines[i]);
+ x += first * 10 + last;
+ }
+
+ printf("%d\n", x);
+}
diff --git a/day10/Makefile b/day10/Makefile
@@ -0,0 +1,30 @@
+CC=clang
+CFLAGS+=-std=c99 -pedantic -Wall -Werror -Wstrict-prototypes
+CFLAGS+=-Wmissing-prototypes -Wmissing-declarations -Wshadow
+CFLAGS+=-Wpointer-arith -Wcast-qual -Wsign-compare
+CFLAGS+=-O2 -g
+CFLAGS+=-fstack-protector-all -Wtype-limits -fno-common
+CFLAGS+=-fno-builtin
+CFLAGS+=-I/usr/local/include
+CFLAGS+=-I../utils
+#LDFLAGS=
+
+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) $(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)
+
+utils:
+ make -C ../utils
+
+clean:
+ rm -rf common.o uppga uppgb
diff --git a/day10/common.c b/day10/common.c
@@ -0,0 +1,3 @@
+#include "common.h"
+
+size_t fn(char **lines, size_t nlines) { return 0; }
diff --git a/day10/common.h b/day10/common.h
@@ -0,0 +1,14 @@
+#ifndef COMMON_H_
+#define COMMON_H_
+
+#include <assert.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <reading.h>
+#include <stack_u64.h>
+
+size_t fn(char **lines, size_t nlines);
+
+#endif
diff --git a/day10/input b/day10/input
@@ -0,0 +1,140 @@
+FFFJJ--JF|JF7-7FJ7FFJ-F--J7F-77.-7-7L|.F.|7F7FLJ-7-|-FFJ-FL7-7FF|-|-7FF7777L-L-7J----JF7.F.F--777FF|77F7|F|777F7LF-J7..-7.777F.F.-.FF.7FF7-7
+-|.||77F-.LJJ7L-J-7JFFL7FFJL--77J|L7-LFJF7|L|7J|.|L7F--7FJ.--F-7-7LL|-FJ|LL.LLJ..L|.|.---LLF7..F77|J|FJ-JF|L7-L7|L|.7FFJF.F|-F7|7JFF|-FFFJ.L
+L-J-7J7LJ--JJ|FJ--|-77JLJJJ|||F----77FJ-.LF.LF.L77-J-7LL|.FL..|.||7.L-JLJFJ7J.FL.|L7L7FJ-||JF7F|.FF7FJJL7-LF|7JJL.LF.LJF7--J7F.|J.LF7F-7L.J|
+FLJ7LL77FJ.|.|--FJ|-||7.LFLFF-L--77LFL-FJFJ.LL7JFJF7-LJJF7L|-7L-JJFFF|F77L7J.7J|FL-7J.|F7J|7JF-77J|F77.LF7|LJJ77L|J|.L|L.J.L|L7L77.JLJL-JFLL
+L.F|LL-J7|.FLL7.L-|7|JJF-L-|-7F-7FFF-|-FF-J.FLJ.L7L-7F7-|7.7|LLJF---FJFJF.77.L-77JF|-LJ-|7.FFL7|7|F||77.||F7JL-F7J||L-JJ7..|JFJ7.|-LJ.F--LJ|
+.L|J.F|-F---7LF-LFJ-|J7.FL7FJ|FF|FL|LJ|LLJ7L|.F..J--LL77LJ7||JL-7LJJ||L.7.J-FJ.|.|..||LLL-FF|L||7F-J|LF7|LJ|--7LJ.|77.LL7F|--FJL7-FJJ.FLJFJ7
+JJ|-F.|L7LFLJFL-.7FF7-LJ7|-LF|7FJ7.|FJJ7L.FJL7JFF||.L7LJ7J7FF7FJJJ.FF|J7L|7LL.FF--F--JFL|7F7F7|L7L-7L7||L7FJ.L-.|.L|-F-FFJL|7LJ.L7|L7-L.-J7|
+|F7|.F7-|77F|FJ.|LL-L7|JL77F7.FLLJ7--7LJ-FF77.-|FF77.L77|.FFFJJJ7FF-LF7--L77||J|7J.LLL|.F-J|||L7|F7L7LJL-J|J7FJ-L-L7J|.FFJ7JL|J.LFJF-J|-J.FJ
+FL7F7-|J|--J7F-FJJL-L-J|.LL|J|||LLJ|L7.|FFLLJ7.FJLFF--7-FJ7|L77.F||.JJ||.LF-7J-77.F--7JFL-7LJL7||||FJF7F7FJ.FFJF7..L-7.F|.7-.-.FJL--|---J.F.
+77|J.---JJ7||.L|J-F-.|L|.|F-7|F-7FF-.LF--J|LFLF|J.F7.L||LL|-JLJFFF7-J||-7-L7J.F7JFL-7L--7JL--7||||||FJLJLJ-F7|FJ|.|LF77JLJJ77--.-F-FJLJFF-|J
+L--J.|7J|FJ-|F--J7J-F-F|7.F7.F.LJ7LJ--JF--F-J.F7LF|L-7.J..F77J-F7LJ.77LF-7L|7-LJ7FF7L7F-J-F7FJLJLJLJL---7||||777F7LFJ|7.-7F7L|FFJJ||JJFJ-J|.
+FJJ.FF--7J7|LL7|.|.---LJ|FJ7..F7LJ-J.F7|-F|7.F||F-JF-J7|F7J|JL--F7J7F7F7F-FF7F7LF7||L||-F7||L--7F-7F----J-FJL-7FJ|F|.F77F77.7JFJ7FL-7-F7|-||
+-J-FJLJ7|-F|7|L7F|-LL-FJ|.-J7FFFF.LFFL-F---7-FJ|L-7L7F7.--JL|7.L||JFJ|||J-FJLJ|FJLJ|FJ|FJ||L--7|L7|L-7|F7|L7F-JL7|F7.|L7J.F-7F7.|7-L|J.-JFFF
+.F-L.|F-J-LJ-L-J7F.F7-77.F|JLL7JF7FFF.FL--7L7L7L-7L7L7|.|L7-F7F7|L7|FJ|||FJF--JL--7|L7||FJL--7||FJL--JFJ|F-JL7|FJ|||F|FJ.F|FJJ-7--J-L7J|LLF7
+7-.LL-J.F77L7J7L-L7LJJL7-7LF|-L7||77JFF7.FJFJLL-7|FJFJ77F-|J|||LJFJ||FJL-JFJF7F7LFJ|FJLJL7F--J||L-7F-7|FJ|F--JFL7||L-JL7F-J|J.|JF--7LJ.7JJ.J
+|FJ7.L|-77FLJ|7||||7|J.-FJ.F7||FJ|F-7FJ|FJFJF-7FJ||FJJ|F7-|-||L-7L7||L---7|FJ|||FJFJL7F--JL--7||F-JL7LJL7|L7F---JLJF---JL7FJF-77L-7-LFF7LF7|
+--J--.7-LFJ.FL-L-7J-7.7L|JF||F7L7||FJ|FJL7|FJFJ|FJ|L7F7|L7F7||77L7||L7JF7|||FJ|||FJF-J|F-7F-7|LJ|F7JL7F7LJFJL----7FJLF--7|L-JFJ-J-J7-LJ|7L-7
+L7JLLFJF-7FJ-L7|7LJ7|F|7LFF|LJ|FJ||L7|L-7||L7L7|L7L7LJ||FJ|LJ|F-7|||FJFJLJLJL7|LJL7L-7||FJL7LJF7||L7FJ|L--J.FF7F-JL7FJF-JL7F-JJ|77..-.FFJFJJ
+F|J.F7-7-J-L7FJJ7LFFFFJ-||FL7FJL7LJFJL-7|||||FJ|FJFJF-J||7L-7|L7||LJL-JF-----JL7F-JFFJLJL-7L--J|LJFJL7L7F-77FJ|L7F-J|FJF77|L-7L7J.F-JF||-F-7
+LJ|F|LFL-LJ-L7JJ|FFJFJ..FF-7||LLL-7L7F-JLJL7|L7|L7L7|F7|L7F7|L7||L----7|F-7F-7FJL--7L7F---JF7F-JF-JF7|FJ|FJFJFJFJ|.FJ|FJL-JF7L-7.F7F7J.L7LJJ
+LJ7.|F|L---F|||.77LF7FF7FL7LJL7-F7|FJL---7FJ|FJ|FJFJ||||FJ||L7||L-----J||FJ|FJL7F-7|FJ|F7F7||L7FJ|FJ|||FJL7L7L7L7|FJFJL7F--JL--J7F77-F-7L7L.
+LL7-L|F|7|77F7LF77-|L7LFF7L-7FJFJLJL77F--JL7|L-J|FJFJ|||L-J|FJ|L-7F---7LJL7||||LJFJ|L7||LJ|||J||F7|FJ||L7FJL|FJFJLJFJ|FJL-7F--7F-7|J|J.J|L.F
+J.|F7.|.LF77F7J||..L7|F7||F7|L7L7F-7L7L---7||F--JL7L-J||F--JL7|F7LJF7L|F--J|L7F-7L7|FJ||F-J||FJLJ||L7|L-J|F-JL7|F7FJF7L7F-J|F-JL7L7FJF-L7J-7
+.|||LF..LF7FJ|-||7FFJLJ||||LJFJ-LJ.|FJ|F--J|||-F7-|F--J|L-7F-J||L7L||FJ|F-7|FJ|FJFJ|L7||L7F||L7F-J|FJL--7||F7FJ||LJFJL7|L7FJ|F7FJFJ-.L.F|FLL
+|L|JF|F7J||L7|FJL7.L--7|||L-7L7-F7FJL-7L--7||L7||FJL7F7L7FJL-7|L7L-J|L7LJFJ|L-JL-JFJFJLJFJFJ|FJL--JL7F7FJ|||LJFJL7.|F-J|FJ|FJ|||FJJJ--F-|F-|
+LFJ7FJ--FJL-JLJF-JF7F-JLJL-7L7L7|||F--JF--JLJFJ|||F-J|L7|L7JFJL7L--7|FJF-J|L7F---7|FJF7FJJL7|L7F7F--J||L7|||F7L-7L7|L7FJL-JL-JLJL7-||FJ-7JLL
+F-J7|LL-L-7F7F7L-7||L-----7L7L7S|||L7F7L--7F7L7|LJL-7L7LJFJFJF-JF--J|L7L-7F7LJF--JLJFJLJF7FJL7||LJF7FJL-J|||||F7L7LJFJL7F----7F--JF7F7-7J-7|
+F-L-77-|-FJ||||F7LJ|F7|F7-|FJFJ|||L7|||LF7||L7||F---JLL7FJFJFJF7L--7L-JF-J||F7L----7|F7F||L-7|||F7|||F--7||||||L-JF7L--JL--7FJL---JLJL7JJ|L-
+77F7.F77-L-J|||||F7LJL-JL-JL7L7LJ|FJLJL7||LJFJLJL7F--7FJ|FJFJFJL7F-JF-7L7FJ|||-F7-FJLJ|FJL7-||||||||LJF-JLJLJLJF--JL-------JL-7F7F7F7FJ7LFLL
+LFF|-J|J..LJLJLJ|||F7F-7F7F7L7L-7||F---J||F7L-7F-J|F-JL7|L7|LL-7|L7FJ.|FJL7||L7|L7L-7FJL-7L-JLJLJ|||F7L--7F7F7FJJF7F---------7||||LJLJ-LJF-J
+F|J|F-77-7.L|-LLLJLJLJFLJLJL7L7L|LJL7F7FJ||L7.||F7|L7F7||FJL7JFJL7LJF-JL7.|LJFJ|FJF-JL7F7|F7F----J||||F--J|LJLJF-JLJF-7F7F7F-JLJ|L--7JFJ.F-L
+FL7J.FFL.LFJ|7L||LLF--7LF-7.L7L7L7F-J||L7LJFJFJ|||L7LJLJ||F7L7|F7|F7L--7L7L7FJFJL7L--7|||LJ|L-7F-7||||L--7L-7F7L7F--JLLJ|||L---7L7F7|.|..JJL
+L|||F.|.|-|.L|LLL7|L-7|FJFJF7L7L-JL7FJL7L7FJ-L7LJL7L7F--JLJ|FJLJ||||.F7L7|FJ|FJF-JLF7|||L7FJF-JL7LJ||L7F7|F-J|L-JL--7|F7LJL7F--JFJ|LJ7J-J--7
+F-J--|J7F7J7F7F7LF---J|L7|FJL7L--7FJL-7|FJ|F7FJF--J-|L-7F7FJL7F-J||L7||FJ||FJL7|F7FJLJ|L7|L7L--7|F-JL7||LJL--JF7F---JFJL7|FJL7JJL7|7.L|LLL|7
+7FFJJ.FJL7LJ-L|J|L---7L-JLJF7L7F7||FF7||L7||||FJF7F7|F-J|||F-JL-7|L7|||L7|||F7||||L--7|-||J|F--J||FF7||L7F--7FJ|L7F7FJF7L7L--J|.L|L77||7..|7
+FJ7-J.J.FJ-L.LLJ7F--7L7F-7FJL7LJ||L-JLJL7|||LJ|FJ|||||F-J||L-7F7|L7||||FJ||LJ||||L-7FJL7||FJ|F7FJ|FJ|||FJL-7|L7L7LJLJFJL-JF---7-JL-J.FFF--L|
+|F|F|-FF|7-|7|LLFL-7L7LJ.LJF7L-7|L----7FJ|LJF-JL7||LJ||LFJ|F-J|LJJ||LJ||F|L7FJ|||F-JL-7||||FJ||L7||FJ|||F--JL-JJL----JF---JF--JJJF7L-7LJ-F7|
+LJ-F7JFFJ|FFF||JF--JFJF7FF-JL--JL-7F7FJL7L-7L7F-J||7FJL7L-JL-7L--7||F-JL7|FJ|FJ|||F-7FJ||LJL7||FJLJL7|LJL--7LF7F----77|F---JF-7F-J|7L|.|.|F-
+||7JF-JLL7F|F77JL--7L-JL-JF-7F-7F7LJ|L-7L7FJFJL-7|L7|F7L7F---JF7FJLJL7F7|||FJL7||LJ7||-||F--J|||F7F-J|F---7L7|LJF--7L7||F7F7L7LJF-JJ.JF|FLJJ
+FL|FJ-7.7L-F7F7FF7FJF7F-7FJ-LJJLJ|F7L--J7|L7L7F7|L7||||FJL7F-7||L7-F7||LJLJ|F7|LJF7FJL7LJL--7||LJ||F7|L--7L-J|F-JF7L-J|LJLJL7L7FJ7-|L7L7JJF|
+|7L|J|-7J-FF7||FJ|L7|LJFJ|F----7-LJL--7F-JFJ7LJ|L7|||||L-7||FJ|L7L7|||L-7FFJ|LJF-JLJF7L7F7F7LJ|F7|LJ||F-7L-7FJ|F7||F--JF7F--JFJL-7--LL.|J.J|
+7--|7.LFFFFJ|||L7L7LJF7L-JL---7|F7-F7FJL-7L--7FJFJ||LJ|F-J||L7|FJFJ|LJF7L7L7L-7L7F-7|L7LJLJL7FJ||L7|LJL7L--JL7||||||F--JLJF--JF--J7|FJ-|F7JF
+|.FJL.FFF7L7LJL7L7L7FJ|F------JLJL-J|L7F7L7F7|L7L7|L-7|L-7||FJ|L7|-|F7||FJFJF-J7LJFJL7|F-7F-JL7||FJF---JF---7|LJLJLJL----7L7F-JF----777FFJFF
+LJ77LFF7||LL-7FJJL7|L7|L7F---------7L-J||LLJLJJL7||F7||F-J||L7|FJL7||||LJ7L7L-7F-7|F7|||FJL7F7LJ|L7L----JF-7LJF7F-7F7F7F7L-JL-7|F---J7-7J|LJ
+.|.FFFJLJL---JL-7FJ|FJL7||F--7F-7F7L-7||L---7F--J|||||LJFFJL7LJL7FJLJ||7F77|F-JL7LJ|||LJ|F7LJ|F-JFJF77F7L|FL7FJLJL||LJLJL--7F7LJL---7LL|.F7.
+LL7L.|F--------7|L7||F-JLJL-7|L7LJL--JFJF7F7|L-7FJLJ|L--7L--JF--JL-7-|L-JL7||F7FJF7||L-7||L7FJ|F7|FJ|FJL7L-7|L7F7FJL--7F-7JLJL-7F7F-J77.|-|7
+.L7J.||JF7F7F--JL-J||L7F77F7|L-JF-----JFJLJ|L7FJL7F7|F7FJ-F--JF7F-7|FJF-7FJ|||LJFJLJ|F-J|L7|L7LJLJL7||F7L-7|L7|||L-7F-J|FJF---7|||||.LJ7|FF.
+|J.|-LJFJ|||L---7F7LJFJ|L7|LJF--JF7F7F7|F-7L7||F7||LJ||L-7|F-7|||FJ|L7|FJL7LJL7FJF--JL-7|FJ|FJF-7F-JLJ|L-7LJFJ||L-7|L--JL-JF--J||||-|J.||-L7
+|-FJ.F-JFJ|L-7F7LJL-7|-L7|L--JLF7|LJLJ|LJFJJLJLJLJL-7||F-J|L7||LJ|FJFJ|L7FJF--JL7L--7F-J||FJL7L7LJF--7|F-JF7L-J|F-JL-7F-7F7L-77LJLJ-L-7F||F-
+|7LJFJF7L7L-7LJ|F7F-JL7FJ|F----JLJF7F7L7FJF7F7FF7F--J||L7FJFJLJF-JL7L7L7|L7|F---JF7FJL7FJ||F-J7L7FJF7LJL--JL7F7|L--77LJ7LJ|F7L-7F77|.L|-|7J7
+FLJ.L-JL7L--JF7|||L-7FJ|FJ|F------JLJL7|L7|||L7|||F-7||FJL7L--7|F7FJJL7|L7|||-F--JLJF-JL7||L-7F-J|FJL-------J|||F-7L----7|LJ|F-J||-J7-F.LJ-J
+FJF7LL-LL7F--J|LJL--JL-J|-LJF-7F7F7F7FJL-J|||FJ|||L7LJ|L-7L-7FJLJ||LF7|L7||LJFJF-7F7L--7LJ|F-JL--JL---7F-7.F-JLJL7|F---7L--7LJF-J||JJ.LJ-|||
+LJ|J-LJJFJ|F--JF---7F7F7L7F7L7LJLJLJLJF---JLJL-J|L7L7|L7FJJFJL7F-JL-J|L7|LJF-JFJFJ|L7F-J7FJL7F7F7|F7F-JL7L-JF7F--J|L--7L7F7L--JF7L7||L.L7LL7
+L7|JFJ-FL7|L7F-J-F7||LJL7||L-JF-7F---7|F--------JF|FJF7|L-7|F7|L-7F7FJFJL-7L7FJ|L-JFJL-7FJF-J|||L-JLJF7FJF--J|L--7L---JFJ|L7F--JL-J-JJ-JLLJ|
+L|-7F|-|FJ|FJ|F--J|||F--JLJF-7|JLJF--J|L----7F-7F7LJL|||F-JLJLJF-J||L7L7F7|FJL--7F-JF-7|L7L7FJ|L---7FJ||FJF77L--7L----7L-JLLJF7F--7-JFJ7.L77
+LLJJ7|7FJFJL-JL--7LJ|L----7|FLJF7LL7F-JF----J|FJ||FF7||LJ-F7F7FJF7|L7L7LJ|||F7F7||F7L7||FJFJL7|.F--J|JLJL-JL---7L7F---JF-7F7FJLJF-J|..L-|-JJ
+|JL-JL-|FJ7F---7FJF7|F----J|F--JL-7LJF7L--7F-JL-JL7||||F7FJLJ|L7|||FJFJ.FJ|||||||LJL7||||FJF7|L7|F7FJF-7F------JFLJF--7|FJ|||F--JJ-F-J-7F7..
+|.J.|.F|||FL--7LJFJLJ|F-7F7|L7F7F7L--J|F--J|F-----J|LJ||||F-7|FJ|LJL-JJ.L7|||LJLJ-F-J|||LJFJ|L7|LJLJFJFJL-------7F-JF-J||||||L7F7F7-7J||LL77
+|7||LFLLJF----JF7L7F7LJ7LJLJJLJLJL-7F7LJF7FJL7F7F7.|F-J|||L7LJL7|7.||7LF7|||L7JF-7|F-JLJF7L7L-JL7F7LL7L--------7LJF7L--JL7|||FJ||||.|-LF-L.L
+J--|-|J|LL----7|L7||L-----7F77F----J|L--JLJF7LJLJL7||F-JLJFJF-7|L7F7JL.|LJ|L7L7L7LJL--7FJL-JF7F7LJL--JF-----7F7L--JL7F---J|LJL7||||..LLL.|7.
+L-JLLF-7.F7F--JL7||L7F-7F7LJL-JF----JF-7F-7|L---7FJ|||F---JJ|FJ|FJ-J7-FL-7L7L7|-L7F-7FJL-7F7||||F-7F-7|F---7LJL7F7F7LJF-7FJF-7LJLJL--7.|-JJ7
+|F|7JF-7FJLJF--7|LJFJ|FJ|L7F7F7|FF---JFJL7|L7F-7|L-JLJL7F7F7|||LJF|LF-JJLL7|JLJF-JL7LJF7FJ|||LJLJ.LJ-LJL-7|L--7LJLJL7-L7LJFJ-L7F----7L-7J|.J
+L-.77L7LJF7FJF-JL-7L-JL-J|LJLJ||FJF--7L--JL7||FJ|F7F--7LJLJLJL---77-|7LF.LLJ7LLL---JF-J|L-JLJF----------7L---7|F-7F7L--JF7L--7LJF--7|F-J-|7|
+LL|JFLL-7|||FJF7F7L--7F-7F7F7|LJL7|F-JF7JF7LJ||-LJ|L-7L-7F---7F--JJFF|.F7F.LL-JF----JF7|F7F7FJF--------7L--7FJLJLLJ|F7F-JL---JF7L7FJLJJJ-|7|
+-7LLJJF-J|||L7|||L7F-JL7LJLJL7F7FLJL--JL-JL--JL7F7L-7L7FJL--7LJJLJ.F-|F|FL7J-LF|F----J||||||L-JF-------JF-7|L----7L|||L7F7F7F7||FJ|F7.LL-|7.
+|||FL.L-7|LJ-LJ|L7LJJF7L-7F-7LJL----7F-7F7F7F-7LJL-7L-JL7F-7L-7.J7.LJ.7FJJ||F|FJ|F----JLJLJL7F7L----7F7FJFJL-7F-7L7LJL7LJLJ|||||L7LJL7-7.J7.
+LJ-L-FLFJL7LF7JL-JF7FJL--JL7L7F7F7F7LJFJ|||LJ|L7F-7L7F7JLJ7L--J7.|JFLFFFJJ|77FL-JL7F---7F--7||L7-F--J|||FJF7.LJ|L7L-7FJF7F7LJLJL-JF7FJL|7JL|
+-JF|7J-L-7|FJL7|F7||L------J|LJ||LJL-7L-J|L--7J|||L7LJL-7.F7F7L|-J-77J.7FFJF-JF---J|F--J|F-J|L7L7L---JLJL-JL7F7F7|F7||FJ|||F-7F7F-JLJJ7JL|.F
+|.FFL.-L7LJ|F7L-JLJL-----7F7F--J|F---J-F7|F--JFJ|F7L----JFJLJL-7LL-7JF|L7J.L|.|F---JL---JL-7|FJFJF7F7F7F----J|LJ|LJLJ|L7||||||||L---7F7-JL-J
+F7J7-7||FLLLJ|F--7F-----7LJ|L---JL-----J||L7F-JFJ|L---7F7|F---7L7F-F.F|7||-FJ7LJ-|LF7F-----J|L7L7|||||LJF----JF7L--7FJFJ|||L7|||F7F-J--J7L-7
+LJ7FFJ7JL|LF7LJF7||F---7L-7L---7F-------J|FJL--JFJF7F-J|LJL--7|FJJ|LLJF77LFL.7.|LFFJLJF7F7F7L7L7|||||L--JF----JL7F7|L-JFJ|L7|||||||-J|FF-.LL
+|-LLJJ|L77FJL--JLJ||F-7L--JF7F-JL-----7F7LJF-7F7|FJLJF7|F-7F-JLJ|-J7|FJLF--J7|FL-|L--7|||||L7L-JLJLJL----JF7F7F7LJ|L--7L-J|LJ||||LJ--F7-L7||
+F.JLLFJFLFL7F-7F--J||FJF7F-J||F7|F7F--J|L7FJFJ|||||-FJLJL7LJF7F7F7F-L|--J.L|F7F7-JFJL||||LJ||F7F--7F------JLJLJL-7L---JF----7||LJJ7LF||7.LF7
+FFJ.L|.|J|7LJJLJF-7LJL7|||F-JLJL-JLJF7F|FJ|FJFJLJL7FJF--7L--JLJLJ|7FJJ.|7F.F-JLL7F|J7LJLJFF7LJLJF-J|F----------7FJF7F7FL7F--J|L7FL|F-L.|J.FJ
+LJ7||.-|-FLJ-FF7L7||F7||LJL7F7F7F7F-JL-JL-JL7L7F7FJ|FJF7L------7FJJ7L--L-7.L|F-J-77FFLF-7FJL----JF7||F------7F7LJFJLJL7.||F-7|FJ7LL7-L-F.|JJ
+F.|-7L.|-7.FF-JL7||FJ|LJFF7LJLJLJLJF7F7F-7F7L7||LJFJL-JL------7LJJ7|F7LJJ|FLLJ.|LJJ--.L7|L-7F7F7FJ||||F-----J|L7FJF--7|FJ||FJLJ|7F|L-L-J.|F-
+FJJ.--L.L|7-L--7||||FJF--JL7F7F7F--J|||L7LJL7LJL--JF------7F-7|-LJ|-FLJFLL77|.F7FLJ7FF7||F-J|||LJ7||LJL-----7|FJ|FJF7LJL7LJL---7-7LJ7.J|F-JJ
+L7FLJ7L7JF7FF--JLJLJ|LL---7|||||L--7LJL7L--7|F7F--7L---7F7LJ7||-J-JJ||-7LL7J-L7||-FF-JLJ|L--JLJF-7LJ7F7F---7LJL-JL7|L7F7|F-----J.-.||7|JJ.LJ
+.|7J.F7FFJL7L--7F7F7L7FF--JLJ||L--7L7F7L---J|||L-7|F7F7LJL--7LJFJ7JLL7-||F|-|FFF7F7L---7|F7FF7|L7|F7FJLJF7LL7F7F-7||FJ|LJL7FF77|.LL7LL.J.|.|
+FL7.||L.|F7L---J|||L7L-JF7F7FJL--7L-J||F7F7|LJL7FJLJLJL7F---JF||.|--||FF777F|FFJ||L7F--J|||FJL--J|||L---JL-7||LJFJLJL-JF7FJFJL---77|F|.|FL-7
+J..F----LJL-----JLJFJF7FJ|||L----JF--JLJLJL-7F7LJF----7|L---7-F77J7LF7|||F---7|FJL7|L--7LJLJF---7LJL7F-7F--J|L-7L7F--7FJ|L-JF----J-77.7-J.|7
+LJFFJ|FJLJF----7-F7L7|||-LJL7F----JF-----7F7LJL-7|F7F7||F---J7||7-|-F-7||L--7LJ|F7||7F7|F7F-JJF7L7F7|L7|L--7L--JFJL7FJ|FL--7L-7F|7JJFF7||.F7
+|.LF--L7JFL-7F7L-JL-J|LJF7F7LJF7F--JF---7|||F7F-J||LJLJLJF----JL7-J|L7|||-F7L-7LJLJL-J|LJLJF7FJL7LJ|L-JL---JFF-7L--JL7L7F7FL--JF-777FF--F.J7
+7.LL-.F-.-LLLJL7F7F-7|F-J|||F-JLJF-7|F--J||LJ|L--JL7F7F7J|F--7F-J7-LFJ||L7|L-7L-7F-7F7L7F7.||L-7|F7|F-------7|FJF---7L7LJL----7|FJJ7||L7|LJ|
+L7|F|-FJ7-|F7F7LJ||FJ|L-7LJ||F-7FJJLJL--7|L7FJF7F-7LJLJL-J|F7LJ-F77.L7|L7||F-JF7LJ7LJ|FJ|L-J|F-J|||LJF7F---7LJL7|F--J7|F7F7F-7LJL7|-|JFL-|-|
+J|-LLF7.-.FJLJL--J|L-JF7|F7|LJFJ|F7F7F--J|FJL-JLJ7L7F7F7F7LJL7F-JL7F-JL-J||L-7|L7F7F7||-L--7|L-7||L-7||L--7L--7LJL---7LJ|||L7L7F7L7|LLJJFF.|
+LL-FFLLJLFJF7F-7F7|F--J|LJ|L--JFJ|LJLJF7-LJF7F---7-LJLJLJ|F7FJ|F--JL----7|L7FJL7|||||||F-7J||F-JLJF-J|||F-JF77L7F-7F7L-7LJ|FJJ|||FJ77.|L-|7J
+F|-|LLJ-FJFJLJFJ|||L7F7L7FJF7F7L7L----JL-7FJ||F--JF7F--7FLJLJFJ|F7F7F7F-JL-JL7FJLJLJLJ|L7|FJLJF7F7L--JL7L--JL-7LJ7||L7FJF7LJ|FLJLJ-|LFF7|L77
+FF7.7.LFL7|J|FJFJ||FJ|L7LJFJ||L7|F-------J|FJ|L--7|||F-JF7F7FL7LJ|||||L---7F-JL------7|L||L--7|||L7F7F7L---7F7L7F7LJFJL-JL---7||7FJLF7|L7|L7
+L|-JJ.-JLLJ-FJFJ7||L7|LL-7L7LJ-LJL-77F----JL-JF-7LJLJL--J|||F7L7FJ||||F---JL7JF-7F7F7||FJL---J|LJLLJ||L--7.LJL-J|L7JL--7F----JJJ-7J-LFL--7|.
+FFJ|L7J7F7|-|FJF7LJLLJF7FJFJF7F7FF7L-JF7F-7F-7|FJF7F7F---J|LJL7|L7||||L----7L7L7LJLJ||||F7F-7FJF7JF7LJF7-L------JFJF--7||F---7.7.|.|..J.F-L7
+||F77|L||FF7LJ7||F7F7FJLJFJFJLJL-JL-7FJ|L7|L7LJL-JLJLJF-7-L--7|L7LJLJL7F-77L7L7L---7LJ|LJ|||LJFJL-JL7.|L---7F--7FJF|F-JLJ|F--J7||-LL-7-FJLF-
+LLJLF|.FF-JL--7|LJ|||L---JLL7F---7F7LJFJFJL7L7F7F---77|FJF-7FJL-JF----JL7|F7|FJF7F7L-7L-7LJF--JF-7F7L-JF--7|L-7|L-7|L7F7FJL--7L7|7FJF|-F-LLJ
+.|J||L7LL7F--7|L-7||||F7F7F7||F-7LJL-7|FJJLL-J||L7F-JFJL7L7|L-7F7|F7F-7FJLJ||L-J||L7FL-7|F7L---JFJ||F7FJF-JL7FJ|F-J|FJ||L7F--JJJFFJ7LJL7.LJJ
+F|-F7F-.LLJ-FJL7FJLJ|FJLJ|||LJ|FJF7F-JLJF7F-7FJL7|L-7|F-JFJ|F7LJ|||LJFJL-7FJ|F-7|L7|F--J||L-7F-7L-JLJ||.L--7LJ7||F7||FJL7||F7F-7-|F7LJL|7--7
+FLFJ|J.F.LF-JF7LJF-7LJF-7LJL--J|FJ|L-7F-JLJFJ|F7|L7FJ||F7L7LJ|F-J|L7FJF7FJL7|L7LJF||L--7||F-JL7L7F7F7LJF---JF-7LJ|||||F-J|LJLJFJL-7|FJ-LJ7F|
+7J|.|77.77L-7|L-7|FJF7|FJF----7|L7L--J|F---J|LJ||FJ|F|||L7|F-JL-7L7||FJ|L-7||FJLF-JL---JLJ|F-7L7LJLJL77L----JFJF7|||||L7J|F---J|J.LL|7.|-FFJ
+--F-J-7JJFJJLJ7FJ|L7||||FJLF7FJL7L----JL7F7F7F-J|L7L7|||FJ|L-7F7|FJ|LJFJF-JLJL-7L-7F---7F-J|FJ-L7F7F7L-7F----JFJ||||LJFJFJ|-F7F7..FJJF---J|L
+.F-J.L77FL7FF--JFJ.LJLJLJF-JLJF7L---7F7FJ||||L-7L7L7|||||.L7FJ||||FJF-JJL--7F--JF7LJF--J|JFJ|F7FLJLJ|F-JL----7L7||LJF7L7L7L7|L-7-||.LJ77||FL
+L-7..LLL-L7FJF7FJF-7F-7F7L--7FJL-7F7LJLJFJ|||F7L7L7|||||L7FJ|F||||L7|F7F-7FJL--7|L-7L--7L7L7LJ|F7F7FJL------7L-J||F-JL7L-JFJ|F-JF77-.L7-LF7.
+LL--|.FJ|--L-J||FJFJL7||L---JL7F-J|L--77L7||LJL7L7LJ||||FJL7L-JLJ||||||L7|L7F--J|F-JF--JFJFJF-J|||||F7F----7|F-7|||F-7|F-7||||F7|L7.7.|..LF7
+F-L7L-7F77|.|JLJL7|F-JLJF---7FJL7FJF--JF7|LJF--JJL-7|||||JFJF----JFJLJL7|L7|L7F7||F7L-7FJ.L7L7-||||LJLJF---JLJ-|||||FJ|L7|L7|LJLJFJF7F7--|J|
+L7.-JFFLJLF7|FLF-JLJF--7|F--JL-7LJ7|.F7||L7FJF7F7F-JLJLJL7L7L----7L---7|L7|L7|||||||F-J|LF7|FJFJ|||F7F7L------7LJ|LJL7L-JL7LJF--7L7||||7LL.L
+LJ-7LLLJ-L|F|7|L--7FJF-J|L--7F-JF--JFJ|||FJL7|LJ|L----7F-JF|F--7FJLF7FJL7||FJ||||||LJF-JFJ|||LL7LJ||||L-7F---7L--JF-7L--7FJF7L-7L7LJLJL7-JF|
+||-7LL|J.|.FLF-F--J|JL7FJF7FJ|F7L--7L7|||L7FJL7FJF77F7||JF7||F7LJF7||L7FJ|||FJ||||L-7|F7|FJ||F7|F-J||L-7||7F7L----JFJF--JL7||F-J|L7F7F7|7-F-
+F--7..L-|77F-FFL-7FJF-J|FJLJFJ||FF7L7|||L7|L7FJ|FJL7|||L7|||||L7FJ||L7|L7|LJL7||||F7|||||L7|||||L7FJL7FJ|L-JL-----7L7L--7FLJ|L---7LJ||LJ|.FJ
+F77|F7-7L--J.F---J|FJF7|L---JFJL-JL-J|||FJL7||-|L-7||||FJ|LJ||LLJF|L7LJ7|L-7-||LJLJ||||||L||LJLJFJ|F-JL7|F7F------JLL--7|F-7|F-7FJ-LLJ.|L-.7
+L-JLJ7-|L|F|F|F7F7||FJLJF7.F-JF---7F7|LJ|F-J||FJF7|LJ||L-JF-JL-7F-JFJ7F-JF-JFJL-7F-J||||L7LJJF--JFJL--7|LJ|L----------7|LJFJLJ|||7.FJ7|7-FFJ
+|F7..|F|-LLJFJ|LJLJLJF--JL-JF7|F--J||L7FJL-7LJL7||L7J|L7F-JF7F7||F7|F-JF7|F-JF-7|L-7||||FJF--JF7FJ-F--JL77|F-7F7F----7|L-7L---7|L-7JF-F7-7JJ
+LFLJ-L-J|JJLL-JJJ.F--JF-7F7FJLJL--7|L7||F7FJJF-J|L7L7|FJ|F7|||||||||L7FJ||L-7L7|L7FJ|LJLJFL-7FJ||F-JF7F7L7LJ-||||F-7FJL-7|F7F7|L7FJJ|-|L7.LJ
+LL.LFJJL7.-.LLF7.FL---JFJ||L7|F---JL7LJLJ||F7L-7|.|FJ|L7||||||||||LJFJ||||.FJFJL7|L7L---7F--JL7|||F7|||L7L--7|||LJFJL---JLJLJLJLLJ.F7-F--...
+.LF.LJFFJ|FJ.|||7F-7F--JFJL-JFJF7F7FJF---JLJ|F-JL7|L7L-JLJLJLJ|||L7FJFJFJL7|FJF-J|FJF7F7|L7F7FJLJLJLJ|L7|F7FJLJ|F7L-7F-----7LJJ7|L-7J..|.F77
+J7|F|FJJF||FLFJL7|FJL7F7|F---JFJLJ||F|F7F---JL7F7|L7L---7F----J|L-JL7L7L7FJLJFL--J|FJ||||JLJ|L----7F-JFJLJ|L-7FJ|L-7LJF7F7FJ7J7JFJ.L-FFJ7LL7
+FF|-J-L7LJLJJL-7LJL--J||||F---JF--J|FJ||L----7||LJFJF-7FJL--7F7L7F7FJFJ-|L-7F-7|F7|L7||||F--JF-7F-J|F7L--7L7FJL7L-7L7FJLJ|L---77|J.L7--L--L-
+FLJJ|.FL-L-JJFFJF7F7F7|||||F7F7L--7|L-JL7F7F-J||F-JFJFJ|-F--J|L7LJ|L7L-7|F7LJFJFJLJFJ||LJ|F-7|FJL-7LJ|F7FJ7|L7-L--JFJL--7L7F7FJJ-7FJ|L||FF-J
+7J|F-77..||7LF|FJLJLJLJ||LJ|LJL---JL7F--J|LJF-J||F7L7L7L7|F-7|FJF7|FJF7|LJ|F-J7L7F7|FJL7FJL7LJL7F7|-FJ||L-7L7L----7|F--7L7||LJ|J|-L-J.7FFJ||
+J--F7L77L.-JJL||F--7F--J|F-JF7F7F7F-J|F7FJ7FJF7|||L-JFJFJLJFJ|L7|||L7||L-7||F7F7|||||F7|L7FJF--J|||FJFJ|F-JFL7F7F7||L-7L-J||7L-7L-7J|.L-JLLJ
+||L-7LLJF7LL77LJL-7LJF--J|F7||||||L7.LJ|L-7L-J|||L-7-L-JF--JFJFJ|||7||L7FJ|LJLJ|||||LJ|L7|L7L--7||||FJFJL--7FJ|LJLJ|F-J-|LLJ-JFJJ.L-7-...L||
+|-J|L7FLL7.FLFJ7LFJF7|F--J|LJLJ||L7L7F-JF7L-7FJ|L7FJF7F7L7F-J.L7||L7LJLLJFJF---J||||F-JFJ|FJ.F7||||||JL7F7FJL7L7F7|LJ.|F77.||.||.FJL--77F-J7
+|7F7JL7J-|77LJLLLL7|||L--7|JF--J|FJFJ|F7|L-7|L7L7|L-JLJ|FJ|F---J||FJF7|F7L7L-7F7LJ|||F7|FJL7FJLJ|||LJF-J|LJF7L7LJL-77FFJL7-77F7-.-JJL-JLJ.F-
+.|LJ-F-.-|FJFL|L|JLJLJF-7||FJF-7|L7|FJ|||F-J|FJFJL7F7F-JL-JL-7F7||L-JL7|L-JF7LJ|F7||||||L-7|L7F7|LJF7L-7L--JL7|F7F7L--JF-JJL7F-7FL7..||L--7|
+-|-..7||J|J|7-77.LLJJJL7LJ|L7|FJ|FJ|L7|||L7FJ|FJ7FJ||L-7F7F--J|||L7F-7||F-7|L7FJ|LJ|||LJF-J|LLJ|L--J|F-JF7F7FJ|||||F---JF|FFFL7FFJJ..FJ7-|L|
+LF7FLJLJJ.----J|FF.|L-LL7FJ-LJL-J|FJLLJLJFJL7|L-7L-J|F-J||L-7FJ||FJL7|||L7||FJL7L-7|LJF-JF7L7F7L7F--J|F7|LJLJLLJ|||L-7|LL7-|7-|JL.LF-|F-FJF|
+|LJ7|.|77|.L|J7.FLL-JL|F||J|F----J|F-----JF7||F-JF--J|F-JL--J|-LJ|F-JLJ|FJ|||F-JF-JL7FJF7|L7|||F|L--7|||L------7||L-7L7.L|....|FLF-J|LJ.|FF|
+F-JL|F--|J-|L77F-J7.FFF-JL-7L--7F7|L7F-7F7||||L-7L---JL-----7L7F-JL-7F-J|FJ||L7FJF7FJL7||||LJ|L-JF7FJ||L7F---7FJLJF-JFJ-7.LL-FFJ|J7.L7LFLJ-7
+7JLF|L.F||.F--77-LJFLJL-7F-JJ|J||||FJ|7||||LJ|F7|F----------JFJ|F7F7|L7FJL7||FJL7||L7FJ|||F--JF-7||L7|L7|L--7|L7|.L-7L7.J7F|F7---7|7LJ-L-|7|
+|7F-7--LL|-FJ|L|7.|F.FLL||7FL7|||LJ|FJFJ||L-7||LJ|F-7F7F7F7F7|FJ|||||FJL7FJ||L-7||L7||FJ||L7F7|FJ||FJL7||F--J|FJ-JLLL-J.L--JFJ|-LL.77.|7FF-J
+F-JF77-L||JL.F.L7-L|77.|LJ7-L|-LJJ-LJJL7|L7FJ|L-7|L7||||||||LJ|FJ||LJ|F-J|FJL7FJLJFJ|LJFJL7||||L7||L-7|||L--7LJ||7..F|7.FJ7.-J7F-..L--7FL77|
+LJL7L|--7L77|..LL||LJ.7-FJJF-L|||J-|J7L||FJL7|F7|L-J|||||||L-7LJFJL-7LJF-J|F-J|F-7L-JFFJF7|||LJFJ||F7||||F-7L7-|LF|-L|FJJ.77JL7JLL|77JFF-F-F
+7JJ|-JFJ|JL7-|..FL-7JF|.FJ-JF7L7JJFLJ|.LJL7FJ|||L-7FJ||||||F7L-7L7F-JJJ|F7||F7LJFJF|LLL7|LJLJ7||FJ|||||||L7|FJ-----7F|F7FLL|.F|-FF||J.|J7L7|
+LFFJJ7..-7|||J.F--JJ.F|-J.-|7|-L.FFJ||-||LLJFJ|L7FJL7|||LJLJL7FJFJ|JJ.LLJLJ|||F7L7JJ|LLLJLF|JF7LJF||LJ|||FJ|L7|L-7J.7-7J7.7|F-7-J7|JFL.-J.FJ
+LJLJFL-FFF77..--F7J.L-LJF7.7-J7J.F7J7|-L77.LL7|-LJFLLJLJ7L|-L|L7L-JJ.FFF---J||||FJFF--|LL-77-|LF--JL-7||||-L7|J.-|7F||L-F7LJJ7|7.7J.JF|F|.||
+FL7||.77J.|.FJ7FJ|.FL.L-|7F|||LLFJ|LFL-JL7-7L||.|FJ.L|.FF|L7-L7|J-|--LFJF7F7|||||-F7|-|7|FJFF7F|F-7F-JLJ|L7FJ|F7.FJ|L-L-FJ7JF-7|.|L7.L7-777|
+-F7-L7FLJF|F7.L|-L-FJF.F|--|FJ.7.-F7-|7|FF--LLJ-||.7J|7F77-|-LLJ.L7|..|FJ|||||||L7|L-.|.F--F-JF||FJL--7FJFJ|FJ7.FJ7LJ.L7L77.L77|JJ7L7F|LJ|F|
+F|JF|-JLF7F|.F|J.|-LLF-F|.LJ-7-F-7LL-7LLJ|--FJ7-LLL-7JL7|..F7J-LF-7J7.LJJ||LJ|||FJJ.||J7FJFJJ7JLJL7F7FJ|FJ-LJ77-LJ|LFL-7.|7.|LL|LL|-J7L.LJJJ
+-J|7F7J|JLJ|.F7JF7-7-J-F7.|LL-7JL-||LJ|LF77.|7F.|.JFJFF|7---J|.J||F--||-F||J-LJLJJ-|7|.L|F-JJF7L-FLJLJ-LJJ7JL|--7F|-|7.|-FJ--7L7.|.F|7LF--L|
+LL7-|L.L7JFJ-L77L7-F-|.LJ-7.|.|-|.L|.F-7L|J-|7JJ|77F|FFJLJ.J7F--FJ7||LLJLLJL7-L.|LLFL|7.L|JFF.-F-JJ..|.F|.J.|.|L|J|.-L-7.JF|.|.|-L7-|-7.LJFF
+7||||J7F--J||7.L-7L77-FJJ.-7.-J-LJ.LLJJ-|JLL|J|.7--F-7J-LF-.||J-L|LL.||7LL-FJ..F|F--7|7--7.7L7-|J.F|-F-JJ7.FFJJ7..F|L|-JL7FL.LJ-7LJF-JL||-||
+|FL-77-J|-7L7-7LF7FJJ.|J.L|.L|.F7F7LL|-LJ.--JFLLF7---J7--J7|FL|.JL7FLLJ--|7JL--FFJ|J|J|7|.F--|7LFF-L-||L7777.JJF.LFL7L.7LJ-J7.FL7.-J||FLL-77
+JLLF---.7.LLJLJ.-JJJF.LJ..|-JL-FLLJ.L|7---J7-F-JJJJL|-J----L--J-.-L-.JJJ.LL.L|JJL-L-J7.FJ.|7-LJFJJ-L|LF-FJ---J.L-JLJ|JLL-JLLL-7-J-L.L7J.|JL|
diff --git a/day10/uppga.c b/day10/uppga.c
@@ -0,0 +1,129 @@
+#include "common.h"
+
+typedef struct {
+ size_t na;
+ size_t nb;
+} pos_t;
+
+static inline pos_t compute_nbrs(size_t row, size_t col, char **lines,
+ size_t nrows, size_t ncols) {
+ pos_t r;
+
+ switch (lines[row][col]) {
+ case '|':
+ if (row == 0 || row == nrows - 1) {
+ r.na = SIZE_MAX;
+ r.nb = SIZE_MAX;
+ } else {
+ r.na = (row - 1) * ncols + col;
+ r.nb = (row + 1) * ncols + col;
+ }
+ break;
+ case '-':
+ if (col == 0 || col == ncols - 1) {
+ r.na = SIZE_MAX;
+ r.nb = SIZE_MAX;
+ } else {
+ r.na = row * ncols + col - 1;
+ r.nb = row * ncols + col + 1;
+ }
+ break;
+ case 'F':
+ if (col == ncols - 1 || row == nrows - 1) {
+ r.na = SIZE_MAX;
+ r.nb = SIZE_MAX;
+ } else {
+ r.na = row * ncols + col + 1;
+ r.nb = (row + 1) * ncols + col;
+ }
+ break;
+ case '7':
+ if (col == 0 || row == nrows - 1) {
+ r.na = SIZE_MAX;
+ r.nb = SIZE_MAX;
+ } else {
+ r.na = row * ncols + col - 1;
+ r.nb = (row + 1) * ncols + col;
+ }
+ break;
+ case 'L':
+ if (col == ncols - 1 || row == 0) {
+ r.na = SIZE_MAX;
+ r.nb = SIZE_MAX;
+ } else {
+ r.na = (row - 1) * ncols + col;
+ r.nb = row * ncols + col + 1;
+ }
+ break;
+ case 'J':
+ if (col == 0 || row == 0) {
+ r.na = SIZE_MAX;
+ r.nb = SIZE_MAX;
+ } else {
+ r.na = (row - 1) * ncols + col;
+ r.nb = row * ncols + col - 1;
+ }
+ break;
+ default: // S or .
+ r.na = SIZE_MAX;
+ r.nb = SIZE_MAX;
+ }
+
+ return r;
+}
+
+static inline size_t traverse(size_t start, size_t next, pos_t *ns) {
+ size_t head = next;
+ size_t tail = start;
+ size_t steps = 0;
+
+ if (ns[head].na != tail && ns[head].nb != tail) {
+ return SIZE_MAX;
+ }
+
+ while (head != start && ns[head].na != SIZE_MAX) {
+ size_t tmp = head;
+ if (ns[head].na == tail) {
+ head = ns[head].nb;
+ } else {
+ head = ns[head].na;
+ }
+ tail = tmp;
+ steps++;
+ }
+
+ if (head == start)
+ return steps;
+
+ return SIZE_MAX;
+}
+
+int main(int argc, char **argv) {
+ char **lines;
+ size_t i, j;
+ size_t nlines = readlines(&lines, "input");
+
+ size_t ncols = strlen(lines[0]) - 1;
+
+ size_t start;
+ pos_t ns[nlines * ncols];
+ for (i = 0; i < nlines; i++) {
+ for (j = 0; j < ncols; j++) {
+ ns[i * ncols + j] = compute_nbrs(i, j, lines, nlines, ncols);
+ if (lines[i][j] == 'S') {
+ start = i * ncols + j;
+ }
+ }
+ }
+
+ size_t r;
+ if ((r = traverse(start, start + 1, ns)) != SIZE_MAX) {
+ printf("%zu\n", (r + 1) / 2);
+ } else if ((r = traverse(start, start - 1, ns)) != SIZE_MAX) {
+ printf("%zu\n", (r + 1) / 2);
+ } else if ((r = traverse(start, start + ncols, ns)) != SIZE_MAX) {
+ printf("%zu\n", (r + 1) / 2);
+ } else {
+ printf("bad\n");
+ }
+}
diff --git a/day10/uppgb.c b/day10/uppgb.c
@@ -0,0 +1,302 @@
+#include "common.h"
+
+typedef struct {
+ size_t na;
+ size_t nb;
+} pos_t;
+
+static inline pos_t compute_nbrs(size_t row, size_t col, char **lines,
+ size_t nrows, size_t ncols) {
+ pos_t r;
+
+ switch (lines[row][col]) {
+ case '|':
+ if (row == 0 || row == nrows - 1) {
+ r.na = SIZE_MAX;
+ r.nb = SIZE_MAX;
+ } else {
+ r.na = (row - 1) * ncols + col;
+ r.nb = (row + 1) * ncols + col;
+ }
+ break;
+ case '-':
+ if (col == 0 || col == ncols - 1) {
+ r.na = SIZE_MAX;
+ r.nb = SIZE_MAX;
+ } else {
+ r.na = row * ncols + col - 1;
+ r.nb = row * ncols + col + 1;
+ }
+ break;
+ case 'F':
+ if (col == ncols - 1 || row == nrows - 1) {
+ r.na = SIZE_MAX;
+ r.nb = SIZE_MAX;
+ } else {
+ r.na = row * ncols + col + 1;
+ r.nb = (row + 1) * ncols + col;
+ }
+ break;
+ case '7':
+ if (col == 0 || row == nrows - 1) {
+ r.na = SIZE_MAX;
+ r.nb = SIZE_MAX;
+ } else {
+ r.na = row * ncols + col - 1;
+ r.nb = (row + 1) * ncols + col;
+ }
+ break;
+ case 'L':
+ if (col == ncols - 1 || row == 0) {
+ r.na = SIZE_MAX;
+ r.nb = SIZE_MAX;
+ } else {
+ r.na = (row - 1) * ncols + col;
+ r.nb = row * ncols + col + 1;
+ }
+ break;
+ case 'J':
+ if (col == 0 || row == 0) {
+ r.na = SIZE_MAX;
+ r.nb = SIZE_MAX;
+ } else {
+ r.na = (row - 1) * ncols + col;
+ r.nb = row * ncols + col - 1;
+ }
+ break;
+ default: // S or .
+ r.na = SIZE_MAX;
+ r.nb = SIZE_MAX;
+ }
+
+ return r;
+}
+
+static inline size_t traverse(char *type, size_t start, size_t next, pos_t *ns,
+ uint8_t *visited, size_t nn) {
+ size_t head = next;
+ size_t tail = start;
+ size_t steps = 0;
+
+ int exit = 0;
+ if (head > tail) {
+ if (head - tail == 1) {
+ exit = 1; // east
+ } else {
+ exit = 2; // south
+ }
+ } else {
+ if (tail - head == 1) {
+ exit = 3; // west
+ } else {
+ exit = 4; // north
+ }
+ }
+
+ memset(visited, nn, sizeof(*visited));
+ visited[head] = 1;
+ visited[tail] = 1;
+
+ if (ns[head].na != tail && ns[head].nb != tail) {
+ return SIZE_MAX;
+ }
+
+ while (head != start && ns[head].na != SIZE_MAX) {
+ size_t tmp = head;
+ if (ns[head].na == tail) {
+ head = ns[head].nb;
+ } else {
+ head = ns[head].na;
+ }
+ tail = tmp;
+ visited[head] = 1;
+ steps++;
+ }
+
+ int enter = 0;
+ if (head > tail) {
+ if (head - tail == 1) {
+ enter = 3; // east
+ } else {
+ enter = 4; // south
+ }
+ } else {
+ if (tail - head == 1) {
+ enter = 1; // west
+ } else {
+ enter = 2; // north
+ }
+ }
+
+ if (exit == 1) {
+ if (enter == 2) {
+ *type = 'F';
+ } else if (enter == 3) {
+ *type = '-';
+ } else if (enter == 4) {
+ *type = 'L';
+ }
+ } else if (exit == 2) {
+ if (enter == 1) {
+ *type = 'F';
+ } else if (enter == 3) {
+ *type = '7';
+ } else if (enter == 4) {
+ *type = '|';
+ }
+ } else if (exit == 3) {
+ if (enter == 1) {
+ *type = '-';
+ } else if (enter == 2) {
+ *type = '7';
+ } else if (enter == 4) {
+ *type = 'J';
+ }
+ } else if (exit == 4) {
+ if (enter == 1) {
+ *type = 'L';
+ } else if (enter == 2) {
+ *type = '|';
+ } else if (enter == 3) {
+ *type = 'J';
+ }
+ }
+
+ if (head == start)
+ return steps;
+
+ return SIZE_MAX;
+}
+
+#define IDX(r, c, n) ((3 * n) * (3 * r + 1) + (3 * c) + 1)
+
+int main(int argc, char **argv) {
+ char **lines;
+ size_t i, j;
+ size_t nlines = readlines(&lines, "input");
+
+ size_t ncols = strlen(lines[0]) - 1;
+
+ size_t start;
+ pos_t ns[nlines * ncols];
+ for (i = 0; i < nlines; i++) {
+ for (j = 0; j < ncols; j++) {
+ ns[i * ncols + j] = compute_nbrs(i, j, lines, nlines, ncols);
+ if (lines[i][j] == 'S') {
+ start = i * ncols + j;
+ }
+ }
+ }
+
+ uint8_t visited[nlines * ncols];
+ size_t r;
+ char type;
+ if ((r = traverse(&type, start, start + 1, ns, visited, nlines * ncols)) !=
+ SIZE_MAX) {
+ } else if ((r = traverse(&type, start, start - 1, ns, visited,
+ nlines * ncols)) != SIZE_MAX) {
+ } else if ((r = traverse(&type, start, start + ncols, ns, visited,
+ nlines * ncols)) != SIZE_MAX) {
+ } else {
+ printf("bad\n");
+ exit(1);
+ }
+ visited[0] = 0;
+
+ for (i = 0; i < nlines; i++) {
+ for (j = 0; j < ncols; j++) {
+ if (!visited[i * ncols + j]) {
+ lines[i][j] = '.';
+ }
+ if (lines[i][j] == 'S')
+ lines[i][j] = type;
+ }
+ }
+
+ uint8_t *expander = calloc((3 * ncols * 3 * nlines), sizeof(*expander));
+
+ for (i = 0; i < nlines; i++) {
+ for (j = 0; j < ncols; j++) {
+ switch (lines[i][j]) {
+ case '-':
+ expander[IDX(i, j, ncols)] = 1;
+ expander[IDX(i, j, ncols) - 1] = 1;
+ expander[IDX(i, j, ncols) + 1] = 1;
+ break;
+ case '|':
+ expander[IDX(i, j, ncols)] = 1;
+ expander[IDX(i, j, ncols) - 3 * ncols] = 1;
+ expander[IDX(i, j, ncols) + 3 * ncols] = 1;
+ break;
+ case 'F':
+ expander[IDX(i, j, ncols)] = 1;
+ expander[IDX(i, j, ncols) + 1] = 1;
+ expander[IDX(i, j, ncols) + 3 * ncols] = 1;
+ break;
+ case '7':
+ expander[IDX(i, j, ncols)] = 1;
+ expander[IDX(i, j, ncols) - 1] = 1;
+ expander[IDX(i, j, ncols) + 3 * ncols] = 1;
+ break;
+ case 'L':
+ expander[IDX(i, j, ncols)] = 1;
+ expander[IDX(i, j, ncols) + 1] = 1;
+ expander[IDX(i, j, ncols) - 3 * ncols] = 1;
+ break;
+ case 'J':
+ expander[IDX(i, j, ncols)] = 1;
+ expander[IDX(i, j, ncols) - 1] = 1;
+ expander[IDX(i, j, ncols) - 3 * ncols] = 1;
+ break;
+ default:
+ expander[IDX(i, j, ncols)] = 0;
+ break;
+ }
+ }
+ }
+
+ stack_u64 stack;
+ stack_u64_init(&stack);
+ stack_u64_push(&stack, 0);
+ expander[0] = 1;
+
+ size_t x;
+ while (stack.nmemb > 0) {
+ x = stack_u64_pop(&stack);
+
+ if (x % (3 * ncols) != 0 && expander[x - 1] == 0) {
+ stack_u64_push(&stack, x - 1);
+ expander[x - 1] = 1;
+ }
+
+ if ((x + 1) % (3 * ncols) != 0 && expander[x + 1] == 0) {
+ stack_u64_push(&stack, x + 1);
+ expander[x + 1] = 1;
+ }
+
+ if ((x >= 3 * ncols) && expander[x - 3 * ncols] == 0) {
+ stack_u64_push(&stack, x - 3 * ncols);
+ expander[x - 3 * ncols] = 1;
+ }
+
+ if ((x < (3 * nlines - 1) * (3 * ncols)) && expander[x + 3 * ncols] == 0) {
+ stack_u64_push(&stack, x + 3 * ncols);
+ expander[x + 3 * ncols] = 1;
+ }
+ }
+
+ uint64_t count = 0;
+ for (i = 0; i < 3 * nlines; i++) {
+ for (j = 0; j < 3 * ncols; j++) {
+ if (!expander[(3 * ncols) * i + j]) {
+ if (i % 3 == 1 && j % 3 == 1) {
+ count++;
+ }
+ }
+ }
+ }
+
+ printf("%llu\n", count);
+
+ free(expander);
+}
diff --git a/day11/Makefile b/day11/Makefile
@@ -0,0 +1,30 @@
+CC=clang
+CFLAGS+=-std=c99 -pedantic -Wall -Werror -Wstrict-prototypes
+CFLAGS+=-Wmissing-prototypes -Wmissing-declarations -Wshadow
+CFLAGS+=-Wpointer-arith -Wcast-qual -Wsign-compare
+CFLAGS+=-O2 -g
+CFLAGS+=-fstack-protector-all -Wtype-limits -fno-common
+CFLAGS+=-fno-builtin
+CFLAGS+=-I/usr/local/include
+CFLAGS+=-I../utils
+#LDFLAGS=
+
+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) $(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)
+
+utils:
+ make -C ../utils
+
+clean:
+ rm -rf common.o uppga uppgb
diff --git a/day11/common.c b/day11/common.c
@@ -0,0 +1,3 @@
+#include "common.h"
+
+size_t fn(char **lines, size_t nlines) { return 0; }
diff --git a/day11/common.h b/day11/common.h
@@ -0,0 +1,13 @@
+#ifndef COMMON_H_
+#define COMMON_H_
+
+#include <assert.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <reading.h>
+
+size_t fn(char **lines, size_t nlines);
+
+#endif
diff --git a/day11/exinput b/day11/exinput
@@ -0,0 +1,10 @@
+...#......
+.......#..
+#.........
+..........
+......#...
+.#........
+.........#
+..........
+.......#..
+#...#.....
diff --git a/day11/input b/day11/input
@@ -0,0 +1,140 @@
+..................................................................................................#..................#......................
+............#...............................................#.........#........................................#............................
+........................#................#.........#....................................................#......................#.......#....
+....#............................................................#.............#............................................................
+...............................................#....................................................#.......................................
+...........................#..........................#.....................................................................................
+..................................#...................................................................................#............#........
+...................#.....................................................#....................................................#.........#...
+.......#.................................#.......#...........#...............................#.............#.....#..........................
+............................................................................................................................................
+....................................................................#.........#........#....................................................
+.#........#.....#.......#..............................................................................#.........................#..........
+............................................#...........................................................................#...................
+.......................................#.......................#............................................................................
+.......#....................#............................#......................................................#...........................
+.............#..............................................................#.....#......................#.................#................
+...........................................................................................#................................................
+.........................#............................#.....#...............................................................................
+...................................#...................................#....................................................................
+........................................................................................#............................#................#.....
+..............#......#........#.........#.........................#................#........................................................
+....#...........................................................................................#........................#..................
+............................................................................................................................................
+............................................................#...............#...........................#........................#..........
+...................................................#.............................#.................#........................................
+..#......................................................................................................................................#..
+...................#....................#..............................#....................#...................#.........#.................
+.......................................................#....................................................................................
+......#.............................#..............................................#........................................................
+...........................................................................#....................#.........#.................................
+....................................................................................................................#.......................
+#............................#............................................................#...................................#.......#.....
+...................................................#............#...........................................................................
+........................#................#........................................................#......................#..................
+.......#.......................................#.................................................................#..........................
+...........................................................#...............................................#................................
+..#.................................#................#.......................................................................#..............
+.............#....................................................#.........................................................................
+.........................................................................#.........#.....#..........................#...............#.......
+....................#.......#..................................................................#............................................
+..................................#............#...............#............................................................................
+.#.......#.............................#....................................#...............................................................
+.........................#...........................#.............#................................#..........#.........#..................
+.....#.........................#............................................................................................................
+...............#............................................#...........#...................................................................
+....................................#............................................#.....#.................#..........#........#..............
+............................................................................................................................................
+.#................#.................................................................................................................#.......
+.........................................#..............#......................................#.....#......................................
+.....#.....#...............#................................................................................................................
+.................................#.........................................................................#.............#.......#..........
+.............................................................................#.........................................................#....
+.......................................#.......................#............................................................................
+.................#.................................#.....#..........#.....................#.....................#...........................
+............#..................................................................................................................#............
+#...................................#.......................................................................................................
+........#..............#..............................#..................................................................#..................
+............................................#..............#................#......................................#........................
+............................................................................................................................................
+...................#......#.......................#..............#..........................................................#.....#........#
+................................#............................................................#..............................................
+......#...................................#.......................................#...............#.........................................
+.....................................#........................#.......#......................................#.................#............
+...........#...........#...............................#.............................................................................#......
+.#...........................................#.........................................................................#....................
+............................................................................................................................................
+..................................................................#...............................................#.........................
+..................................................................................#.......#................#................#...............
+.........................#.......#...........................................#........................................................#.....
+.....#..............#......................#.........#......#.........................................#.....................................
+.....................................................................................................................#......................
+....................................................................................#.....................................................#.
+.............#.......................#......................................................................................................
+.#......................#....................#.....................#.............................................................#..........
+..................................................#.........................................................#...............................
+.................................#........................................#.................................................................
+.....................................................................................#..............................................#.......
+............................................................................................................................................
+.......#..................#.............................#........................#.................#.................#....................#.
+..........................................................................................#.................................................
+....................................#..........................#.........................................#.....................#............
+......................#...................#..................................#....................................#.........................
+....#........#.............................................................................................................#................
+...............................#...............#......................#...............................#.....................................
+.........#.......#.......#..................................................................................................................
+.#.....................................................#....................................#.............#...........................#.....
+...........................................#......#......................#.....................................#............................
+.............................................................#..............................................................................
+.............................#......#..........................................#............................................................
+....#..................#............................................#...............................#.......................................
+.........#.......#.............................#.........................................#..................#........#............#.........
+.......................................................................................................................................#....
+#.............................................................................................#.............................................
+...................................#..............................#......................................................#..................
+............................#...........................#................#.............................#.......#..............#.............
+................................................#.........................................................................................#.
+........#.............#.....................................................................................................................
+....................................................................#......................................................#................
+............................................................#........................................#......................................
+.............#...................#.................................................#........................................................
+.............................................................................#.......................................#......................
+.........#...................#........#.........#........................................................#..............................#...
+.#....................................................................#..................................................#.......#..........
+................#...............................................................................................#...........................
+......................#....................#............#...............................#...................................................
+......#.......................................................#...................................#.........................................
+.........................................................................#......#............................................#..............
+..........#.........................................................#.......................................................................
+............................#.........#................................................................#............#.......................
+.......................#......................................................................#.............#...............................
+................#.......................................#...............................................................................#...
+#..............................#.....................................................#......................................................
+............#....................................................................................#..............#.......#...................
+.....................#..............#............................#..........................................................................
+....#.............................................................................#.......................................................#.
+.....................................................................................................#.....#.......................#........
+...............#..............#............#.............................................#................................#.................
+...........................................................#.........................................................#......................
+.....................................................#...........................................#..............#...........................
+...........#...............#.......................................#...............#........................................................
+................................#...........................................................................................................
+................#.........................#...............................#.............#.......................................#.....#.....
+...............................................................#.............................#........#...............#.....................
+..#.........................................................................................................................................
+............................#......#................................#.............#...............#.........................................
+...........#.........#.............................#.........................................................#..............................
+.....#...................................................#..................#..................................................#...........#
+..........................................#..............................................................#..................................
+.....................................#......................................................................................................
+.......................#......#............................................................#.......................#........#.....#.........
+.#........#.......................................#.........................................................#...............................
+................#................................................................#..........................................................
+.........................................#.............................................#....................................................
+...............................................#.......................................................................#........#...........
+............................................................................................................................................
+..............................#.........................#......#....................#.......................................................
+.............................................................................................................#..............................
+.................#.......................................................................................................................#..
+........#................................#.........................#............#.........#......#........................#.................
+........................#...............................................................................#...................................
diff --git a/day11/uppga.c b/day11/uppga.c
@@ -0,0 +1,98 @@
+#include "common.h"
+
+static inline int is_expandable_row(size_t i, char **lines, size_t ncols) {
+ size_t j;
+ for (j = 0; j < ncols; j++) {
+ if (lines[i][j] != '.')
+ return 0;
+ }
+ return 1;
+}
+
+static inline int is_expandable_col(size_t i, char **lines, size_t nrows) {
+ size_t j;
+ for (j = 0; j < nrows; j++) {
+ if (lines[j][i] != '.')
+ return 0;
+ }
+ return 1;
+}
+
+static inline int isin(size_t i, size_t *lst, size_t nlst) {
+ size_t j;
+ for (j = 0; j < nlst; j++) {
+ if (lst[j] == i)
+ return 1;
+ }
+
+ return 0;
+}
+
+static inline uint64_t count_betw(size_t ca, size_t cb, size_t *lst,
+ size_t nlst) {
+ size_t mi = ca > cb ? cb : ca;
+ size_t ma = ca > cb ? ca : cb;
+
+ uint64_t count = 0;
+ size_t i;
+ for (i = mi; i < ma; i++) {
+ if (isin(i, lst, nlst)) {
+ count += 2;
+ } else {
+ count++;
+ }
+ }
+
+ return count;
+}
+
+int main(int argc, char **argv) {
+ char **lines;
+ size_t i, j;
+ size_t nrows = readlines(&lines, "input");
+ size_t ncols = strlen(lines[0]) - 1;
+
+ size_t expand_cols[2 * ncols];
+ size_t expand_rows[2 * nrows];
+ size_t nexpand_cols = 0;
+ size_t nexpand_rows = 0;
+
+ for (i = 0; i < nrows; i++) {
+ if (is_expandable_row(i, lines, ncols)) {
+ expand_rows[nexpand_rows] = i;
+ nexpand_rows++;
+ }
+ }
+
+ for (i = 0; i < ncols; i++) {
+ if (is_expandable_col(i, lines, nrows)) {
+ expand_cols[nexpand_cols] = i;
+ nexpand_cols++;
+ }
+ }
+
+ size_t galaxies[4 * ncols * nrows][2];
+ size_t ngalaxies = 0;
+ for (i = 0; i < nrows; i++) {
+ for (j = 0; j < ncols; j++) {
+ if (lines[i][j] == '#') {
+ galaxies[ngalaxies][0] = i;
+ galaxies[ngalaxies][1] = j;
+ ngalaxies++;
+ }
+ }
+ }
+
+ uint64_t summarum = 0;
+ for (i = 0; i < ngalaxies - 1; i++) {
+ for (j = i + 1; j < ngalaxies; j++) {
+ uint64_t rowc =
+ count_betw(galaxies[i][0], galaxies[j][0], expand_rows, nexpand_rows);
+ uint64_t colc =
+ count_betw(galaxies[i][1], galaxies[j][1], expand_cols, nexpand_cols);
+ summarum += rowc + colc;
+ }
+ }
+
+ printf("%llu\n", summarum);
+}
diff --git a/day11/uppgb.c b/day11/uppgb.c
@@ -0,0 +1,98 @@
+#include "common.h"
+
+static inline int is_expandable_row(size_t i, char **lines, size_t ncols) {
+ size_t j;
+ for (j = 0; j < ncols; j++) {
+ if (lines[i][j] != '.')
+ return 0;
+ }
+ return 1;
+}
+
+static inline int is_expandable_col(size_t i, char **lines, size_t nrows) {
+ size_t j;
+ for (j = 0; j < nrows; j++) {
+ if (lines[j][i] != '.')
+ return 0;
+ }
+ return 1;
+}
+
+static inline int isin(size_t i, size_t *lst, size_t nlst) {
+ size_t j;
+ for (j = 0; j < nlst; j++) {
+ if (lst[j] == i)
+ return 1;
+ }
+
+ return 0;
+}
+
+static inline uint64_t count_betw(size_t ca, size_t cb, size_t *lst,
+ size_t nlst) {
+ size_t mi = ca > cb ? cb : ca;
+ size_t ma = ca > cb ? ca : cb;
+
+ uint64_t count = 0;
+ size_t i;
+ for (i = mi; i < ma; i++) {
+ if (isin(i, lst, nlst)) {
+ count += 1000000;
+ } else {
+ count++;
+ }
+ }
+
+ return count;
+}
+
+int main(int argc, char **argv) {
+ char **lines;
+ size_t i, j;
+ size_t nrows = readlines(&lines, "input");
+ size_t ncols = strlen(lines[0]) - 1;
+
+ size_t expand_cols[2 * ncols];
+ size_t expand_rows[2 * nrows];
+ size_t nexpand_cols = 0;
+ size_t nexpand_rows = 0;
+
+ for (i = 0; i < nrows; i++) {
+ if (is_expandable_row(i, lines, ncols)) {
+ expand_rows[nexpand_rows] = i;
+ nexpand_rows++;
+ }
+ }
+
+ for (i = 0; i < ncols; i++) {
+ if (is_expandable_col(i, lines, nrows)) {
+ expand_cols[nexpand_cols] = i;
+ nexpand_cols++;
+ }
+ }
+
+ size_t galaxies[4 * ncols * nrows][2];
+ size_t ngalaxies = 0;
+ for (i = 0; i < nrows; i++) {
+ for (j = 0; j < ncols; j++) {
+ if (lines[i][j] == '#') {
+ galaxies[ngalaxies][0] = i;
+ galaxies[ngalaxies][1] = j;
+ ngalaxies++;
+ }
+ }
+ }
+
+ uint64_t summarum = 0;
+ for (i = 0; i < ngalaxies - 1; i++) {
+ for (j = i + 1; j < ngalaxies; j++) {
+ uint64_t rowc =
+ count_betw(galaxies[i][0], galaxies[j][0], expand_rows, nexpand_rows);
+ uint64_t colc =
+ count_betw(galaxies[i][1], galaxies[j][1], expand_cols, nexpand_cols);
+ summarum += rowc + colc;
+ }
+ }
+
+ printf("%llu\n", summarum);
+}
diff --git a/day12/Makefile b/day12/Makefile
@@ -0,0 +1,30 @@
+CC=clang
+CFLAGS+=-std=c99 -pedantic -Wall -Werror -Wstrict-prototypes
+CFLAGS+=-Wmissing-prototypes -Wmissing-declarations -Wshadow
+CFLAGS+=-Wpointer-arith -Wcast-qual -Wsign-compare
+CFLAGS+=-O2 -g
+CFLAGS+=-fstack-protector-all -Wtype-limits -fno-common
+CFLAGS+=-fno-builtin
+CFLAGS+=-I/usr/local/include
+CFLAGS+=-I../utils
+#LDFLAGS=
+
+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) $(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)
+
+utils:
+ make -C ../utils
+
+clean:
+ rm -rf common.o uppga uppgb
diff --git a/day12/common.c b/day12/common.c
@@ -0,0 +1,3 @@
+#include "common.h"
+
+size_t fn(char **lines, size_t nlines) { return 0; }
diff --git a/day12/common.h b/day12/common.h
@@ -0,0 +1,14 @@
+#ifndef COMMON_H_
+#define COMMON_H_
+
+#include <assert.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <reading.h>
+#include <stack_u64.h>
+
+size_t fn(char **lines, size_t nlines);
+
+#endif
diff --git a/day12/exinput b/day12/exinput
@@ -0,0 +1,6 @@
+???.### 1,1,3
+.??..??...?##. 1,1,3
+?#?#?#?#?#?#?#? 1,3,1,6
+????.#...#... 4,1,1
+????.######..#####. 1,6,5
+?###???????? 3,2,1
diff --git a/day12/input b/day12/input
@@ -0,0 +1,1000 @@
+..???#??.?????? 4,3
+##??#??#?..??? 9,1,1
+.?##?#?????..? 5,1,1,1
+???#?##??? 4,4
+?.??#?????#???? 8,1
+.?#?.???##??##? 3,6
+??????#??? 3,2
+?##??##???.??.?#? 3,4,1,2,2
+#..#?#?.?????#.# 1,1,2,5,1
+#???.###???? 1,2,3,2
+???????#??????##. 1,3,2,1,2
+?..??????? 1,1,2
+.#????#??##?? 3,6
+.???##???. 2,4
+???.##??.#????#?.? 3,2,1,2,1,2
+.???????##??.???? 8,3
+#??????#????.?.. 1,1,5,1
+??????#??#?.?# 2,2,2,1
+.....??#??.?.???? 2,1
+?????.#?#?#??..?? 1,1,4,1
+.#?.?????? 2,2
+???#??.??????? 1,3,4
+?#??????#???..??.?#? 10,1,1
+???????.??. 2,2
+?????##??#?? 1,6
+?????#?##?????#? 1,1,6,1,2
+???#??????.? 5,1,1,1
+??#.?##?.#??#??.?.## 2,2,5,2
+??#?#??#?#.?.??.?.# 7,1,1,1,1,1
+.#??##????#??????#? 12,5
+?##???#?#??????. 4,6
+.?.??????????#????#? 1,1,2,7,2
+.?????????#.???????? 1,3,2,8
+??#?.?.?????? 3,1,2
+.????##????.??????? 7,2,1
+????#??.?????????? 2,4,2,1
+???.????#?#???. 2,1,1,2,1
+.#???.???##?????##?# 4,14
+??.?.?#??## 1,1,6
+#.#??#?????##??##?? 1,1,1,1,9
+.#.##????.#?#??#?. 1,5,1,4
+.???????## 1,2,2
+?.????.??.?. 3,1
+????.#?#?#.?#? 2,1,5,1
+????####??##??????? 2,14
+???????#??? 2,7
+#??.#?#?##??. 2,1,6
+???#?#???????#???? 2,9,3
+##???#???#????..# 3,3,1,1,1
+.?.????.?..??#???# 2,1,1,1,1,2
+?????.?????#??. 2,1,1,2,1
+?????.???? 3,1
+?????###?????..?? 1,8,1,1
+.?.??????#?.? 1,1,4,1
+?#?.??????#??# 2,6,1
+?.??..??#?..??#????? 3,2
+???#??????? 1,4,2
+#?.?#????#?? 1,4,2,1
+?.#?????.??#. 3,1,1
+#?..?#???##??#?????? 2,13
+????????.. 1,1,1
+?###??#????#?.#??# 6,3,1,1
+???.??#????##?#?#?? 2,2,7
+????????????.??# 1,4,1,3
+????##?..#. 2,3,1
+?.?#.?.??.#.#??? 2,1,1,3
+??#??#???.#??##?? 1,1,1,6
+???#?##?##?.??#??#. 2,1,6,5
+????#???#??.??#?. 1,5,1,1,2
+??.?..???????.?? 1,7
+?#???#?.????#? 4,1,1,2
+.?##???.????.? 4,2
+.#????.?????#??? 1,2,6,2
+?.???#???#.?#? 3,1,1,2
+???.????#? 1,3
+#.#??#??.?#.# 1,6,1,1
+.#??.????#?# 2,1,3
+??.?.##??#?#?????#? 2,1,5,2,1,2
+.?????.#??? 2,3
+???.?.??????????? 2,1,3,2
+????????????????? 2,2,6
+##.?#?#????.# 2,6,1
+??.?????????#?? 1,4
+?????????.??????? 5,1,1,1,1
+?#?????##?#????###. 2,2,4,5
+???.???????????? 1,1,1,4,4
+????..?.?????..#??.. 1,2,1
+?#?#????.??.????? 4,2,2,1,3
+.#??.?#.?#.#???#?.? 3,2,1,3,2,1
+.????#?#????#.#?.. 10,1
+#.??#??#?? 1,2,2
+?.?.??#??? 1,3
+??????#.??.? 6,1
+???.#.?????#?###? 2,1,9
+???##????# 6,2
+?#.????##?.??.????? 2,7,1,4
+?????.?#??.? 1,1,1,1
+?#???...?? 4,2
+?????.???#?? 2,1,1,3
+?#??.?.?.#?????. 4,1,2,3
+?#..?.?????#.? 1,1,2,2
+?????###????#? 1,6,1
+?.?#???#?#???.???. 1,3,6,1,1
+.????#?##????#?#.?? 1,3,3,5,1
+#???#.???# 2,1,2
+.?#???#???????.#??# 1,1,2,3,1,4
+.??.??.?##???#?##. 1,1,9
+?####.???? 4,4
+?#??##????#.?#? 9,1,1
+?#?..?#.##?#.?.?#? 1,1,2,1,1,2
+????????.#?. 1,4,1
+????#???#??#.?#.? 1,2,1,4,1
+?#?###????##?#??.# 15,1
+?#?#?.#???? 3,4
+..##???##??? 2,5
+???..??##.???#???? 3,2,1,1,1
+#.??????..???????? 1,2,2,2,1
+?????#????? 2,3,1
+.????..##????#? 1,1,7
+?.??????.??? 4,1
+????#?????...??..?. 1,1
+?.?.?##???#????.?#? 10,2
+??#???.??##?#??.??. 3,4,2,2
+?####?###?#??#.????? 11,1,1,1
+??..?????? 1,1,1
+?#???#?#?.??#? 2,4,2
+..????#?.??. 2,2,1
+?.?#??.??#????##?? 2,9
+???..????. 1,1,1
+??.??#.#.??.???#??? 1,1,1,1,1,7
+???????????#??? 2,1,6
+.?#??????? 2,1,1
+?#.??????#???????#? 1,10,1,1
+??#?????.?.???? 5,4
+#?.#???#??.??.## 1,1,2,1,2
+??????#??#??.# 1,2,6,1
+.?#?.?????????#???? 3,4,1,1,1
+..?.???#???.?? 1,1,1,1
+?#?#????#.??.?? 2,6,1
+??#??#??#? 2,5
+..??#??##?#?.? 3,4
+.???###?.#??#????. 4,6
+.??.#.?.#??? 1,1,1,1
+?#??##?##???#???.?## 2,12,3
+.#?????.???..?? 1,1,1,1,2
+?#?##???#?????#? 4,3,1,3
+?????.?####??.? 3,5,1
+????.??#?#?# 3,1,5
+???.##??#??# 1,8
+??.?#?##????#?.?# 1,1,4,2,1
+.?#????..?#? 4,2
+.#.????????? 1,2,2
+??#????.??#.??????? 4,3,7
+????#?#??.????#?? 5,5
+?#.???#???#..?##?# 2,6,1,5
+.?#?????????.??##??? 1,4,3,6
+.???#??#??# 1,5,1
+????.????###???#?#? 1,1,1,5,2,1
+???????#?#??##?. 1,1,10
+????#?..?????.? 4,1
+???.???#?#????#?.#?# 1,1,8,1,1,1
+??###???#.?. 3,1,1
+????#??.?#??##?#?# 1,1,1,10
+###??#???.?#???### 4,1,1,8
+#?.?????#??#?#?#? 1,13
+#.???.?.??#??#? 1,2,1,1,5
+?????#.???#??#?#... 5,3,4
+?#?#??#???.???#???? 4,3,1
+#???#??##??###?.?.# 5,8,1
+??????.????#???#?#.? 3,5,1,1,1
+??##?.?#?#. 4,1,1
+#??#.?????###? 4,1,5
+#?#???.?#??# 3,1,3,1
+?#?#?.?#????? 1,2,1,3
+.?????.##???#?.???? 4,7,1
+#?.?#?????????##?# 1,4,1,5,1
+?????#??#???.??# 5,3,1,1,1
+#?????????#??????.?# 1,1,1,7,1,1
+.???##???.???#??. 7,3
+#???#?????.??? 1,3,2,2
+????.??????? 1,2,2,2
+?.??????.??. 1,3,1
+???#?#????.??#? 6,3
+??????##?#?#?#????#? 1,1,1,6,6
+?#??#???#???##??. 1,2,8
+?????#??#? 1,1,4
+.???.#??#? 1,2,2
+???????????? 2,2,1
+?#???.???????? 3,1,6
+??.#..#?.?#?? 1,1,2,2
+?.????#?#? 1,6
+??.#?????#??###??? 1,1,1,9,1
+?#??#??.???????#. 7,3
+??#??.??.?. 5,1
+?????##??????#? 2,3,1,3
+?#????#?.?.#..? 7,1,1
+.#????.?.?????? 4,1
+#???#?????????.??# 9,1,1,1,1
+.???###?.????#??#??? 4,7
+?????.??????#.???? 1,6,1
+.??????#??????.???# 1,2,3,1,1,1
+?#?????.????.?????? 1,2,1,1,3,1
+???..????? 3,1,1
+.?#??.?..??##? 3,4
+???...#?#???.? 2,5
+??.???##?#.? 1,6
+??#.?????##?#?#?#? 1,1,1,1,6,2
+??#???..?#. 2,1
+#.??????#?.?# 1,1,6,1
+.?#?##?????#???? 8,5
+?.?.????#??? 1,1,5
+???###???????????# 8,3,1,1
+?#?.????????.#.? 3,1,1,1,1
+??..????????. 1,1
+.???#?..#?#??. 5,3
+.?.?.????. 1,1,1
+????????#...# 1,4,1
+?#????#.?##??. 1,1,1,5
+.?.??.??.?#?..? 1,1,1,3,1
+?#?#?.??.?????? 4,1,1,1
+??##???????? 5,2
+???#??#???.???.#? 6,2
+##?##?#??.#? 2,4,1,1
+.????.??#?????.??. 3,6,1
+?????#?.??##? 3,1,5
+.#????#?#???#?# 1,2,3,5
+??.????.?.???? 2,2,1,1
+.????.?.?? 3,2
+.?.?#????.????# 3,2,1,1
+??###.?.?? 4,1,2
+.???.?????.??? 1,4,2
+???.??#??????? 1,4,1,1
+?#.#..?##?????? 1,1,7,1
+?#???##??????? 1,8
+?..??#.????? 1,3,5
+??#??#..#???? 4,3
+#?#??.?#???.#. 5,3,1,1
+#???#?.#????.????. 1,1,2,1,3,1
+.?????????. 3,4
+???#??????????.#??? 1,9,1,2,1
+?.#?...?.?????.??#? 1,2,1,3,1,1
+.???#?.????#?? 3,5
+????.??.??.# 1,1,1,1
+???????#?#????#???. 10,3,1
+#????#??##???#?.?? 1,1,1,4,1,1
+???????????.#????? 7,2,1,1
+?###?#.?.???##?? 5,5
+?##?#????#?? 7,2
+??#??????#??#?#?# 7,2,1,1,1
+??????#?.????? 3,1,2
+?#????.?##??..#?# 5,5,1,1
+#?###?????????.##.? 9,1,1,2
+????????#?#?.?? 5,4,2
+??????##?.#. 2,1,4,1
+..?#.?#????.#? 2,6,1
+?##?#???#??#??#??#?? 8,5,2
+?#.?#??????.????? 2,6,1,1,1
+?.??????#???.#. 7,2,1
+??#?##?#..???? 6,1
+????#??..#? 5,1,1
+##??.?.??.?? 4,1,1,1
+?#?.??????#?# 1,9
+.????##????..#??? 8,1,1,1
+??????????#??#?#??? 4,9
+.###?#.?????# 5,1,4
+#.?????..?? 1,2
+?.???#?????? 1,1,5
+?##??##????? 2,2,1
+.??????#?#?#??? 1,8,1
+??#..?#???##?.#?# 3,3,3,3
+?#?#????.##?????#.? 3,1,5,1,1
+.???#?.?.??#?.#???? 2,3,3
+??????????.? 1,1,1,1
+##?#?###?????????.# 10,1,2,1
+.#.??##?#????#?. 1,7,2
+.?????????????#?.? 1,2,6
+????.#.???????? 2,1,2,3
+???.?????.?. 2,1,1,1
+?#??????#?.???.?? 1,7,1,1
+????????????? 1,4,1
+..?##?.?.????? 4,4
+????.#???? 1,1,1
+??#????#??.??.???? 1,6,1,2,1,1
+??#???#??.??? 1,1,2,3
+?.?????#??#???#?? 1,9
+#?.##?#??#??.?.??#.? 1,2,6,1,1,1
+...???????#?#?.??? 1,4
+?????#????.?#?.?? 6,2
+???????????? 1,6,1
+??..?.????##. 1,5
+#???##???#??.?. 6,2,1,1
+..??#.?#??#???????? 3,3,1,1,1,2
+?????????? 1,1,1
+???..??#?..? 2,4,1
+?.??#???#?##?##?#. 1,14
+#??????.?. 1,3
+###?.?.???.???.# 3,1,3,1,1
+??#???????#.?? 6,2
+.??????#??#???? 5,6
+???#.????.# 2,2,1
+?#?##...??####??.??# 4,6,3
+..?#?#?..#.???? 5,1
+???#?#??????? 1,4,3
+?????#???#??#???#? 1,1,3,1,3,2
+..??#?.????#???? 3,5
+###..#.???#??#???# 3,1,1,6,1
+##?????####.???? 3,7,3
+?#???##.????#?#???? 2,4,2,2,1,2
+.?.#?..#??.#? 1,1,3,1
+??.?##?#?????.??.??# 1,7,1,1,2
+?#??.#????#???#?.? 3,3,7
+????.?.??? 2,1,1
+.???.??.#??# 3,4
+?.???#????????# 5,1,1
+.??..?????. 1,2
+???.#.?.#?.?.??#?.. 1,2,2
+????###???.?#???. 6,2
+???##?#.??? 6,1
+???????.?#??.??#?? 1,4,4,4
+????..?##?##.??? 6,1
+#???????#?#? 1,1,6
+??#????#????? 7,2
+.?#??#???? 5,1
+.??????#?? 1,1,2
+.??#..?#?. 3,2
+?#??#?#??????## 2,4,5
+..???#???????? 2,2,1,1
+.#??##???#??#??? 1,9,1
+.???.?#??????. 1,1,3
+??#?????????????##?? 2,5,3,4
+??#???#????????.???# 1,6,1,4,1,1
+?????#?#?.???. 6,2
+.?????#?##??.????#? 10,6
+.???#??#??#?.#?. 10,1
+?#?.?##????? 1,4,2
+???..??#??#?.. 3,3,2
+?#????.???????#. 6,1,1,1,1
+?..?#####.??#? 6,3
+.#.?#???#???????.??? 1,9,1,2
+??#.?.????.? 3,1,1,1
+??.?#??????????#?? 4,5
+??.#??.????? 1,1,2,1
+?.#??##?###.???. 1,1,7,1,1
+#?#..#?..##?. 1,1,2,2
+???????.??#??.?.? 2,1,3,1,1
+.??#???#.??#??? 3,2,5
+??????.#.???#????? 2,1,8
+.????##?#?.##????? 8,4,1
+.???#?.#?#.?? 4,1,1,1
+???????#??.???.??#.. 4,2,1,1,1,1
+#?#?#???.??.?#???#?? 1,1,1,1,1,8
+.????..??. 4,1
+???#?#???#?#..? 1,5,1,1
+?.#??#????##?#??.??? 5,2,1,1,1
+??.?.??.??.?????# 1,1,1,5
+..??.???.??.?. 1,2
+.?????????#? 1,1,3
+.?????##???.?..?#??? 9,2
+??#??#??##?.?? 4,3,2
+???.?..????.? 2,1,3,1
+#..???#?#.??#.??? 1,1,3,2,1
+.??###?.??????#??# 5,4,1,1
+???#?#???.???????. 1,2,1,2,3,3
+.??#?##??????..#?#. 3,4,1,1,1,1
+...?#??.?.#??????##? 2,1,10
+????##?.#?#? 1,3,1,1
+???????????? 1,2,5
+.?#??#???.?.??#??#?. 5,1,1,1,3
+?#??##????. 6,2
+.?#?.??#??.????#?? 2,5,7
+??#??????#. 4,3
+.????.?.?????###???? 3,1,12
+##??#?#?#????#??.??? 5,4,2,1,1
+?#.#????.??.?#..??#? 1,5,2,1,4
+?.?#??#?.# 1,4,1
+.?#.???.#. 1,1,1
+#?##.????#?? 1,2,1,3
+.??#?#?.?????? 5,5
+..?????????????.???. 12,1
+??#?????????#?? 3,5,1
+.??????###?#?? 1,9
+#...?##??#? 1,7
+???..????.?. 3,2,1
+?.?#?.???????.#? 2,4,1
+?####?#?.??.??.#?? 6,3
+.??##??.??.#### 5,1,4
+.#?????.#???#? 3,1,4
+?#?##.?.??. 4,1
+???##?##?.?.???.?. 4,2,1,2,1
+?????#?#?.? 2,5,1
+#?#??.#??#?#???.?? 1,1,1,4,1,1
+???????.?? 1,1,1
+????#..??.?# 2,1,1,1
+????????.???# 1,3,1,2
+?#????#???#?#??? 6,3,1
+??###???????????? 3,2,3,2
+???????.???#??? 1,2,1,2,3
+??.?????.???.?? 3,1,3,1
+?###?.??????? 4,1,1
+??#??????? 3,1
+#..??#..??.???#?? 1,3,2,1,3
+?.??.#??#??##?????.# 1,2,1,3,3,1
+#.#?.?#??.?????# 1,1,4,1,3
+..?#??.??#?.?##???. 4,1,5
+#?##???.?#????..?. 6,6,1
+.#????#?#??? 1,2,1
+.#??#.#?????#?#??? 4,10,1
+##??.???.#?#?#? 4,1,1,1,1
+?.???.????#? 1,2,2,2
+??#??.??.? 4,1
+??#?????????.??.??. 4,1,1,1,2,1
+????#?.??? 2,2,2
+.??#.#?#?????????# 2,5,1,3
+##?????????? 2,1,3
+?.?????????#??#??. 2,1,7
+??????.??? 5,1
+???????#?..#?#?? 2,1,2,3
+.??#..?#??.??? 1,1,4
+?##.??#???#????#??? 2,1,1,4,3,1
+??#?????#????? 4,3,1
+#?##?#???#???? 4,1,2,2
+???.????????.? 1,6,1
+?..##?#.??.??? 1,4,1,1
+.?.##??#??#?????? 8,3
+?.?.??#??. 1,1,3
+#.???##?#???#???#??? 1,14
+???#??..???. 1,4,2
+?##???.?.. 5,1
+?#?...??#?. 2,1,2
+?#?.?#??#???????? 2,6,6
+?###..????????.?? 4,2,1,1,1
+?.#.?...#.?.? 1,1
+??##????.????##? 4,1,1,1,3
+?.#??.?##?.?? 2,4
+#####?????#.???? 6,2,2
+??#.?.??#????#???? 3,11
+?#.#?##?#???? 1,7,1
+?????????###?###.? 5,8
+?##?.?.?#???? 3,2,1
+#.####???#??#?..? 1,12
+?.?#?????#?.#. 8,1
+???.??#.??????#? 3,2,4,2
+???##??#....??. 2,5,1
+??#??.?#?.?????? 3,2,4
+????#.??#??#?## 1,1,1,5
+???????.#? 4,1,1
+?#?..???.??? 1,1,1,1
+?#????.??? 1,2
+??#???#??? 5,3
+?#??.????#?? 1,1,4
+????#?#.??#?.. 4,4
+????#???.??.?.? 5,1
+??????.#??????.# 1,3,7,1
+?###????????#?#???.. 9,5
+???#??????.? 6,1,1
+?#??????????###???. 9,5
+??????.#????# 1,1,4,1
+??..#??#.?? 1,4,1
+???????????##?#?.?? 1,2,1,3,5,1
+?#??..?#???.## 1,1,4,2
+?##?#?..## 5,2
+.?#?.???.#. 1,1,1
+.#?.????????..#? 1,1,1,2,1
+?#??.?????##?#?.?.# 2,1,7,1
+???##?.???..?.?? 5,1,1,1,1
+?#?#????.???##????? 7,8
+##??#?#..#???.??? 7,1,2
+??.??.????? 1,4
+??.#.???.?.???. 1,1,1,1,3
+..?#???#?.. 2,3
+#.##????????.?? 1,2,4,1,2
+???#.????? 3,3
+.????#??#?#?##??# 12,1
+.?#####?#?#????#. 12,1
+....#?#?????????# 9,2
+??????##?#?? 1,4,3
+?.??#??????##??#?#?. 4,9
+#????.???? 1,1,1
+#?#???.?.????? 1,1,2,3
+..???????#???####. 1,11
+??????##???. 1,1,7
+????????????#?????? 1,1,14
+.?#???#?????# 2,1,5
+??.???????..?? 1,1,2,1
+???????.?? 2,2
+.?.#?#?.?## 3,2
+#??????.#. 4,2,1
+?#????????#.??. 1,2,1,1,1
+##?.?.#??##??#?? 2,1,9
+?????####??#???? 1,6,1,1
+.#.#????#?#.??? 1,1,5,1,1
+??.?????.? 1,4
+.?.?.??..? 1,1,1
+?.??????.????? 1,1,1,3
+.#????????? 2,5
+??.?.?.#?? 1,1,2
+??.?#.???.???#?#?#? 1,2,1,6,1
+.???#.?.???#? 4,1,2
+.#???????##??##?? 1,1,10
+.????????#????.#?? 10,2
+?#?#?.#??????. 4,1,2,2
+?.##?..?#?#? 3,1,1
+.?..???#..??..?.? 3,1
+?????#?.?? 2,2,1
+????##????.?.???#.. 5,3
+.??.??#.#?? 2,2,1
+??#??#??#?##?? 2,10
+.??#..???#????????? 2,11
+.??????.??##???????? 5,10
+????.????#? 2,2,1
+?#.??.??.?#. 1,1,1,2
+??????#?#????#??? 2,13
+?#.?.#?#??#??# 1,1,9
+?..??..??????#? 1,5
+?#??????#??#?. 1,1,6
+.???#?#???? 1,5,1
+..##?#?#??? 2,6
+???????.???.??? 3,1,2
+#????##???.???? 7,2
+?#???????.?? 9,1
+???????????.#???#??? 5,1,1,1,1,4
+?.?##?##????.??? 1,10,1
+???#??#??????#?. 7,2
+??????.?.#? 4,1
+????..????????? 2,3,2
+.???.#?##???? 1,4
+??????.?#???#?. 1,1,2,3
+??.???????# 1,6,1
+??#????????##? 4,6
+.??#??.??#? 2,3
+?????.?.?..??? 3,1,1,1
+..?.?#?##.?#????#?# 5,8
+?#????..?????. 6,2
+?#?.??????#??. 1,7,1
+#??##.?#?#??#???.? 5,1,4,1,1
+.???.?????.? 1,2,2
+.?????.#?????????? 3,3,1,3
+#.????#?##???? 1,1,1,6
+..?#?#.??#.?.?.? 4,1,1,1,1
+.??#???????.??? 3,4,1,2
+??###...##??? 3,3
+?.?#????#????? 1,2,4,1
+..??.?#???.?#?#?. 1,3,4
+????.??#??.???##??? 1,1,1,6,1
+???#?????? 1,1,1
+?#???#??.?????#?.?? 6,6,1
+??????????????.##? 9,2
+.#????#.#??#?????? 1,2,1,1,4,1
+?.?#.??.??#???? 1,1,1,3,1
+.??#?#??#.??????.#? 5,1,1,2,2
+???#??#.#????. 4,1,1
+??....??????....? 5,1
+?#????#????#?? 3,2,1,2
+.#???????.?.?? 1,3,1,2
+##????#?#.##?# 4,3,4
+??..#??????#??? 1,1
+.#?.????##? 1,2
+???????????#?#? 2,3,4
+??.#??###?#.???.#.. 1,1,6,1,1
+???#??#??#???#???. 1,1,3,8
+.???##..?.#??## 4,5
+.##???##?..#??? 7,1
+????.???????#? 2,1,3,1
+?#?.##??#???? 2,6
+????#???#??#?????? 2,2,11
+?#?????#??#??? 1,3,5
+#????.?##???#?#??? 3,1,3,2,1,1
+#?????.?#????.???#?? 5,3,1,1,1,1
+????#?.?.##??# 2,1,3,1
+????#.???#??????##?# 2,2,1,1,2,4
+..????##???#?????#?# 4,10
+#???#?????.????#..? 5,5
+??????#?????????? 1,5,1,1,4
+.?#?????##?.#?? 6,2,3
+.?#.????#?#????????. 1,8,4
+?????#???#. 1,2,1
+.?#?#????#. 2,6
+?????#...???? 2,1,3
+?????.??????. 2,2,5
+??#?.????#????.?#?# 4,4,3,1,1
+.?#??#???#??????.?? 4,6,1
+.##?#.#???.??? 4,3,1,1
+?#??.?#??#?## 2,3,1,2
+#.??#??????#??#? 1,13
+.???.????#???#?#? 2,5,5
+###..??#.???.???.# 3,1,1,1,1,1
+??#.???##??#?##?#?. 3,2,8
+???????#???#? 9,1
+??????#?????#? 1,2,2,4
+?.####?.?# 5,1
+?.???????###??.?..?# 1,10,1,1
+#?#?#?#????. 3,7
+.?#???????? 2,1,1
+.????##..?# 6,1
+???.??.???.#?? 1,2,2
+#??#?#??..???.? 2,1,3,3
+###????#?.?.?????. 8,4
+??#??...?. 4,1
+?.?##?????#?#??#? 1,4,1,4,1
+.?.??????.?##??#?? 1,1,4,2
+?.#???.??##?#??#??# 1,1,1,1,10
+.?#??#?.?.??? 1,1,1,2
+??????#...?#?#?? 3,1,5
+?.????#?.#?###. 5,5
+?????#???.?? 1,2,4,1
+??.????#?????# 2,5,2
+?#????#?#?????. 1,9
+?#??..##?# 3,4
+?..???????#??.?.?# 1,10,2
+?#.??#?????##.?.??. 2,5,2,1,1
+#????#?????.?#? 1,1,4,1,1
+??.##??.?????????? 1,3,3,4
+?#??????.????##????? 6,1,1,4,1,1
+????##?#??? 7,1
+#???#?##???#?#???.#? 2,2,6,2,1,1
+?.#????????.? 1,3,1
+??????.?.???#???#? 1,9
+???#.#???###?????? 1,2,1,6,2
+#????#??###?#??..# 1,9,1
+?#?????#?.?..?.??#? 2,1,1,1,1,3
+?#.????.?#.##?#? 1,1,1,1,5
+??#??#???????.? 11,1
+??#?###?.?#. 5,1
+??#.?????.??? 2,5,1,1
+???.???.????#?##? 3,1,1,1,6
+????.??????.?.#???? 2,2,2,1,2,1
+???##??#?#??.??##?.. 5,3,5
+??#????.?#? 1,1,2
+?.?.????????#???. 4,4
+.?????....?#????#?.? 2,7
+?.?#??##???.#.???#.? 5,1,1,1,1,1
+????#?.##??????? 1,2,6,1
+??#??????#?#???#? 10,2
+..?#?#????###?.?.? 10,1
+????????.?.??.?.? 3,2
+#????????.?????? 3,1,2,2
+?????###????? 1,9
+.?#???.?#? 3,2
+.#????#.?##?#??? 1,2,2,1,1
+?????????#?. 5,4
+..??...?#######.. 1,8
+.???#??.????#.#?.??? 4,5,1,1
+??...?#??.????#?#. 2,2,2,3
+.?##.?#????.? 3,5
+#???##?..??.?.#.?? 3,3,1,1,1,1
+???????????? 3,1,1,2
+?????#?##..???????? 1,7,3,1,1
+???.??????#?# 2,4,1,1
+????#??.#????##??.? 2,2,8,1
+???#????#??#..?# 8,1,1
+????#?.?#.# 5,2,1
+.#.??#..?#? 1,2,1
+?..?.#?..???##? 2,4
+.????????# 1,7
+.??#?????.????? 7,2
+?.????#??????. 1,9
+?#.#?#?.?? 1,1,2
+??.#???#.?????..?.# 1,2,2,2,1,1
+??#.?.?#.? 1,2
+.##???#.#?##??.???# 2,1,5,4
+?????????#?? 1,4,1
+?????..??.#??????? 2,1,1,3,1,1
+.?#??.#.#??? 2,1,1,2
+..?.?##?????#.?#? 1,5,1,2
+???#.?.##???#??? 3,1,3,1,1
+???#????..#????????# 5,1,1,1,4,1
+???.??????#???#??# 1,1,1,9,1
+??#???.?.?#?.??? 4,1,2,1
+.???????###?#??#?.## 5,6,1,2
+?#??????????? 3,1,1
+?.????#???. 1,2,4
+?????#???#??... 1,2,5
+????#?#??#??? 1,5,1,1
+?.?????#.#.? 1,1,1,1
+#?.??????##? 1,1,1,3
+??#???????##????.#?? 1,4,5,3
+?#?#??##??.?#?# 4,2,1,1,1
+.##???????????#???? 4,2,4,1
+??#??.?????? 2,5
+??#???????.#? 6,1,1
+?.#?????#??#.? 7,2
+???????????#??? 1,3,4
+..?#???#???##??. 8,4
+??#?.#??#??????#??#. 1,14
+#??##..#.. 5,1
+???#?#????.?#..? 7,1,2
+#??#????.?#.???????? 2,1,1,2,6,1
+??##??..???#.? 5,1,1
+???????????#??.????? 1,1,1,7,1,1
+??#?#??.?#?? 1,5,2
+???.?.#.??.?#.#???# 1,1,2,1,5
+?.???#??????.?.?.?. 6,1
+??.???.??#?# 1,3,4
+?????..?.? 4,1
+#??##??.????????? 6,3,1,2
+?????.???#?#?????? 1,6
+????##?#?# 4,3
+..??#?????#. 3,3
+??????.??? 1,1,1
+????.#?#???.?#????? 3,2
+?#??#.?###?#?? 2,1,8
+?.??#???#?#?#?.#. 1,10,1
+?#??#??.?##?? 5,4
+??#?##?#?#?#??##??#? 6,3,5
+?.?.?.##?.??. 1,1,2,1
+?.?#??.#.? 4,1,1
+?.?#?#???. 1,1,4
+?#???????? 2,2,1
+????#?#?????#. 5,2,1
+????##??#?.??? 1,7,1
+????#?????##??????? 1,2,9,1
+???###?#.??. 1,3,1,1
+??????#????????? 9,3
+?.????#.?.????#? 1,1,1,1,3
+.?.??#??????##?. 7,2
+??#??#..?? 3,1
+..?#??#??????.??.??? 9,1,1,1
+????##??????###?#.?? 1,5,5,1
+.????#??#?? 1,2,4
+.##???????..???? 2,2
+##?#?.?#??#??#??? 4,4,2,1
+?#??#??.?# 5,2
+.????#.???? 4,1
+??????.??#?.. 4,3
+.??##?#?.????????? 5,7
+.?.???.??##?#??## 1,2,6,2
+.?###???????????.? 5,5,1
+?.#?#.??????? 1,1,4
+##??????#?? 5,2
+?.????????? 1,4,2
+##?###?????????.? 9,1,2
+??##??.##??. 3,1,2,1
+.#??#??#?? 4,1
+##??.?.???#?. 4,1,3
+???.??#?###..?.??? 1,7,1,1
+.?????.?#.? 1,1,2
+??..???????#..##?? 2,1,3,4
+.?#.?#?#?? 1,4
+?#?#???####????.???? 2,1,9,1,1
+?????#????.????#?? 3,1,3,4
+.?#??.?###???## 3,3,2
+??.??????.. 2,2
+??????.?.??.##???# 1,1,1,1,4,1
+?????##?.??.? 1,3,2
+.??.??.??#??.??#??? 2,2,1,1,2,1
+#??????#???###???? 1,1,1,7,1,1
+?#???.?#.?#??. 1,2,1,3
+?.?#..???????.? 2,7
+?#.#?#?#???? 1,3,1,1
+.#?????.??...#. 1,2,1,1,1
+???????????#?#??. 1,7,2
+??#???#???.???## 1,1,1,2,5
+?.??#..?#???#?????? 3,9
+???##??.#?#????####. 1,2,11
+.?##??.##?#?#?? 3,6
+????.??##?? 2,4
+??.?##?.???.?#? 1,3,1,2
+???#?.?.#?.? 4,1
+#????????# 1,3,3
+???#?#?#??#?.??? 4,1,2,1,2
+..?##??#?#.?????#??. 7,1,1,2
+???.????????. 1,1,2,2
+.?##?##?????. 2,2,2
+.?#???????????.##??? 1,2,2,2,2
+#??????.??#????# 6,4,2
+??.????#?#? 1,2,4
+??????.?????????? 4,2,1
+??????#??? 3,3,1
+.###????.?? 6,1
+??.???????. 2,1
+?##.#?????.? 2,1,1,1
+?.????#?.??#??????? 6,4,1
+.????.???##?? 1,5
+#?#???##??#??? 9,1
+???????????.?.??? 1,8
+???.#..???#????. 3,1,8
+?.?????#??????? 1,1,7
+?#??????#?#?????? 2,7,1
+?#?##?#??????# 1,6,1,1
+??#???#??#...????? 9,3
+#.??#??#?.#???? 1,2,1,1,1
+?##?.????? 2,3
+?#????##?.??###?? 8,3,1
+.????????.?.??.? 7,2
+.???#???#???.#?.? 6,1,1,1
+?##??????#??? 3,4,2
+???##?????#.??#???#. 3,1,1,5
+??.??????##?????.? 1,1,1,6,1,1
+?#??????#?#. 4,4
+????????#?????????#? 1,2,3,1,5
+????#????#???#??#?? 7,5
+?????#????. 3,6
+#?#??##?.?###????#. 3,2,4,2
+???.#???#?## 2,1,2,2
+??.?????????? 1,1,8
+?.?????#?????? 6,2
+#??.?#????#??.? 1,1,2,2,1
+???###?#??#?????? 8,4
+#??#.?.#???? 1,1,1,2
+????#?#???#?.?.?.? 8,1
+??????.?###?###??. 4,3,5
+??##???#???#? 3,1,2,2
+??.#.???#??# 1,1,4,2
+#????#?????#?????#? 1,1,1,12
+.??????#?#?? 1,6
+??#????#????#? 2,3,2
+?#?????#???...#???? 10,4
+??.?????#????#?.? 1,4,1,2
+???.????#?##?. 1,9
+????????????????. 1,5,1,3
+??#.?#?????.? 1,1,2,1
+????#????#?????? 1,2,1,3,1
+??#??..#??.?? 1,2,1,1
+.???.??#?..??. 1,4,2
+??.???#????#????#??? 2,4,1,2,4,1
+???.??????.??#? 1,2,2,4
+???#??.??#???# 1,1,1,2
+?????#.????????.#? 2,1,1,2,1,1
+#???#?#?#?#?????? 2,9,1
+?#?#?#??.#????? 1,5,3,1
+???.#????.##?##???? 2,4,7
+.?..#??#?? 1,2
+??.??????#??.??? 1,1,3,1,1
+?.???????? 1,2,1
+??#????????#??????.# 1,1,1,11,1
+?#?.???????##.?#??. 2,8,4
+.?#???.?#???????#?. 3,2,1,1,3
+??##.#?.?#??#.# 3,2,1,2,1
+##????.?#. 4,1,1
+???#?#?..?####??? 5,4
+##?.?#??#?????##??.# 2,8,4,1
+.#.?.??.????### 1,1,1,6
+?.??#??????#?? 1,1,3,4
+??.??.???.?#?? 1,1,1,2
+.#???#??????##. 1,1,4,4
+??.?????#?#???????? 1,12
+#????##????#??#???? 1,14
+???????.#.??? 5,1,1,1
+????.?#?????#?#.# 1,1,2,7,1
+?.#?.#?##????# 1,2,6,1
+.????.??#?..?#?? 1,2,4
+?#??###???.? 1,6
+?????..?#??#??? 4,6,1
+#???#????.#? 1,2,1,1
+?#?????##???#? 2,9
+?#?.#..?##? 2,1,3
+#.??.?????.???. 1,1,1,3,1
+.??.??????? 1,5
+..??.??##?####??#? 1,12
+##???#?#?????##??? 3,4,1,3,1
+?#????###? 4,4
+?.?.?????.? 1,1,2
+?.?????.????###?? 4,7
+?.?????#..? 1,1,1
+??.???..##? 1,1,3
+#??????????##??? 1,2,1,3,1
+.????#?##??#. 8,1
+??..????####? 1,4
+??#?#?#.??#???????.? 6,2,3
+????#???##??????. 8,2
+?#??#?????.?#.#?# 1,4,2,3
+?????#?#???..?????. 1,1,6,1,1
+???#????.?##????.?#? 4,1,3,2,2
+?????####?#?.??. 10,1
+?????..????????##?? 1,11
+##??#??#?.?#..? 3,1,3,2,1
+#?##?.?????#?????# 4,1,7
+.??????.??#?#.??# 6,3,1,3
+????#????#???? 1,6,2
+??###?????#.????.??? 10,1,2,2
+?.?##???#.?#?.# 1,4,1,2,1
+???.??#??#?#??.#.??? 1,1,6,1,1,1
+?.?.?..###??##??. 1,9
+#.#?#??#??##??#?? 1,1,8,3
+??????????###?#?? 2,3,3,1,1
+?#???#??##????.??? 6,3,2,1
+??.?#???#??? 1,1,3
+???#??.??.. 1,1,2
+.?#?#????#?#??.#?#? 6,3,3
+?##??#??#?#??.???? 13,3
+#.#??????. 1,1,3
+???#??????##?????? 1,3,6
+?.????????? 1,2
+#?#???????#?#????. 1,1,6,1,1,1
+.#?#?.???#.# 4,4,1
+?#?#...???.????##?? 1,1,3,1,2,1
+.#??????#?#.? 1,1,5
+...????.#?? 1,2
+.#????##??#.??.?? 1,6,1,1,1
+.##???#?????. 6,2
+??#??.??????#?####. 1,1,1,1,9
+#?????#?#?#??#??#? 2,1,11
+?????????#??#? 1,7
+??????#??.???#?? 9,5
+??????#?.?..#.?..? 1,6,1,1,1,1
+?#???#?.#??#?#? 2,2,6
+????###???.?##???? 2,5,1,2,1
+????#????? 1,7
+?.?##?#???.???. 1,2,1,2,3
+?##?#.????#?#??#??? 3,1,2,2,5
+??##??#??.?? 6,1
+#.???????##?. 1,1,1,3
+.?###.???# 3,1,1
+.??##???#?##? 1,10
+?.???.???.. 1,2
+.?#.#??##??? 2,5,1
+????????????????? 3,2,2,1,1
+.#?.???.?????#??#??? 2,1,11
+????#?????.??????. 7,1,1
+??..??##?#???#?? 1,9
+?????#?#????????? 1,12,1
+####?###????? 8,2
+?#??#??.?#?? 6,2,1
+????.##???????#??? 1,3,1,4,1
+??.????.?.??. 3,2
+#??#???.?#??##?##? 2,2,1,5,3
+???.????????? 1,3,3
+.???##?#?????? 2,9
+?##?#?#?#????.? 5,1,1,1,1
+??????#?#??????## 1,1,3,1,3
+.??????#??????#.? 1,1,1,6,1
+???#.???.???.?#??# 1,1,1,1,3,1
+????.???##??.??.?#.. 1,1,7,1,1
+??#.???#??? 1,3
+??????.???? 2,1
+???????.?#??#??###. 1,1,10
+?#?#?##?##.???? 2,7,1,1
+???..?#.??.#. 3,2,1,1
+.?...???????????#??? 2,11
+???.?.?????...??? 1,5
+???#???#??##???#??#? 2,6,3,1
+??#?.????.?.??#??##? 3,1,2,1,7
+?#?.?????#??? 3,1,4
+.#?##?.???????? 5,6
+.?.#???????. 1,5,1
+?..?#???#???????#? 6,4
+#????.?##???. 4,4
+????#.#??????? 1,2,1,3
+????.?#???##???????? 4,12,1
+?#..????#???# 1,7
+????#??#??????..#?? 1,3,2,3,1,1
+??.?##??#??... 2,3,3
+???.???#??#???..?? 1,8
+???????#?###?#?? 6,7
+?????????#?#????? 1,1,10
+?#.??.??##???.?#.? 1,4,2
+#?????##???#?.#??# 1,10,1,1
+?????????#???#??##. 1,1,1,1,7,2
+??.?#?..?? 2,1
+???#..?.??####?##??? 1,11
+?.?#????????? 1,1,2,4
+???#???.#??? 6,3
+..?????#.? 1,1,1
+?.??#?????? 1,8
+?#????????????? 4,1,4,1
+??.??##????????.???# 8,1,1
+#??.??????? 3,1,1
+????.????????????. 2,3,1,1,1
+??????#??#?. 1,4
+.?#.???.????? 2,2,4
+..???#?#??# 5,1
+..?????.?.?#?#?. 4,4
+.#?.???????.? 2,5
+#??????#??#?#?.#?. 1,3,1,2,2,1
+???..???##?????#?? 1,10
+?????..??????#?????# 1,1,1,2,3,3
+??#??##??? 7,1
+????.#?????#?#? 1,2,5
+??..??.?#? 1,3
+?????.?.???#?? 2,1,1,1
+?.#?#?#.???#?. 3,1,2
+#??.????#.?#? 1,3,1,1
+.?#?#???#?? 3,2
+.??##????#??#?? 12,1
+#??#??????? 6,3
+#?##.??#??#? 4,3,1
+#?????.???.????#??? 2,2,5
+???????.?.?..???.#? 3,1,1,1,1,2
+#?#?#.###???#?.??? 1,3,3,1,2,2
+.???##.??#?. 4,2
+??????????? 1,5
+??#.???????#?#????# 1,1,11
+???#?.??#?.???#?? 1,3,1,2,5
+?????#??????.???#?? 3,3
+??#?###????##..?? 13,2
+..?##???????#??..? 4,1,6,1
+.??????????#?. 1,3,1,1
+???????#?. 2,3
+???#.#..???? 2,1,2
+?.????.????#?? 1,1,1,5
+?#.????#??????? 1,7
+????#??????.?.?.# 1,6,1,1,1
+??.#.??#..?? 1,1,1,1
+??#????????.? 4,3
+????.?###??? 2,5
+#####??.#?.? 6,2
+?#..#??#???????? 1,1,6,1
+???#?#???##?.?#?.? 2,4,4,3
+??##??##?????#?? 9,4
+#????.#.#..?? 3,1,1,1
diff --git a/day12/uppga.c b/day12/uppga.c
@@ -0,0 +1,236 @@
+#include "common.h"
+
+static inline void read_stack(stack_u64 *s, char *line) {
+ char *cp = line;
+ uint64_t t;
+
+ while ((cp = sread_next_u64(&t, cp)) != NULL) {
+ stack_u64_push(s, t);
+ }
+}
+
+static inline size_t patlen(char *line) {
+ size_t c = 0;
+ while (line[c] == '.' || line[c] == '#' || line[c] == '?')
+ c++;
+ return c;
+}
+
+/**
+ * Check if it is possible for pattern in string s of length
+ * n to end with exactly a '#'s.
+ */
+static inline int can_end_with(int a, char *s, size_t n) {
+ if (a > (int)n)
+ return 0;
+
+ if (a == 0) {
+ if (n == 0 || s[n - 1] == '.' || s[n - 1] == '?')
+ return 1;
+ return 0;
+ }
+
+ if (s[n - 1] != '?' && s[n - 1] != '#')
+ return 0;
+
+ assert(a > 0);
+
+ return can_end_with(a - 1, s, n - 1);
+}
+
+/**
+ * Check if it is possible for pattern in string s of length
+ * n to begin with exactly a '#'s.
+ */
+static inline int can_beg_with(int a, char *s, size_t n) {
+ if (a > (int)n)
+ return 0;
+
+ if (a == 0) {
+ if (n == 0 || s[0] == '.' || s[0] == '?')
+ return 1;
+ return 0;
+ }
+
+ if (s[0] != '?' && s[0] != '#')
+ return 0;
+
+ assert(a > 0);
+
+ return can_beg_with(a - 1, &s[1], n - 1);
+}
+
+static uint64_t counter(char *t, size_t l, uint64_t *s, size_t n) {
+ size_t i;
+ uint64_t r = UINT64_MAX;
+
+ if (n == 0) {
+ if (l == 0) {
+ r = 1;
+ goto endit;
+ } else {
+ for (i = 0; i < l; i++) {
+ if (t[i] != '.' && t[i] != '?') {
+ r = 0;
+ goto endit;
+ }
+ }
+ r = 1;
+ goto endit;
+ }
+ }
+
+ if (l < 2) {
+ if (l == 0) {
+ assert(n != 0);
+ r = 0;
+ goto endit;
+ } else {
+ assert(l == 1);
+ switch (t[0]) {
+ case '#':
+ if (n == 1 && s[0] == 1) {
+ r = 1;
+ goto endit;
+ } else {
+ r = 0;
+ goto endit;
+ }
+ break;
+ case '.':
+ assert(n != 0);
+ r = 0;
+ goto endit;
+ break;
+ case '?':
+ assert(n != 0);
+ t[0] = '.';
+ r = counter(t, l, s, n);
+ t[0] = '#';
+ r += counter(t, l, s, n);
+ t[0] = '?';
+ goto endit;
+ break;
+ default:
+ assert(t[0] == '#' || t[0] == '.' || t[0] == '?');
+ }
+ }
+ }
+
+ size_t centrum = (l >> 1);
+ int k, a, b;
+ uint64_t left, right;
+ r = 0;
+ switch (t[centrum]) {
+ case '?':
+ t[centrum] = '.';
+ r += counter(t, l, s, n);
+ t[centrum] = '#';
+ r += counter(t, l, s, n);
+ t[centrum] = '?'; // prolly not needed
+ goto endit;
+ break;
+ case '.':
+ for (k = 0; k <= (int)n; k++) {
+ left = counter(t, centrum, s, k);
+ if (left != 0) {
+ r += left * counter(&t[centrum + 1], l - (centrum + 1), &s[k], n - k);
+ }
+ }
+ goto endit;
+ break;
+ case '#':
+ /* DEBUG
+ printf("---> bradgard (l = %zu, n = %zu)\n", l, n);
+ */
+ for (k = 0; k < (int)n; k++) {
+ // a + b == s[k]-1
+ for (a = 0; a < (int)s[k]; a++) {
+ b = s[k] - 1 - a;
+
+ /* DEBUG
+ printf(">> a = %d, b = %d (KAA = %d, ELL = %zu) \n", a, b, k, l);
+ int cew = can_end_with(a, t, centrum);
+ int cbw = can_beg_with(b, &t[centrum+1], l-(centrum+1));
+ printf(">> cew = %d, cbw = %d\n", cew, cbw);
+ */
+
+ if (can_end_with(a, t, centrum) &&
+ can_beg_with(b, &t[centrum + 1], l - (centrum + 1))) {
+ if (a < (int)centrum) {
+ left = counter(t, centrum - (a + 1), s, k);
+ } else {
+ assert(a == (int)centrum);
+ left = counter(t, 0, s, k);
+ }
+
+ if (left != 0) {
+ if (b < (int)(l - (centrum + 1))) {
+ right =
+ counter(&t[centrum + 1 + b + 1], l - (centrum + 1 + b + 1),
+ &s[k + 1], n - (k + 1));
+ } else {
+ assert(b == (int)(l - (centrum + 1)));
+ right =
+ counter(&t[centrum + 1 + b + 1], 0, &s[k + 1], n - (k + 1));
+ }
+ }
+
+ r += left * right;
+ }
+ }
+ }
+ goto endit;
+ break;
+ default:
+ assert(t[centrum] == '?' || t[centrum] == '.' || t[centrum] == '#');
+ }
+
+endit:
+ /* DEBUG
+ for(i = 0; i < l; i++) {
+ printf("%c", t[i]);
+ }
+ if(centrum < l) {
+ printf(" <%zu, %zu> ", centrum, l);
+ }
+ printf(" [");
+ for(i = 0; i < n; i++) {
+ printf(" %llu", s[i]);
+ }
+ printf("]");
+ printf(" -> %llu\n", r);
+ */
+ return r;
+}
+
+int main(int argc, char **argv) {
+ char **lines;
+ size_t nlines = readlines(&lines, "input");
+ printf("#lines: %zu\n", nlines);
+
+ size_t i;
+ stack_u64 tmp;
+ stack_u64_init(&tmp);
+ uint64_t summa = 0;
+ for (i = 0; i < nlines; i++) {
+ // for(i = 0; i < 1; i++) {
+ while (tmp.nmemb > 0)
+ stack_u64_pop(&tmp);
+
+ size_t l = patlen(lines[i]);
+ read_stack(&tmp, lines[i]);
+
+ uint64_t cs = counter(lines[i], l, tmp.data, tmp.nmemb);
+ printf("RESULT = %llu\n", cs);
+ summa += cs;
+ }
+
+ /**
+ * Todo: Optimize by having second branch to be conditional
+ * on the result of the first when product is to be
+ * calculated.
+ */
+
+ printf("%llu\n", summa);
+}
diff --git a/day12/uppgb.c b/day12/uppgb.c
@@ -0,0 +1,288 @@
+#include "common.h"
+
+static inline void read_stack(stack_u64 *s, char *line) {
+ char *cp = line;
+ uint64_t t;
+
+ while ((cp = sread_next_u64(&t, cp)) != NULL) {
+ stack_u64_push(s, t);
+ }
+}
+
+static inline size_t patlen(char *line) {
+ size_t c = 0;
+ while (line[c] == '.' || line[c] == '#' || line[c] == '?')
+ c++;
+ return c;
+}
+
+/**
+ * Check if it is possible for pattern in string s of length
+ * n to end with exactly a '#'s.
+ */
+static inline int can_end_with(int a, char *s, size_t n) {
+ if (a > (int)n)
+ return 0;
+
+ if (a == 0) {
+ if (n == 0 || s[n - 1] == '.' || s[n - 1] == '?')
+ return 1;
+ return 0;
+ }
+
+ if (s[n - 1] != '?' && s[n - 1] != '#')
+ return 0;
+
+ assert(a > 0);
+
+ return can_end_with(a - 1, s, n - 1);
+}
+
+/**
+ * Check if it is possible for pattern in string s of length
+ * n to begin with exactly a '#'s.
+ */
+static inline int can_beg_with(int a, char *s, size_t n) {
+ if (a > (int)n)
+ return 0;
+
+ if (a == 0) {
+ if (n == 0 || s[0] == '.' || s[0] == '?')
+ return 1;
+ return 0;
+ }
+
+ if (s[0] != '?' && s[0] != '#')
+ return 0;
+
+ assert(a > 0);
+
+ return can_beg_with(a - 1, &s[1], n - 1);
+}
+
+static uint64_t counter(char *t, size_t l, uint64_t *s, size_t n) {
+ size_t i;
+ uint64_t r = UINT64_MAX;
+
+ if (n == 0) {
+ if (l == 0) {
+ r = 1;
+ goto endit;
+ } else {
+ for (i = 0; i < l; i++) {
+ if (t[i] != '.' && t[i] != '?') {
+ r = 0;
+ goto endit;
+ }
+ }
+ r = 1;
+ goto endit;
+ }
+ }
+
+ if (l < 2) {
+ if (l == 0) {
+ assert(n != 0);
+ r = 0;
+ goto endit;
+ } else {
+ assert(l == 1);
+ switch (t[0]) {
+ case '#':
+ if (n == 1 && s[0] == 1) {
+ r = 1;
+ goto endit;
+ } else {
+ r = 0;
+ goto endit;
+ }
+ break;
+ case '.':
+ assert(n != 0);
+ r = 0;
+ goto endit;
+ break;
+ case '?':
+ assert(n != 0);
+ t[0] = '.';
+ r = counter(t, l, s, n);
+ t[0] = '#';
+ r += counter(t, l, s, n);
+ t[0] = '?';
+ goto endit;
+ break;
+ default:
+ assert(t[0] == '#' || t[0] == '.' || t[0] == '?');
+ }
+ }
+ }
+
+ size_t centrum = (l >> 1);
+ int k, a, b;
+ uint64_t left, right;
+ r = 0;
+ switch (t[centrum]) {
+ case '?':
+ t[centrum] = '.';
+ r += counter(t, l, s, n);
+ t[centrum] = '#';
+ r += counter(t, l, s, n);
+ t[centrum] = '?'; // prolly not needed
+ goto endit;
+ break;
+ case '.':
+ for (k = 0; k <= (int)n; k++) {
+ left = counter(t, centrum, s, k);
+ if (left != 0) {
+ r += left * counter(&t[centrum + 1], l - (centrum + 1), &s[k], n - k);
+ }
+ }
+ goto endit;
+ break;
+ case '#':
+ /* DEBUG
+ printf("---> bradgard (l = %zu, n = %zu)\n", l, n);
+ */
+ for (k = 0; k < (int)n; k++) {
+ // a + b == s[k]-1
+ for (a = 0; a < (int)s[k]; a++) {
+ b = s[k] - 1 - a;
+
+ /* DEBUG
+ printf(">> a = %d, b = %d (KAA = %d, ELL = %zu) \n", a, b, k, l);
+ int cew = can_end_with(a, t, centrum);
+ int cbw = can_beg_with(b, &t[centrum+1], l-(centrum+1));
+ printf(">> cew = %d, cbw = %d\n", cew, cbw);
+ */
+
+ if (can_end_with(a, t, centrum) &&
+ can_beg_with(b, &t[centrum + 1], l - (centrum + 1))) {
+ if (a < (int)centrum) {
+ left = counter(t, centrum - (a + 1), s, k);
+ } else {
+ assert(a == (int)centrum);
+ left = counter(t, 0, s, k);
+ }
+
+ if (left != 0) {
+ if (b < (int)(l - (centrum + 1))) {
+ right =
+ counter(&t[centrum + 1 + b + 1], l - (centrum + 1 + b + 1),
+ &s[k + 1], n - (k + 1));
+ } else {
+ assert(b == (int)(l - (centrum + 1)));
+ right =
+ counter(&t[centrum + 1 + b + 1], 0, &s[k + 1], n - (k + 1));
+ }
+ }
+
+ r += left * right;
+ }
+ }
+ }
+ goto endit;
+ break;
+ default:
+ assert(t[centrum] == '?' || t[centrum] == '.' || t[centrum] == '#');
+ }
+
+endit:
+ /* DEBUG
+ for(i = 0; i < l; i++) {
+ printf("%c", t[i]);
+ }
+ if(centrum < l) {
+ printf(" <%zu, %zu> ", centrum, l);
+ }
+ printf(" [");
+ for(i = 0; i < n; i++) {
+ printf(" %llu", s[i]);
+ }
+ printf("]");
+ printf(" -> %llu\n", r);
+ */
+ return r;
+}
+
+static inline void linear_remake(char *out, char *in) {
+ size_t i;
+ char *co = out;
+ char *ci = in;
+
+ // five times until space
+ for (i = 0; i < 5; i++) {
+ while (*ci != ' ') {
+ *co = *ci;
+ co++;
+ ci++;
+ }
+ // add extra ?
+ if (i < 4) {
+ *co = '?';
+ co++;
+ }
+ ci = in;
+ }
+
+ // go to space
+ while (*ci != ' ')
+ ci++;
+
+ in = ci + 1;
+
+ // five times numbers
+ for (i = 0; i < 5; i++) {
+ while (*ci != '\n' && *ci != '\0') {
+ *co = *ci;
+ co++;
+ ci++;
+ }
+ if (i < 4) {
+ *co = ',';
+ co++;
+ }
+ ci = in;
+ }
+
+ // newline null
+ *co = '\n';
+ co++;
+ *co = '\0';
+ co++;
+}
+int main(int argc, char **argv) {
+ char **lines;
+ size_t i;
+ size_t nlines = readlines(&lines, "input");
+ printf("#lines: %zu\n", nlines);
+
+ char linez[nlines][512];
+ for (i = 0; i < nlines; i++) {
+ linear_remake(linez[i], lines[i]);
+ printf("%s", linez[i]);
+ }
+
+ stack_u64 tmp;
+ stack_u64_init(&tmp);
+ uint64_t summa = 0;
+ for (i = 0; i < nlines; i++) {
+ // for(i = 0; i < 1; i++) {
+ while (tmp.nmemb > 0)
+ stack_u64_pop(&tmp);
+
+ size_t l = patlen(linez[i]);
+ read_stack(&tmp, linez[i]);
+
+ uint64_t cs = counter(linez[i], l, tmp.data, tmp.nmemb);
+ printf("RESULT = %llu\n", cs);
+ summa += cs;
+ }
+
+ /**
+ * Todo: Optimize by having second branch to be conditional
+ * on the result of the first when product is to be
+ * calculated.
+ */
+
+ printf("%llu\n", summa);
+}
diff --git a/day13/Makefile b/day13/Makefile
@@ -0,0 +1,30 @@
+CC=clang
+CFLAGS+=-std=c99 -pedantic -Wall -Werror -Wstrict-prototypes
+CFLAGS+=-Wmissing-prototypes -Wmissing-declarations -Wshadow
+CFLAGS+=-Wpointer-arith -Wcast-qual -Wsign-compare
+CFLAGS+=-O2 -g
+CFLAGS+=-fstack-protector-all -Wtype-limits -fno-common
+CFLAGS+=-fno-builtin
+CFLAGS+=-I/usr/local/include
+CFLAGS+=-I../utils
+#LDFLAGS=
+
+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) $(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)
+
+utils:
+ make -C ../utils
+
+clean:
+ rm -rf common.o uppga uppgb
diff --git a/day13/common.c b/day13/common.c
@@ -0,0 +1,3 @@
+#include "common.h"
+
+size_t fn(char **lines, size_t nlines) { return 0; }
diff --git a/day13/common.h b/day13/common.h
@@ -0,0 +1,13 @@
+#ifndef COMMON_H_
+#define COMMON_H_
+
+#include <assert.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <reading.h>
+
+size_t fn(char **lines, size_t nlines);
+
+#endif
diff --git a/day13/exinput b/day13/exinput
@@ -0,0 +1,15 @@
+#.##..##.
+..#.##.#.
+##......#
+##......#
+..#.##.#.
+..##..##.
+#.#.##.#.
+
+#...##..#
+#....#..#
+..##..###
+#####.##.
+#####.##.
+..##..###
+#....#..#
diff --git a/day13/input b/day13/input
@@ -0,0 +1,1387 @@
+.####.#...##.#.
+...###.##.#.#..
+...###.##.#.#..
+.####.#...#..#.
+..##......#..#.
+#.#...#.##...##
+.#.#.#..##..##.
+#..##...#####.#
+.#.#.#.#..##.#.
+.....###.#.#..#
+.....###.#.#..#
+
+.#.###.....
+#..#.##...#
+.#.....#.#.
+.#.....#.#.
+#..#.##...#
+.#.###.....
+##.#..##.##
+#....##..#.
+.##.##.#.##
+...#..###.#
+...#..###.#
+.##.##.#.##
+#....##..#.
+####..##.##
+.#.###.....
+#..#.##...#
+.#.....#.#.
+
+###....##....
+####..#..#..#
+..###.####.##
+..#..######..
+...#.######.#
+#####.#.##.##
+##.#..#..#..#
+##....####...
+....#......#.
+.....#.##.#..
+##...##..##..
+...##.#..#.##
+##..###..###.
+
+.##.#...##.
+.#.########
+.##.#.#.##.
+#.##..#....
+####.##....
+####.##....
+#.##..#....
+.##.#.#.##.
+.#.########
+.##.#...##.
+..####.####
+.##.###.###
+.#..#.#.##.
+#.####..##.
+...#..#....
+
+.....##..#.
+.##..##.#.#
+#..#...####
+####.....##
+#..#.##....
+#####.....#
+#####.....#
+#..#.##....
+####.#...##
+#..#...####
+.##..##.#.#
+.....##..#.
+....##.##..
+
+#####..
+.##.#..
+.##....
+.##...#
+.##....
+#..####
+..#.#.#
+#####..
+#####.#
+.##...#
+.##.##.
+.##.##.
+.##...#
+
+.##.#.##.##.##.##
+.##.####....###..
+.##.#.#.#.##..##.
+#..#.#..#.#.##.#.
+....####...####..
+#..##.#...######.
+....#.#..........
+#..#.##.####..###
+#####...##......#
+....###..##.##.##
+####..###..####..
+.##..##..#.####.#
+#..##..##..#..#..
+.##..#.#.#..##..#
+####..####.####.#
+####.....###..###
+#..#..##.##.##.##
+
+.#..#.#.#####
+#.##.#.#.#.##
+#.##.#.#.#.##
+.#..#.#.#.###
+##..##..###..
+##.####.#####
+.##.#.#...###
+
+.###.#.###.###..#
+...####.####..#.#
+#..####.####..#.#
+.###.#.###.###..#
+...###..#..##....
+.#.#####.###..###
+#.#.#####.#.#####
+.##.###.#...###..
+.##.#.....##..##.
+#..##.####...##..
+#.#.#..#....#.###
+..#...#...##..##.
+##..#.######...##
+###.#.####..#..##
+...#..##..##...##
+###....##.#..#..#
+###....##.#..#..#
+
+##.###..####..#
+#.###.###.##..#
+..##...##..##.#
+..##...##..##.#
+#.###.###.##..#
+##.###..####..#
+....#####.#####
+##..#....#.#..#
+##.#..#.#...#..
+.##.#..##.#.###
+.##.#..##.#.###
+#..#..#.#...#..
+##..#....#.#..#
+
+.###.#....##....#
+#.##.##........##
+...###.#..##..#.#
+...###.#..##..#.#
+#.##.##........##
+.###.#....##....#
+.###..#.##..##.#.
+.###.#...####...#
+####.....####....
+###...##...#..##.
+.#..#.#.#.##.#.#.
+
+#.#..#.
+#.#..#.
+#......
+###..##
+##.##.#
+..####.
+#......
+##.....
+.##..##
+..#..#.
+..#..#.
+.##..##
+...##..
+
+##.#########..##.
+...#.####.#.##..#
+##.#...#..##..##.
+....#..###.##.#.#
+....#..###.##.#.#
+##.#...#..#...##.
+...#.####.#.##..#
+##.#########..##.
+##...####...##...
+###...##..###.#.#
+...#.#..##.#.....
+.........#####...
+....##..#.#.##.##
+...#.#.###.....#.
+...##..#.##.#.#.#
+##...##....#.####
+###....###......#
+
+..##.##.##......#
+.###....###....##
+#.###..###.####.#
+.##########.##.##
+...##..##........
+###......###..###
+.##########....##
+.#.######.#.##.#.
+.....##.....##...
+####.##.####..###
+...#....#........
+.##.#..#.##.....#
+..##.##.##......#
+
+####.##
+.##..#.
+..###.#
+.##.#.#
+###.#..
+##...##
+##...##
+#####..
+.##.#.#
+..###.#
+.##..#.
+####.##
+####.##
+.##..#.
+..###.#
+
+#.###..
+.....##
+..#....
+.#.##..
+..#.###
+..#..##
+.#.##..
+
+#..#.###....#####
+##.####.####.####
+#...###..#..#.##.
+..###.#.##.....#.
+..#....####..####
+...#.###.#.##.##.
+.#...###.#..#####
+.#.#...##.#......
+.##.##..#.....##.
+.#..#.#...##.#..#
+.#....##.##.##..#
+###..####.###....
+###..####.###....
+
+######.#.##....
+.####.#..##.##.
+.####.##..#....
+.####.#.#.#####
+#....#..####..#
+.####...#.#....
+..........##..#
+..##..#.#####.#
+######.#...####
+#.##.##.....##.
+.#..#...##.####
+..........#####
+#.##.#####.#..#
+
+#####.#
+##.##.#
+#.#.###
+...##.#
+######.
+......#
+......#
+######.
+...##.#
+#.#.###
+##.##.#
+
+.#..#.#####...#..
+#######.#.#.....#
+#....#...#.#...##
+######...###...##
+.#..#..###..#..##
+#....##..#...##.#
+.####..##.###.##.
+.#..#.##.###..#..
+#....#.#.##.##.#.
+.#..#.#...#.##...
+.####.##.#.#....#
+.......#.##.#.##.
+.......#.##.#.#..
+.####.##.#.#....#
+.#..#.#...#.##...
+
+##.####
+..#....
+###....
+.##....
+#.#....
+#.#....
+..#....
+###.##.
+#..####
+#.#####
+###....
+#..####
+.######
+##.####
+.#.....
+
+###.##....##.##
+##.##......##.#
+####...##...###
+....#.#..#.#...
+....#.....##...
+#####..##..####
+###..##..##..##
+###..#.##.#..##
+###..#....#..##
+#####.####.####
+..#.#..##..#.#.
+..#..#.##.#..#.
+##............#
+
+###.#.##.#.#.#.
+###.#.##.###.#.
+##..#...##....#
+.#..###.###..##
+#.#......###.##
+........##.##.#
+........##.##.#
+#.#......###.##
+.#..###.###..##
+##..#...##....#
+###.#.##.###.#.
+###.#.##.#.#.#.
+.#..#.#...#.###
+.....##.#.##.#.
+.#.###.#.###.##
+.#.#.....###.#.
+##....####.#.##
+
+###......###.
+##.######.###
+###.####.###.
+##..#..#..##.
+..##....##...
+###..##..###.
+####....#####
+####.##.####.
+##.##..##.##.
+#...####...#.
+...#....#....
+...#....#....
+..#.#..#.#..#
+
+.##..##.###..##
+.##.#...##.#.#.
+.##.#...##.#.#.
+.##..##.###..##
+#...#.#..####..
+.#.#....#.#....
+#..##..#..##...
+##....####..#..
+.#.....#.###..#
+..#....#.#...#.
+.##...#.#..#.##
+...##.#..######
+.###.......####
+.###.......####
+...##.#...#####
+
+.#........#.##.
+#.##.#...##.#.#
+###.####...##.#
+###.####..###.#
+#.##.#...##.#.#
+.#........#.##.
+...#.##.#.#.##.
+#.####.###.####
+.#...##.##.###.
+.....#..#.####.
+##.##.##..##..#
+.....#..#.....#
+##.##.#.#####..
+##.##.#.#####..
+.....#..#.....#
+##.##.##..##..#
+.....#..#.####.
+
+######.##.###
+.#..##.##.##.
+#.#.##.##.##.
+#.#..#.##.#..
+....#.####.#.
+#...#..##..#.
+####.#....#.#
+.###.######.#
+####.###.##.#
+....###..###.
+..###.####.##
+..###.####.##
+....###..###.
+
+..##..##..#
+..###.#....
+##....#....
+###.#.#.##.
+##.####.##.
+##...##.##.
+...##..####
+##.#####...
+...#.##....
+..#####.##.
+...#..##..#
+..#.#..####
+##.....####
+...##.#.##.
+..#####.##.
+.....#.#..#
+##.##...##.
+
+#......##.##.##
+..####..#####..
+..#..#...#..#..
+.######.##.#...
+..#..#....#####
+...##....######
+.........#.##..
+.##..##.#......
+####.####.#.###
+
+#......##......##
+..####....####...
+..#..#....#..#..#
+...##......##....
+################.
+.#....#..#....#..
+...##......##....
+.#....#..#....#..
+##....####....##.
+..#..#....#..#...
+..#..#....#..#..#
+##.##.####.##.##.
+###..######..###.
+..####....####...
+...##......##....
+####.######.#####
+.#.##.#..#.##.#.#
+
+...##.##.##..
+##..........#
+##..##..##..#
+..#.######.#.
+##...####...#
+...##.##.##..
+###..####..##
+##...####...#
+...##.#..##..
+....##..##...
+##..#.##.#..#
+
+.#.##.####.##.#..
+##..###..###..##.
+##..##....##..##.
+#.#.##....##.#.#.
+#.#.###..###.#.#.
+##...##..##...###
+#..#.##..##.#..##
+....#.#..#.#....#
+....#.#..#.#.....
+
+.##.#.....#...###
+###..#.####..####
+##....#..####....
+#..###..#.#..####
+..#.####.####.##.
+.##....##...#.##.
+.##....##...#.##.
+..#.####.####.##.
+#..###..#.#..####
+##....#..####....
+###..#.####..####
+
+##..#.#..#.#.
+##.###.##.###
+#######..####
+##..##....##.
+##.####..####
+#####..###.##
+####...##...#
+....###..###.
+..##..#..#..#
+..#..##..##..
+##.##.#..#.##
+###.###..###.
+...##.####.##
+##.###.##.###
+...#...##...#
+..#....##....
+.....#....#..
+
+..#.##.##
+..#..####
+#...#.##.
+#...#.##.
+..#..####
+..#.##.##
+######...
+#.##..#..
+.#.....#.
+###.###.#
+#.##..###
+.#..#..#.
+###.##...
+###..#...
+###..#...
+###..#...
+.#..#..#.
+
+###.###.##.
+###.###.##.
+##.#.##..#.
+....#.##.##
+.#.##.##.##
+###....####
+###.##..#..
+
+####.#..##..#.#
+.......######.#
+####.##.....#..
+####.##.....#..
+.......######.#
+####.#..##..#.#
+.##.####.#.#.#.
+######....#.#.#
+.......#....#..
+###...###.#####
+#..#..#####.###
+......##.##.#..
+.##.###.###...#
+####...###.####
+#####.###...#.#
+
+#####....
+#...#####
+#....####
+#..##..##
+#..##..##
+#....#.##
+#...#####
+#####....
+#..#..#..
+.#....###
+##.#..#..
+.#...####
+###.#.###
+##.#.....
+##...#.##
+
+....#.#.#......
+.....#.#####...
+....###..#.#...
+..#...#..##.###
+####...##..####
+.##...##.###.##
+#..#..#........
+#..###..##.....
+.....####...#..
+.##.#.#.###.###
+####.##.#.#.###
+.....#.#.....##
+########...####
+#..###..###..##
+.##.###.#..####
+
+.#.#..##.#.#.#.
+....##.....##..
+#.#.####..####.
+#..#..##.###...
+#..#..##.###...
+#.#.####.#####.
+....##.....##..
+.#.#..##.#.#.#.
+.#####..#..####
+#....#.#..##..#
+#..#.#..##.#..#
+#.##..#..#.#..#
+.####..##.#..#.
+.####..##.#..#.
+#.##..#..#.#..#
+#..#.#..##.#..#
+#....#.#..##..#
+
+#..#######..#.#..
+#.#...#.###..####
+##....###.###.###
+.........#.#.....
+.#.#..####...##..
+#.#.##.#.###...##
+#.#.#...####.....
+#.#.#...####.....
+#.#.##.#.###...##
+.#.#..####...#...
+.........#.#.....
+##....###.###.###
+#.#...#.###..####
+#..#######..#.#..
+##...#.####....##
+
+....######.
+###.....#.#
+###.....#.#
+.#..######.
+.#..######.
+###.....#.#
+###.....#.#
+....######.
+.#####.###.
+#..#......#
+##....##.##
+.#.#.#..#.#
+.####....##
+##...#.#.#.
+#...###..#.
+
+########..###
+....###....##
+....###.##.##
+####.........
+....####..###
+#..##..####..
+######.####.#
+#..#...#..#..
+####...####..
+.##.....##..#
+#..##########
+#..#..######.
+.##.#..#..#..
+
+#.##.####.#....
+#.##.####.#....
+##...##.##..###
+..#..#...#.#..#
+#.#....#.##...#
+.#.####.#...#.#
+####.#.#....###
+.##.#.####...##
+.##.#.####...##
+####.#.#.#..###
+.#.####.#...#.#
+#.#....#.##...#
+..#..#...#.#..#
+##...##.##..###
+#.##.####.#....
+
+###..##
+###..##
+#..##.#
+.##....
+.##....
+#..##.#
+####.##
+
+....#...#..#.
+.##..#..#.#.#
+####.##.##.#.
+###.###..#...
+#.#.#...###.#
+#.#.#...###.#
+###.###..#...
+####.##.##.#.
+.##..#..#.#.#
+....#...#.##.
+#.###.##.##.#
+#.###.##.##.#
+....#...#.##.
+.##..#..#.#.#
+####.##.##.#.
+
+..#..#........#
+...##....#.#...
+##....###...#.#
+##....##.###.#.
+...##...#.#.#..
+........#######
+##....##.#.....
+..............#
+#########.##.#.
+........#.#.##.
+#########..##..
+.######..##..#.
+..####..###..#.
+..####.....#...
+..####...##....
+
+..#####.###
+...####.###
+.....#.#...
+.####..##.#
+##...#..###
+##...#..###
+.####..##.#
+
+#..##.###.####.##
+########.##..##.#
+.##....##.####.##
+#######.#......#.
+####..##...#....#
+####..###########
+....#############
+......##.##..##.#
+#######..##..##..
+#..##.#...#..#...
+.##.#.##.##..##.#
+.##..###..#..#..#
+....#.##........#
+.....##.#.####.#.
+.##.#.##........#
+
+.##....#...#.#...
+.##....#...#.#...
+..#...###.#####..
+.####...#..#..##.
+##.###.#.....##..
+.....##.#..#.#.##
+.#.##....##.#.#..
+#..........####..
+#.....###.##...##
+
+#.###..##..
+.#..#.#..##
+###..##....
+###..##....
+.#..#.#.###
+#.###..##..
+####.#..###
+
+.....#.####..#..#
+.....#.####..#..#
+..#.#..###.#..#.#
+####..#####.##...
+..#.##..###.....#
+##...#.###.#..#.#
+###.#.#...#...###
+.###.....#.##..#.
+.###....##.##..#.
+
+...#...#..#.##..#
+#..##.#..####.##.
+.##..#.#..##..##.
+..##..###....#..#
+.#.....###.#.####
+###..#.#.##...##.
+###..#.####...##.
+
+##.##..
+..#....
+.#.#...
+##.####
+##.####
+...#...
+..#....
+##.##..
+#.#####
+##..#..
+.#.#...
+..#.#..
+###.###
+....###
+.##.#..
+#..#.##
+##...##
+
+###.#....#.##
+#..#.#..#.#..
+#..#.#..#.#..
+###.#....#.##
+#.###....###.
+.##...#....##
+...#.####.#..
+##..##..##..#
+..#..####..#.
+.##..####..##
+##..#....#..#
+..##.#..#.##.
+.##.#....#.##
+
+..#######
+...##.##.
+##.#.####
+#.#..#..#
+.#.##....
+#.##.#..#
+...######
+#..######
+#.##.#..#
+
+######.........
+.##..##..##..##
+.......##..##..
+.#.#...#.##..##
+#.#.##...#....#
+.##..#.....##..
+.##..#.....##..
+#.#.##...#....#
+.###...#.##..##
+
+####..#.##.#.
+###.#.#.##.#.
+#.##..#.##.#.
+....#..#..#..
+.#.###.####.#
+##..#.######.
+.#.##.#.##.#.
+#.##..######.
+#.##..######.
+.#.##.#.##.#.
+##..#.######.
+.#.###.####.#
+....#..#..#..
+#.##..#.##.#.
+#.#.#.#.##.#.
+####..#.##.#.
+.#..#.#.##.#.
+
+.#........#..
+#.###..###.##
+.#..####..#..
+#.#.#..#.#.##
+.#.#.##.#.#..
+.##..##..##..
+#...####...##
+..#.#..#.#...
+...#.##.#....
+#..#....#..#.
+..#.####.#...
+.##########..
+.#........#..
+#..#....#..##
+..##....##...
+
+.##..###...#...
+.##.##.########
+#.#.#..#..#..#.
+.#......###..##
+....######.##.#
+.#.##......##..
+##.#...###.##.#
+##.#...###.##.#
+.#.##......##..
+....######.##.#
+.#......###..##
+
+.##...##.
+#..#.###.
+####.....
+#..######
+.##..#..#
+.##.#####
+....#####
+
+.###...#####.###.
+..##...#..##..##.
+..##..#..#...#..#
+##..###.#.#.#.##.
+##..##.#.#......#
+##..###...##.###.
+........##.###..#
+.####.#....###..#
+#.##.###..#..###.
+.........#.#.#..#
+##..##.#.##..###.
+##..##.#.##..###.
+.........#.#.#..#
+
+....#......#...
+....###..###...
+.....######....
+##.#.#....#.#.#
+##.....##.....#
+..##..#..#..##.
+..####....###..
+
+.....#.#..#
+#####.#####
+#..########
+#..#.######
+#....#..##.
+.##.#..#..#
+#..#..#####
+
+#.##.#..#
+##..#.##.
+..###.##.
+..#...##.
+#.#...##.
+###......
+###......
+#.#...##.
+.##...##.
+
+.......#.
+.......#.
+.#..#.#..
+.####...#
+..##..#.#
+########.
+.####.#.#
+..##.....
+..##...#.
+#....#..#
+##..##.##
+######...
+.#..#.#.#
+#.##.###.
+#.##.##..
+....#...#
+######.##
+
+#..#..#........#.
+....##..#.##.#..#
+....##.#..##..#.#
+.....#...#..#...#
+####..#.##..##.#.
+.##.#####....####
+....#.#.##..##.#.
+...######....####
+######..##..##..#
+
+###.#..
+####..#
+..#....
+###.##.
+...#..#
+..#.##.
+###.##.
+###....
+..#.##.
+
+.#..###....#...
+##...#...###...
+.#..#..##...#.#
+.#..#..##...#.#
+##...#....##...
+.#..###....#...
+###..###..#.#.#
+#.##.#.#.#####.
+#......##...#.#
+###....#.#.#.#.
+###....#.#.#.#.
+#......##...#.#
+#.##.#.#.#####.
+###..###..#.#.#
+.#..###....#...
+##...#....##...
+.#..#..##...#.#
+
+..##.#.
+##.##..
+..##.#.
+...##.#
+#.#####
+..###.#
+..#.##.
+###.###
+##...#.
+..####.
+..####.
+##...#.
+###.###
+
+.##.#...#.##.
+#.####.####.#
+####...#.#..#
+.##.#.######.
+######...##.#
+.....#..#.#..
+.....#..#.#..
+######...##.#
+.##.#.######.
+
+.###.#.#.
+...#.##..
+##.....##
+###..#.#.
+#.#..##..
+...#..##.
+.......#.
+.......#.
+...##.##.
+...##.##.
+.......#.
+.......#.
+...#..##.
+
+...##....####.##.
+.##..###.#...####
+###..###.####.##.
+.######.#....####
+########....#.##.
+..#..#..##..#....
+.##..##...#......
+..#..#..##.###..#
+#.####.##.#......
+
+#.#..#####..#..
+##.##.####..###
+#......#.##.#.#
+###..####.##...
+#.#..#.###...#.
+.#.##.#.#.#.###
+##.##.##..#.###
+.##..##.#####..
+#......#.##....
+#......#.##....
+.##..##.#####..
+##.##.##..#.###
+.#.##.#.#.#.###
+#.#..#.###...#.
+###..####.##...
+#......#.##.#.#
+##.##.####..###
+
+####..#####
+.....#..###
+#..####.#..
+.......##..
+#..#..#.###
+####.......
+.....#.#.##
+#..##..#...
+.##...##..#
+.......###.
+.##..##..##
+....#....##
+####.#.##.#
+#####.####.
+#####.###..
+
+#..#.####.#.#..
+#.#####.#.#####
+##.#...##.#...#
+#..#.##...#.##.
+#..#.##...#.##.
+##.#...##.#...#
+#.#####.#.#####
+#..#.####.#.#..
+#..#.######.###
+.....####....##
+.##.....##.####
+......#.##..##.
+......#.##..##.
+.##.....##.####
+.....####.....#
+#..#.######.###
+#..#.####.#.#..
+
+#.#...###
+#.#####..
+.###.....
+.###.....
+#.#####..
+#.#...###
+.#.....#.
+.#..###.#
+.#..###.#
+.#.....#.
+#.#...###
+#.#####..
+.#.#.....
+
+..........###
+..##....#.###
+..##....#..##
+..........###
+.####...#....
+.####.######.
+##..##.######
+.####.....##.
+.####.##.###.
+
+######..##.
+.#..#..#..#
+#######.##.
+######..##.
+.####.##..#
+.####.#....
+.####...##.
+.#..#.#####
+##..#######
+.####.#....
+#.##.##....
+..##....##.
+.#..#.#####
+##..##..##.
+.####...##.
+#.##.##..#.
+#....###..#
+
+#...#..#....#.##.
+..........###.##.
+....#.#.###..#..#
+.###...######.##.
+.###....#####.##.
+....#.#.###..#..#
+..........###.##.
+#...#..#....#.##.
+##.###.###...####
+#......#...#.#..#
+..#..##..........
+.###.###.##...##.
+..##.#####..#####
+....#.##.#.##....
+....##.#..#.##..#
+...#####....##..#
+....#.###..#.####
+
+...######...#
+##.##..##.##.
+##.#....#.###
+####.##.#####
+#..........##
+....#........
+.####..####.#
+.#.##..##.#..
+#....##....##
+#..........##
+....####.....
+##.##..##.###
+##.##..##.###
+
+###..##
+##.#.#.
+..#...#
+##..#..
+#####.#
+###..#.
+###....
+
+#####.#
+...####
+.##....
+...#..#
+#.#....
+.######
+###....
+###....
+.######
+
+..#..####..
+####.####.#
+####.####.#
+..#...###..
+##...#.#.#.
+...####...#
+....#...##.
+..#.###.#.#
+#######.##.
+...#...##.#
+..#.#.#...#
+####.#....#
+.....#..#.#
+
+######..#
+..##...#.
+##..##.#.
+#....###.
+#....##..
+##..##.#.
+..##...#.
+
+#.##..#
+#####..
+##.##..
+##.##..
+#####..
+#.##..#
+.###.##
+.#.##..
+.###.##
+.##..##
+#.#.###
+.#.....
+##.##..
+.######
+.#.####
+
+####..#..#..###
+..#.########.#.
+####...##...###
+...##########..
+..#..........#.
+###.########.##
+..#..##..##..#.
+##..#.####.#..#
+##.#.##..##.#.#
+###.###..###.##
+####.##..##.###
+..#....###...#.
+..##.#....#.##.
+##..##.##.##..#
+...##########..
+######.##.#####
+###..........##
+
+#.....#...#..#...
+##.#...#..#..#..#
+##.###.##########
+##.##.###########
+#.##...#.#.##.#.#
+#.#..............
+..##.....##..##..
+##..#......##....
+##.##.#.#.####.#.
+##..#.#.#.####.#.
+##..#......##....
+
+......#.##.#...
+#.##.#......#.#
+......####.#...
+.#..#.#....#.#.
+##..###.##.###.
+.#..#.#....#.#.
+#....##....##..
+.####..####..##
+.####.#....#.##
+
+#####.#.##.#.
+...##...##.#.
+...##...##.#.
+#####.####.#.
+####...#....#
+####.....###.
+##....###.##.
+##...##...###
+..###...##.#.
+.....#.#.##..
+...#.##......
+####..#####..
+###.#....##..
+..######..###
+....##...#..#
+
+.##.###....####
+#......#..#####
+..#..#..#.##..#
+#...##.####....
+.###...####....
+.###...####....
+#...##.####....
+..#..#..#.##..#
+#.....##..#####
+
+#..##..#.#.#..#
+....#.#.##.##.#
+....#.#.#.####.
+####.#.....##.#
+.##...#.#..###.
+.##...#.#..###.
+####.#.....##.#
+....#.#.#.####.
+....#.#.#..##.#
+#..##..#.#.#..#
+####.#...##.#.#
+#####..#.###..#
+.....#.#.#.##..
+#..##.##.###.#.
+#..#...##.#.#.#
+....##.###.#..#
+.##.###.....##.
+
+.#..#.##.####..##
+#..##..#.#.#...##
+#...#.#.##.#.##.#
+##..###....#.###.
+.###...#.#.####.#
+.###...#.#.####.#
+##..##.....#.###.
+#...#.#.##.#.##.#
+#..##..#.#.#...##
+.#..#.##.####..##
+.#....###..##...#
+#.#.######..#####
+...#.#..##...####
+.#.#####.....##..
+##.#.#.##.###....
+##.#.#.##.###....
+.#.#####.....##..
+
+.#..#.#.#.##.
+##..##.#.....
+#....#.#.####
+#.##.#.#..##.
+..##..#......
+##..##.##.##.
+#....#.#..##.
+######..#####
+..##....##..#
+#.##.#..##..#
+.........####
+..##..#.##..#
+.#..#..##....
+....#...#####
+##..##..#.##.
+.####.####..#
+##..##.######
+
+#....#..#
+###..#...
+##.######
+..##..#.#
+..####.##
+##...####
+##.#..###
+.....#.#.
+..##...#.
+...#.###.
+####..###
+......###
+...#....#
+#####.#.#
+..#.#..#.
+..#.#..#.
+#####.#.#
+
+#######...#....#.
+###.#..##..#..#..
+#.###.#..#..##..#
+#.###.#..#..##..#
+###.#..##..#..#..
+#######...#....#.
+#...#.#.##.####.#
+..#.#.#.##.#..###
+#.#...#.###....##
+.######.....##...
+#..#.#.##.##..##.
+.##..#.##.#....#.
+#.##..######..###
+#...#.#..########
+#.###.#..........
+
+#..#..#..##..#..#
+#.###############
+####..##....##..#
+##.####......####
+..#####..##..####
+#.##..#..##..#..#
+###.####.##.####.
+##.#..#......#..#
+.###..#.#..#.#..#
+.#.#..#..##..#..#
+##.####......####
+.##.##.#.##.#.##.
+.######.####.####
+
+#.#....#.
+###..#..#
+###..#..#
+#.#....#.
+.####..#.
+..##..###
+..#.#..#.
+#..#..##.
+.###.###.
+...#..#..
+...#....#
+###.#.###
+....#.#.#
+##.#.##.#
+##.####.#
+#..####.#
+##.#.##.#
+
+......#
+#####.#
+......#
+####.#.
+.##...#
+#..#.#.
+.###.##
+.....#.
+.##....
+.##....
+.....#.
+
+...###.#.....##..
+#.######.#.......
+#.##.###.#.......
+...###.#.....##..
+.#..##..#.###..##
+#..###.####...###
+#####.#...#.##...
+#####.#..###.####
+#########.#.#####
+.#####....##..###
+##.#..#..####..##
diff --git a/day13/uppga.c b/day13/uppga.c
@@ -0,0 +1,90 @@
+#include "common.h"
+
+static inline size_t parse_next(uint64_t **rows, size_t *nrows, uint64_t **cols,
+ size_t *ncols, char **lines, size_t nlines,
+ size_t s) {
+ size_t i, j;
+ size_t nc = strlen(lines[s]) - 1;
+
+ // find number of rows
+ size_t nr = 0;
+ while (s + nr < nlines &&
+ (lines[s + nr][0] == '.' || lines[s + nr][0] == '#')) {
+ nr++;
+ }
+
+ // read rows
+ uint64_t *r = malloc(nr * sizeof(*r));
+ for (i = 0; i < nr; i++) {
+ // read row i
+ r[i] = 0;
+ for (j = 0; j < nc; j++) {
+ r[i] <<= 1;
+ if (lines[s + i][j] == '#') {
+ r[i] += 1;
+ }
+ }
+ }
+
+ // read cols
+ uint64_t *c = malloc(nc * sizeof(*r));
+ for (i = 0; i < nc; i++) {
+ c[i] = 0;
+ for (j = 0; j < nr; j++) {
+ c[i] <<= 1;
+ if (lines[s + j][i] == '#') {
+ c[i] += 1;
+ }
+ }
+ }
+
+ // output
+ *rows = r;
+ *cols = c;
+ *nrows = nr;
+ *ncols = nc;
+
+ return nr + 1;
+}
+
+static inline int is_refl(uint64_t *v, size_t nv, int i) {
+ int j = i + 1;
+
+ while (0 <= i && j < (int)nv) {
+ if (v[i] != v[j])
+ return 0;
+ i--;
+ j++;
+ }
+
+ return 1;
+}
+
+int main(int argc, char **argv) {
+ char **lines;
+ size_t i;
+ size_t nlines = readlines(&lines, "input");
+
+ size_t cr = 0;
+ uint64_t summa = 0;
+ uint64_t *rows, *cols;
+ size_t nrows, ncols;
+ while (cr < nlines) {
+ cr += parse_next(&rows, &nrows, &cols, &ncols, lines, nlines, cr);
+
+ for (i = 0; i < nrows - 1; i++) {
+ if (is_refl(rows, nrows, (int)i))
+ summa += 100 * (i + 1);
+ }
+
+ for (i = 0; i < ncols - 1; i++) {
+ if (is_refl(cols, ncols, (int)i))
+ summa += (i + 1);
+ }
+
+ free(rows);
+ free(cols);
+ }
+
+ printf("%llu\n", summa);
+}
diff --git a/day13/uppgb.c b/day13/uppgb.c
@@ -0,0 +1,112 @@
+#include "common.h"
+
+static inline size_t parse_next(uint64_t **rows, size_t *nrows, uint64_t **cols,
+ size_t *ncols, char **lines, size_t nlines,
+ size_t s) {
+ size_t i, j;
+ size_t nc = strlen(lines[s]) - 1;
+
+ // find number of rows
+ size_t nr = 0;
+ while (s + nr < nlines &&
+ (lines[s + nr][0] == '.' || lines[s + nr][0] == '#')) {
+ nr++;
+ }
+
+ // read rows
+ uint64_t *r = malloc(nr * sizeof(*r));
+ for (i = 0; i < nr; i++) {
+ // read row i
+ r[i] = 0;
+ for (j = 0; j < nc; j++) {
+ r[i] <<= 1;
+ if (lines[s + i][j] == '#') {
+ r[i] += 1;
+ }
+ }
+ }
+
+ // read cols
+ uint64_t *c = malloc(nc * sizeof(*r));
+ for (i = 0; i < nc; i++) {
+ c[i] = 0;
+ for (j = 0; j < nr; j++) {
+ c[i] <<= 1;
+ if (lines[s + j][i] == '#') {
+ c[i] += 1;
+ }
+ }
+ }
+
+ // output
+ *rows = r;
+ *cols = c;
+ *nrows = nr;
+ *ncols = nc;
+
+ return nr + 1;
+}
+
+/**
+ * Checks if n is a _positive_ power of 2.
+ */
+static inline int is_power2(const uint64_t n) {
+ uint64_t t;
+
+ __asm__ volatile("POPCNT %1, %0;" : "=r"(t) : "r"(n) :);
+
+ return t == 1;
+}
+
+static inline int is_refl(uint64_t *v, size_t nv, int i) {
+ int j = i + 1;
+
+ size_t smuts = 0;
+ while (0 <= i && j < (int)nv) {
+ if (v[i] != v[j]) {
+ if (!is_power2(v[i] ^ v[j]))
+ return 0;
+ if (smuts > 0)
+ return 0;
+
+ smuts++;
+ }
+
+ i--;
+ j++;
+ }
+
+ if (smuts == 0)
+ return 0;
+
+ return 1;
+}
+
+int main(int argc, char **argv) {
+ char **lines;
+ size_t i;
+ size_t nlines = readlines(&lines, "input");
+
+ size_t cr = 0;
+ uint64_t summa = 0;
+ uint64_t *rows, *cols;
+ size_t nrows, ncols;
+ while (cr < nlines) {
+ cr += parse_next(&rows, &nrows, &cols, &ncols, lines, nlines, cr);
+
+ for (i = 0; i < nrows - 1; i++) {
+ if (is_refl(rows, nrows, (int)i))
+ summa += 100 * (i + 1);
+ }
+
+ for (i = 0; i < ncols - 1; i++) {
+ if (is_refl(cols, ncols, (int)i))
+ summa += (i + 1);
+ }
+
+ free(rows);
+ free(cols);
+ }
+
+ printf("%llu\n", summa);
+}
diff --git a/day14/Makefile b/day14/Makefile
@@ -0,0 +1,30 @@
+CC=clang
+CFLAGS+=-std=c99 -pedantic -Wall -Werror -Wstrict-prototypes
+CFLAGS+=-Wmissing-prototypes -Wmissing-declarations -Wshadow
+CFLAGS+=-Wpointer-arith -Wcast-qual -Wsign-compare
+CFLAGS+=-O2 -g
+CFLAGS+=-fstack-protector-all -Wtype-limits -fno-common
+CFLAGS+=-fno-builtin
+CFLAGS+=-I/usr/local/include
+CFLAGS+=-I../utils
+#LDFLAGS=
+
+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) $(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)
+
+utils:
+ make -C ../utils
+
+clean:
+ rm -rf common.o uppga uppgb
diff --git a/day14/common.c b/day14/common.c
@@ -0,0 +1,14 @@
+#include "common.h"
+
+uint64_t load(char **grid, size_t nr, size_t nc) {
+ uint64_t i, j;
+ uint64_t r = 0;
+ for (i = 0; i < nr; i++) {
+ for (j = 0; j < nc; j++) {
+ if (grid[i][j] == 'O')
+ r += (nr - i);
+ }
+ }
+
+ return r;
+}
diff --git a/day14/common.h b/day14/common.h
@@ -0,0 +1,13 @@
+#ifndef COMMON_H_
+#define COMMON_H_
+
+#include <assert.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <reading.h>
+
+uint64_t load(char **grid, size_t nr, size_t nc);
+
+#endif
diff --git a/day14/exinput b/day14/exinput
@@ -0,0 +1,10 @@
+O....#....
+O.OO#....#
+.....##...
+OO.#O....O
+.O.....O#.
+O.#..O.#.#
+..O..#O..O
+.......O..
+#....###..
+#OO..#....
diff --git a/day14/input b/day14/input
@@ -0,0 +1,100 @@
+.OO.#.....#..O.O.O#....O....#....O....#..##.#...#..O....#.....O...##O...O#.O.#O.O....O......O.....OO
+.......#........O...O..#.....O....O.#..#O#.#.##O.#O.#..O.O....O.###O.........#.O.O......O....#O.....
+O..O.OOO....#O..#.#......OOO.#O#O.OO..#.O#.O.....O....#O.O####...##O..O....O#..O#...#..#......O..#..
+.#.#.##...#.O.#...O##..O....#........#..#.#.O...O.......#.OO...#........#...O#.#.......O..OO.OO.OO##
+....O.O.O#.....O#.OO..O...........O.OO..#.........O...O........#.OOOO..##.#....#.#..O..O#..O#.#O..OO
+#.#...O##.##...#.#O.OO..O.##O.#.##O...#O#....#OOOO.O........#......O.....O#....O....O..O#.OO#.O.....
+......O..O.O...O...#..OOO##...O.OO....#......OO.#.....OOO##..##.#.#..#OOO.......#O.#....O....O...#.#
+O..........OOO#.O.O.#.....OO...O.#..#...OO....OO#O.#OOO..OO..#.OO.....#O##.O..#.OOO...#.#O#...#.OO..
+....O..#O...........#.O..OO##....#..................O....O.O.O.#.O.......O.O.#.....O..#O..#..#......
+....##OO.#.....#OO...O......O#.....O.OO#....O..O.###.##.OO.#O....#.OO#O#.O......##O#..O...O#.#.O..O.
+#....OO.##...#.....O.O....#O.O#...OO#..#.O.O.#..O......###.O..O......#..........O...#.O.#O#OO..O.O.#
+........#....O..O###.#.#...OO##.#.....#O.O..........#...O..O...OO##....O#..O.#O......#..O..O...#..O#
+..O.#..O......#......O..#......#...O.#O...O...O.#..#.OO.O.O...O...O.O.#....#O...O#..##..O..O......O.
+...OO.............O....#O.O..O...OOO....O..#...O....#..#.O#.#..OO..#......O.....OOO....O..##..O#....
+O.#O#.#O#.#..#.O.#....#..O...#..O#O..#.#.O..O...OO.....O...O....#.O.#OO.OOO#.O.....O..O#.O..#.OO##..
+.....#..#.O.O##O.#O..O..OO.#O..O....O..O.....O..#.##..O.............#......O...###...O.....O....#...
+O...O..O#O..#O.#O.O#.O...#O#.......O.......#...O.#.#.O#.......O.#.OO.O.#O..O..........O#...O.OO..#..
+..O.O#.O.....O.OO..O#O...#.#....#..O.OO.....O.........O.O#...#....##......OO............O.O......#..
+...O#OO.....OOO.........#OOO.O.......O.....O....O....#OO##.O##...#.................O....#O...#......
+#.O#OO.#..#.......O.O.###O....O..O.....#.O.OOO.#.O#.#..O....#..#...#.O#.O#..##..#...##OO..O#...#...#
+O...#.......O##.OO...#O..#......O.......O..#.....#..#.#..OO....#.#.#O..OO..#.OO.#..##OO#.O#OO..#...#
+...O...#...O.#O....#.......O..OO.O..O.......O.#....#O..#O#.#...#....#.#....#....O.O......O.O........
+#..O...OOOO.......#.....O..O...##O...#OO...OO..OO#O.O..#.....#O...#..#.....O.#O.#...#....#...O#....#
+.O.#O.....#...#...O.OOO#...O#..##O#OO##.#.#...O#.....#O..O#..#OO....#O...O.#..O..#.....#.#.OO...O.#.
+..#..OO......#..O..#.O.O..O.#...#.#....#.......O.#O#....O.#.O#.O.O.O..O.###O.OOO...#O....O#..O.#...#
+....O.#.....#.....OO.......O#O.O..OO#..O.O...OOOO....OO..O.#..O.....OOO.O#O.O......#..#O.O....O.#..O
+..#......#O##....O.O.OO..#.#.....O.#.#O#.....OO#......###..#.O.O#....#O...O...O...OO...OO..O.#...O.O
+#...#.....O.#..##.......#.OO......#O..O.........O#.#O#.#..#O.O......O.O..O.OO#...O.#..O...O..O.O....
+O.#..##...O.O..O....O.O.OO......O...O.O....#..#.O.....OO...O.OO.O....O....O.O.O........O..O#...OO.O.
+....O..O.O...OO#O..O..........OO#...O..O.O#...#O......#.#.#...#..O.....O..O.#O#.....O.#O.O..O#.....O
+#O...O...O..O.#.O#OO.......O#.....O.#..O.OO.#.........O..OO.....OO.OO#OO...O.#.O....#...#..#.##.O...
+##O...#.##...OO.......##..#.#.#..OO.....OO#.....OOO.OO.......O.#.O...#..O.OO.#.....##.#.#........#.#
+...OO..#....#..O...O........OO.O...##.......O...#O#..O...#....#O....#....#O..##.#O.#..O.....##OO#.O.
+.O.#.O#O.#...#..O.##.#....OO..........O.#.O.O#O...#......O.O....O#.O.#.....O...##...O.#.O.O.#O##.O..
+...#.....O....#.OO.#.#..#..#..###.....#.......#.O...O#...O..#.O#O##O.O....#.O.#....O............O...
+#.##..##....#...O.....#.O.....OO....OOO......#...O.#....OO.#....O...##..#OO.#....O..O.O#O.O..#...O#.
+O##....OO...#.#..O...#......#.##..O......#........O.O.O.#O..#.#..O..#.....#O.O.....##OO.O..O..#.....
+.....O#..O.#.#..#O#.O.......OO.O.....#.....##...O..#...OO.O.OO....OOO........O#OO...O..#.OO##OO#.O#.
+...#.O#O......O....O#................#O.....#..O.OO#.......#.#.O##......OO.#..#..O#...OO..#.#.O#O.#.
+O......#.#....O.O...O.#.O......#.#.O..OOO.O..........#..O....#..O.O.#.O.##OO..#O#.O....#O..###...#..
+..##..#...#..#.#O.#.#..#O#.#.....O.#..#OO....OOO#O...O##O..#.##.O..O..O#O..........O.#..#....O#.....
+O.....#OO#...OO#O..O......#O.O..........O####.#.....#..#.....#...#..O#...#...#O#...#..O..#.O#......O
+....O###.OOO...O.O...O#...O##....OO..O..O#..O.#.OO.O#.#...#O.#......##.O.......O...#.O.O.#.......O.#
+O..O.....##....#OO#.OO....##.O#.O..#.#.......O......#....#O#.O.......OO..O.#..#.O..#..........OO..OO
+.......O.O......O.....#O..#.....#....#O#...#...O..#...O#....#O.O.....O...#OO...#......#...##...OOO..
+#..O.....#O.O..O.O...#.O...O.O.#.#OO.....OOO....O.........OO..O.OO#...O#..O...#.#..#.##.#..OO...#...
+...O..OO.#O...OOOOOO..O#....#.OO...O#...O.....#.#.O.....O..O.O#O.#.#.O..#....O..#.#...OO#.......#O..
+..............O.OO#.........##..............O..#........##....O...#.#.##O#.O....O#.OO....O.#O.OO.O.O
+....O....#..O..O....O##...OO...O....O#..#O#.....OO...#.OOO#....#.O..O..O...#.....#..OO#.#O....O.O#..
+#O#...O..O#.OO..OO....#.......O#.........##.....OOO......O..#....O.#.#.O.O..O.O..O...#.#..O.#......O
+O....O...#..##...OO.....#.#.#.........OO..#..#...O...O..#..#.OOOO....#O..O##.O.O#....#....O.##.O..O.
+....O..#.OO.##...O.OOO.O.O#.....#..O..O....#.#O...#O#O.....O..##...##.O.#O...#.....OO.#..#O#.O.#.O..
+O..O#.....O..OO........OO...##....O#OO#.O..OO.....O.....O...O.##..#..#O..O.#.OO....#.........O...#.O
+#...O.O..O..O........#OOOO......#..O...#..O.....OO#.....O.......O#...O..O.....##O.....OOO#...#..##O.
+#.##...##O.#....#.OO#.OO.#..OO#...#...O..O.O#..##..O.....O.OO.#OO#....#.#.O.#...OO..#.##O...#.....#O
+..#.O.....O##.....O.O#O.#O#..#...O...O#.......#O..OO.O..O..O.##O...O...........#..#....O............
+..O.#O....O...#O....#....O...OO.OO...#O.O..O.....O.........##.....#..#O.O.OO..O..#....#.............
+..#...O.OO.......#....OO.O...#.O...#O.O#......O..#..............#O......#.O#..#...O.......#......O..
+..O..O....O.....O#O....OO.....O.O##O...O....#..OO...O.OO....O.O...O.O.......#..#O.O..O.........#.#..
+...O..O#.......#..#...OOOO...O.###..#O.OO..O#.O.O.OOO.#.O..O.#......#OO....O....#..#O..O......O....O
+....##OO###.......OO.##O.....##.#.OOOO.#OO#...#.#.O..#.....O.#.##O..#OOO.#OO.OO#OO.......O.#...#O...
+....O.O.OO.O.#O...#.O.O.....OO#.OO....O.......O.O.O...##OO....O....#.#..#O###...OO..O...#.#.O.O.O.#.
+....O....O....#...O..O#.OO..O.OOO...#.......###O#....##O.O#..O...O.#.O.O.......O.###..O#.#.O.O.....#
+..#..O...O..O.......O..#.#O.O..O...O.........#.O......#....O..O..O#.O..O..#.O.......#...#...O#.OO..#
+O....OO#O..#....O.#OOO..O.....O...O.O....O.O#O..#........OOO..#O..O.O.....O#O...#.#.....#.O.O......#
+##OO.O#..#O#.....O.........O..O.#.......OO.....O...#........###.OO...O..#..OO.O#.O#O....#..##....O.O
+.#OOO........O#...O.#..O.O.O..#.....#..OOO...#.....O........#.........O.O.....#.#.O.O#O.#.#...#...#.
+.O.....#.#....O.O...#O..O###...O..#...#O#.O.O...........#.O....#O.OO......O....O..OO....#....#..##O#
+....#..O#...#....#.O..O.#......OOO.........O....#....O...O#......#.#...OO..O..#.#O.#......#.O.#.#...
+O.O.......O.O#OOO#.O......O#.O......OO.O..O.......##O....O...#.O...O..#....###.####...OO...OO..O..OO
+#..#.....O.....O..O.#....#O....O.OO..#...O.O.....O.O..#O...O#....O##...O.....#OO#..OO#..#.O..O.###..
+O##..#...O..#...........OO...#..#....#...#.O.....OOO...O.OO...O.#.#..O...OO.....OO#O...#O...#..#...O
+....O....#.....O.#.#.OO..#.........#..........O#..O#O.#....###..O.....#.......O..#.#.....OOOO.......
+O.O.O.#........#.#.O.#..##O.OO..O...#O#OO.....O...O.#.#.O#O......#O.....O...O..O##.##.#......O..#...
+....O.......O..#.OO###..#.O#....#O.OO#..OO...#.#...###...#OO#..#...........#OO#..O.#..#....O#....O.O
+....#O..#...#O..O..O...#....O....#....OOO.OO.O..#...OO.O#.....OO.O..#..#...O.#.#.O..#.#O.O#O.O......
+.OO....#.OO.............#..###.#...O...#O...OO#...OO#O..#...##.#..........O..#...#.....O.....O...O..
+#.O....#O....O#..#O......#####O....O..O....O#.......#..O.#..#....O...##..#.........O..O.....#.O#.O..
+...O.O.....#....O.#O....#....O..........###....O.#.O.O#O.#.#.O..#.O.O...#.###...OOO...##..O.#.O..O#.
+.##...#..O..O.#....O..OO..O.....#..O.##O#O.........OO#...#.......O#....O............#O.##.OO#..O.#..
+.O.........O.#O.......#O..O....#.##.O.O...##....#.##...#O#.#.....O#O.#...#..O.#.O...O..##..O.#.O.O..
+...O.#.O.O#.OO..OO#.O...O.O.O...O.O.###O.O..O.O.O........#.O....#....O.#.#OO.....OO.#.....##..#OO...
+....OO##...#O.#..#.....#.#..##O.O##..O...OO#O...........O..O.#.OO..O...OO.##.O.#..#.##OO...#..O.....
+...#....O....#..#.O....O..#....O...#....#O...O.O..#O#O..O.......#..O......#OO..OO.OO......#.##O...O.
+...O......O.....OO#.O.#..O..O..O.O.....O...........O....#.###...O.#......O....O.##..#....O...#.#.#..
+..O.O.#.O......OO..##.O......O#..#O.....##O.O#....#.#....O.....OO.#.....O.O#.#..O...O.#....O#...O..#
+O...OO#O.......#..#O#........#.#.##.O........#O...#..#O..#.....#....O#O.#......##O....O.OO.O........
+.#..O.....OO..O.#..O.O........O.......#.#.#.....O.OO.....#......O.......O##.O...#....#O....O........
+.O.OO....O.O.##..........O.....O.##.#.......OO....O.O....#........##O..O.O##.O......#.#.#.....OO.O#.
+O.....OOO.O###...OO.##.............#..O.#.....#O.....O..OO..O#....##....OO.....#.O.#OO......OO...O##
+O........###.##..O......O#.....O.O#O......#....O#..O........O..O.#.......OO......O..##..OOO.O..O.O#.
+OO.#O......OO...O..O..#..##O..#...O......#..............O..............O..#......#.#O....O...#...O..
+.O..O#.O#..O.#..O..OO#..#.##O.....O.O.#......##O#..O....O......#.#.O..#.....O#.O..O.#.##.......#....
+....OO.#....O..O...OO..#O..#...###..OO.......O##.##.#OO..OOO...#.O..O......O........##..#...OO...#..
+....#O........#.O......O##...##O......#.O..O.O........##...#.O.......O..#OOOOO..#......O###..O..O.O.
+#.#..O.#.........O#...#O.##..O.....#..O...........##......O..#...O......#.................OO...#O.#.
+..O..#OO...OOO...O.#...#.......#OOOO#...#...O....O..#........OO....O..O..##.OO.O#....OO#O#..#....O..
+.O.O..........OOOO.#.#......O##...............#.O.OO.###.#....O..O.O#O...OO..O#O........#.O.....O#.O
+...#......#.#.....#........#O#.........#O....#O.O..#.###.....O#OOO#O#.#.O..#.#OOO..O.#....#O......#.
+O..O...#O.O.....O..O.#.#......O.#O#...#.....#..OO#.....OO.O#.O.....#....O.#...O...O.OO.....O....O#..
diff --git a/day14/uppga.c b/day14/uppga.c
@@ -0,0 +1,35 @@
+#include "common.h"
+
+static inline void move_north(char **grid, size_t nr, size_t nc, size_t r,
+ size_t c) {
+ if (grid[r][c] != 'O')
+ return;
+ if (r == 0)
+ return;
+
+ if (grid[r - 1][c] == '.') {
+ grid[r - 1][c] = 'O';
+ grid[r][c] = '.';
+ move_north(grid, nr, nc, r - 1, c);
+ }
+}
+
+static inline void tilt_north(char **grid, size_t nr, size_t nc) {
+ size_t i, j;
+ for (i = 0; i < nr; i++) {
+ for (j = 0; j < nc; j++) {
+ move_north(grid, nr, nc, i, j);
+ }
+ }
+}
+
+int main(int argc, char **argv) {
+ char **lines;
+ size_t nlines = readlines(&lines, "input");
+ size_t nc = strlen(lines[0]) - 1;
+
+ tilt_north(lines, nlines, nc);
+ uint64_t l = load(lines, nlines, nc);
+
+ printf("%llu\n", l);
+}
diff --git a/day14/uppgb.c b/day14/uppgb.c
@@ -0,0 +1,187 @@
+#include "common.h"
+
+#define MAXNUM 1000
+#define NITS (1000000000L)
+
+static inline void move_south(char **grid, size_t nr, size_t nc, size_t r,
+ size_t c) {
+ if (grid[r][c] != 'O')
+ return;
+ if (r == nr - 1)
+ return;
+
+ if (grid[r + 1][c] == '.') {
+ grid[r + 1][c] = 'O';
+ grid[r][c] = '.';
+ move_south(grid, nr, nc, r + 1, c);
+ }
+}
+
+static inline void tilt_south(char **grid, size_t nr, size_t nc) {
+ int i, j;
+ for (i = (int)(nr - 1); i >= 0; i--) {
+ for (j = 0; j < (int)nc; j++) {
+ move_south(grid, nr, nc, i, j);
+ }
+ }
+}
+
+static inline void move_east(char **grid, size_t nr, size_t nc, size_t r,
+ size_t c) {
+ if (grid[r][c] != 'O')
+ return;
+ if (c == nc - 1)
+ return;
+
+ if (grid[r][c + 1] == '.') {
+ grid[r][c + 1] = 'O';
+ grid[r][c] = '.';
+ move_east(grid, nr, nc, r, c + 1);
+ }
+}
+
+static inline void tilt_east(char **grid, size_t nr, size_t nc) {
+ int i, j;
+ for (j = (int)(nc - 1); j >= 0; j--) {
+ for (i = 0; i < (int)nr; i++) {
+ move_east(grid, nr, nc, i, j);
+ }
+ }
+}
+
+static inline void move_west(char **grid, size_t nr, size_t nc, size_t r,
+ size_t c) {
+ if (grid[r][c] != 'O')
+ return;
+ if (c == 0)
+ return;
+
+ if (grid[r][c - 1] == '.') {
+ grid[r][c - 1] = 'O';
+ grid[r][c] = '.';
+ move_west(grid, nr, nc, r, c - 1);
+ }
+}
+
+static inline void tilt_west(char **grid, size_t nr, size_t nc) {
+ int i, j;
+ for (j = 0; j < (int)nc; j++) {
+ for (i = 0; i < (int)nr; i++) {
+ move_west(grid, nr, nc, i, j);
+ }
+ }
+}
+
+static inline void move_north(char **grid, size_t nr, size_t nc, size_t r,
+ size_t c) {
+ if (grid[r][c] != 'O')
+ return;
+ if (r == 0)
+ return;
+
+ if (grid[r - 1][c] == '.') {
+ grid[r - 1][c] = 'O';
+ grid[r][c] = '.';
+ move_north(grid, nr, nc, r - 1, c);
+ }
+}
+
+static inline void tilt_north(char **grid, size_t nr, size_t nc) {
+ size_t i, j;
+ for (i = 0; i < nr; i++) {
+ for (j = 0; j < nc; j++) {
+ move_north(grid, nr, nc, i, j);
+ }
+ }
+}
+
+static inline void tilt_cycle(char **grid, size_t nr, size_t nc) {
+ tilt_north(grid, nr, nc);
+ tilt_west(grid, nr, nc);
+ tilt_south(grid, nr, nc);
+ tilt_east(grid, nr, nc);
+}
+
+static inline void write_pos(uint8_t *p, char **grid, size_t nr, size_t nc) {
+ size_t i, j;
+ uint8_t *pp = p;
+
+ for (i = 0; i < nr; i++) {
+ for (j = 0; j < nc; j++) {
+ if (grid[i][j] == 'O') {
+ *pp = 1;
+ pp++;
+ } else if (grid[i][j] == '.') {
+ *pp = 0;
+ pp++;
+ }
+ }
+ }
+}
+
+static inline size_t add_pos(uint8_t **ps, size_t nps, char **grid, size_t nr,
+ size_t nc, size_t npp) {
+ size_t i;
+
+ uint8_t n[npp];
+ write_pos(n, grid, nr, nc);
+
+ for (i = 0; i < nps; i++) {
+ if (memcmp(ps[i], n, npp) == 0)
+ return i;
+ }
+
+ memcpy(ps[nps], n, npp);
+
+ return nps;
+}
+
+int main(int argc, char **argv) {
+ char **lines;
+ size_t i, j, nlines, nc, nbum;
+ uint64_t l;
+ nlines = readlines(&lines, "input");
+
+ nc = strlen(lines[0]) - 1;
+
+ nbum = 0;
+ for (i = 0; i < nlines; i++) {
+ for (j = 0; j < nc; j++) {
+ if (lines[i][j] == 'O' || lines[i][j] == '.') {
+ nbum++;
+ }
+ }
+ }
+ uint8_t **ps = malloc(MAXNUM * sizeof(*ps));
+ for (i = 0; i < MAXNUM; i++) {
+ ps[i] = malloc(nbum * sizeof(*ps[i]));
+ }
+
+ size_t nps = 0;
+ size_t tmp;
+ for (i = 0; i < MAXNUM; i++) {
+ tmp = add_pos(ps, nps, lines, nlines, nc, nbum);
+ if (tmp != nps) {
+ break;
+ } else {
+ nps++;
+ }
+ tilt_cycle(lines, nlines, nc);
+ }
+ assert(i < MAXNUM);
+ size_t remaining_steps = NITS - tmp;
+ size_t cycle = nps - tmp;
+ size_t rr = remaining_steps % cycle;
+
+ for (i = 0; i < rr; i++) {
+ tilt_cycle(lines, nlines, nc);
+ }
+
+ for (i = 0; i < MAXNUM; i++) {
+ free(ps[i]);
+ }
+ free(ps);
+
+ l = load(lines, nlines, nc);
+ printf("%llu\n", l);
+}
diff --git a/day15/Makefile b/day15/Makefile
@@ -0,0 +1,30 @@
+CC=clang
+CFLAGS+=-std=c99 -pedantic -Wall -Werror -Wstrict-prototypes
+CFLAGS+=-Wmissing-prototypes -Wmissing-declarations -Wshadow
+CFLAGS+=-Wpointer-arith -Wcast-qual -Wsign-compare
+CFLAGS+=-O2 -g
+CFLAGS+=-fstack-protector-all -Wtype-limits -fno-common
+CFLAGS+=-fno-builtin
+CFLAGS+=-I/usr/local/include
+CFLAGS+=-I../utils
+#LDFLAGS=
+
+UTILS=../utils/reading.o ../utils/stack_str.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) $(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)
+
+utils:
+ make -C ../utils
+
+clean:
+ rm -rf common.o uppga uppgb
diff --git a/day15/common.c b/day15/common.c
@@ -0,0 +1,3 @@
+#include "common.h"
+
+size_t fn(char **lines, size_t nlines) { return 0; }
diff --git a/day15/common.h b/day15/common.h
@@ -0,0 +1,15 @@
+#ifndef COMMON_H_
+#define COMMON_H_
+
+#include <assert.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/queue.h>
+
+#include <reading.h>
+#include <stack_str.h>
+
+size_t fn(char **lines, size_t nlines);
+
+#endif
diff --git a/day15/exinput b/day15/exinput
@@ -0,0 +1 @@
+rn=1,cm-,qp=3,cm=2,qp-,pc=4,ot=9,ab=5,pc-,pc=6,ot=7
diff --git a/day15/input b/day15/input
@@ -0,0 +1 @@
+jn=7,dmbj=9,jv-,bsk-,rhlzp=1,lvj=7,lxn=4,lp-,ssfn-,hjcbzv-,cpdmvs-,nkcd-,ppr=4,czj-,kcp-,hdzp-,rprrh-,cpt=4,tglkr=2,lfxnd-,frl=1,jvp=1,xzmsg=2,svfq=9,xxqk=9,bdf-,rc=3,mtkx=2,hn-,qnkn=4,nsxl=2,nkcd=4,mbtmlh-,lhmph=7,nfgj-,tcp=1,mjh=9,nbhhl=1,zrm=3,hfhgc-,nntzz=2,ksr=2,tf=1,pq-,dkbdvq=4,sjdq-,bcvm=3,vtq=9,fx-,kcxt-,jn-,hv=1,jrhtx=4,lzd=1,znnhs-,cjp=9,hj-,dqn-,zz=7,frl-,xxp-,vkzss=2,jzh=2,hjcbzv-,vvx=6,kfk-,rvsp=8,vjs-,nkcd=4,jlx-,fntz-,mk=3,hpm=2,zqbhl-,nmstn-,rfdx-,xtq-,rf=5,mbbtz-,dnt=7,vkzss-,kgl-,lj-,zjjs-,bdh-,pn-,zzdl-,vfts=7,ckx-,nsxl-,zjjs-,lvj-,kphn-,js-,cmg-,jpc=4,hhkkdc-,zbj-,xb-,cx-,bbt=3,xxp=4,mjh-,qgsx=7,rq-,vczz=1,lrm=1,nv=2,qpff=5,js-,jvvndd=9,dg=1,zs=2,psh=8,dp=5,dt-,lft-,qdd=2,cpt=2,nkhq=1,rns=7,zrm=4,hfq=5,ghj-,nt=6,ssfn=3,vdgk-,tr=5,tq=6,hfhgc-,frtvrl-,tr=4,jcx-,vkzss-,hsl-,gl-,dtm-,hz=6,bdk-,qqhht-,gvbnl=3,lplzh=8,cp-,vdgk-,htf-,dnhj=6,bpk-,nt=9,vc-,tqjk=9,tqjk=9,hhch=2,drz-,qnr-,htf=3,rns=4,vvx=7,mk-,rd-,qdd-,dgv=2,grs=2,mk=4,lhm-,qq-,br=2,vdgk-,dtr=9,htf=2,bgsm-,kk-,hbm-,ztzh=3,ftct-,qlj-,rdtv=8,xhrp=3,ftct-,bfs-,vc=9,tdvd-,btjs=7,sx-,tlr-,xtvtz=1,kt=9,vfts=5,qjb-,sb-,tdvd-,pp=1,fs=4,jr-,nk-,qx=5,xtq=4,brb-,mc=2,xqltnl-,jmjjv-,lks=8,cvd-,khkgrl-,rhssrf-,cbz=3,js=4,nsxl=2,lzsdjk=5,tqjk-,jhk-,gl=7,tccm=4,slhc-,cbz=2,crz=3,vfts=2,grs=6,xq=7,nbhhl=5,vrls=3,bdf=7,ljd=9,dtm-,hrr=9,mbtmlh=2,xxp=3,tglkr-,htf-,kphn-,qjj-,btq-,xtcnp-,xh=2,hprv=2,nzd-,bcvm-,nt=6,xtg-,hj-,bgsm=8,ll=2,xx-,zgs-,zsk=6,rrcd=2,qrdm-,bz-,zs=5,tcp-,tfb=5,ksr-,vkzss-,pjv-,bdh-,vd=1,qv=6,jv-,kzs=8,tl-,mxbq-,pn-,xxp-,rgt-,nmstn-,nzd=9,bbt=1,xtvtz=5,lplzh=5,ss=2,mbbtz=8,qlfq-,qq=3,vqr=7,dtr=7,zc=1,bk-,js-,hdzp=9,qt=4,qrdm-,qtd=7,jv=5,nhg=8,hz=5,grs-,mrg=4,bdf-,nf=8,vbhss-,lbnpn-,qpff=6,ntpb-,tccm=7,jv=8,zn=1,qlj-,kvxklg=4,sx=8,xj-,ftct-,ctd-,mcv=7,mb-,vbhss=2,xs-,csk=5,kk=2,jh=4,fj-,qc-,cdq=3,bzvmmv=8,qdd=6,lplzh-,cj-,mcv=1,zjjs-,nf-,cc-,sjdq=8,gkl-,pd=4,hqd=7,pr-,hfh=6,ctd=4,mmvth=5,pn=8,mbtmlh=8,sqr-,tnd=8,rqnbp=8,ksr=4,jvp=3,hfhgc-,vr=8,ssx=4,nr-,vk-,pp-,dlf=7,hhch-,bm=5,dcnj=9,zpk-,jpc=5,ghj-,bll=1,mb-,rns-,vjs=1,fqs=6,gghpgg=9,mp-,pn-,xk=1,nm=1,dpc=3,bp-,hth-,nmstn-,cdf-,njp-,kcp=1,xtvtz-,rl-,lj=9,kqbn-,tdfsgx-,ljd-,kgl=4,hth-,qrdm-,bdf=7,mjsj-,gkl-,dt=9,dpj-,pskpgz=4,xqltnl-,pjv=5,ltd=7,vmgtz-,ssv-,chg-,kcxt-,fh-,lrm-,cmg-,xk=3,dtm-,grs-,ss=3,tnd-,hhkkdc-,xnxv=1,jhk=9,lmj-,dx-,gghpgg=2,rvsp=1,qdd=5,bk-,nt=9,ssfn-,lplzh-,nr-,kvxklg=4,qqhht-,tqjk=7,lrzk=5,ssv-,qrdm=8,dzg-,zx-,jlx=4,lrm-,hdzp-,gltc=8,lmj-,gghpgg=7,mmvth=3,zf-,lqcqp-,xxl=4,cxmnl-,rtjqkd-,sdh-,gkl-,px-,cdb-,ljd-,gfczl=6,fg-,xk-,hhtcjf-,xh-,rd-,rtjqkd=2,gs=5,lqcqp=9,tlt-,rz-,gcjd-,nq=8,cdq-,bd-,frld-,dcnj-,gghpgg=1,zs=7,nt=9,kt=2,ctd=3,llhl-,nkcd-,jh-,nnr=3,lxn=5,rprrh=1,hvvd=5,rc=1,cpt-,bgsm-,qnr=5,dqn=3,pcxg=3,jzh-,qkgkf=2,prtv=6,zrm-,cg-,vvx-,hj=4,lsm-,kzs=8,djjj-,jzh=7,vcg-,hjcbzv-,cng=4,nfht=3,xtq-,zbj-,bt=8,pmjd=1,lxn-,zgs=1,jk-,xp=7,kbs=6,qqhht=5,lsm-,bp=5,bfs=4,xpz-,fx=7,kdh-,zlq-,qqhht-,bznnxv=8,ptd-,bz-,nkcd-,lfxnd-,ph-,jpc-,nt=1,pjrj=6,bdh-,rns-,vrn-,xzh=1,btq=6,nkhq=7,fqs=6,dzg=4,mnn=2,nfx-,fmc-,hv-,ljc=9,gl-,fj-,dqn-,mbbtz=7,xf=9,htnv=1,cpdmvs=9,bll-,xzh-,cj=2,cg=6,fjq=3,pjv=1,hjdc=6,fhhl-,grs-,ksr=2,pmjd-,mc-,qnkn=9,dx-,mbbtz-,vn-,pr-,bv=3,xxl-,mdf=3,ss=6,jvvndd=5,qc=7,kc-,xtq-,kdh=7,qr-,fsk-,hjns-,lzd-,qkl=1,xx=3,sqr-,cjp-,jvb=7,vlm=2,smcc=5,nkzqqf-,tpph-,hjdc=3,hqd=6,hjkn-,mf=8,ntpb=6,mx-,dn-,crz-,zc=3,jk=9,chg-,jzh=6,svf-,djjj=8,sc=9,zh-,nfht=3,ktm=2,qgsx=2,mjj-,ss-,hjdc=4,lrzk=2,ztzh=9,qnl=1,dx=2,hbm=3,db-,rhlzp=6,njp=9,brb-,xh=6,grs-,jh-,rc-,kf-,jh=7,zzdl-,bfs=6,nfx=7,tvz=4,br=2,bv=6,fh-,xk=4,kqbn=5,jcx=2,zp-,vdgk-,mbh-,sn=5,cmg-,hfh=7,mshn=5,xmkxf-,xh-,bnkf-,fsk=1,mrg=3,zzs=4,jjfz=5,cng=4,fcj-,jdfgx=7,jvb-,nfht-,mgq-,lfxnd-,xzmsg=1,jjfz-,csk-,mbh=1,kfk=4,pn=7,xp-,tqjk-,vzn=7,hp=4,dtm-,dtm=1,nnr=3,dzg=9,kb-,xpz=9,mq-,sn-,hj=6,bs=5,vfts-,lsm-,jh=3,hhkkdc-,xxl-,zmq-,vsh=3,qs=9,qrdm=3,gvbnl=7,qdd=7,sdh-,gfczl-,vzn-,ntpb=5,slhc-,rl-,shjl-,bs-,qpn=8,hdzp-,czj-,nsxl=1,hp-,vcvct=9,bs=3,xxl-,bp-,fmc=2,ktjrb=1,vm-,xx=8,hjkn=4,cng-,frtvrl=8,nhg-,mshn=7,px=7,rprrh=2,jhk=2,tc=6,xj=9,rr=1,btt-,xq=9,dg-,nzd=8,sssgg-,qnl=4,pskpgz=3,gnbl=5,zms-,sqr-,bsk-,fj=4,dg-,rl-,nnr=4,gnbl=3,tlt=5,cjp=7,qhb=2,grs=1,qkgkf-,vbt=8,lrzr-,dgv-,xtg-,fv-,pmjd-,pjv=8,btjs-,dlf=2,mbtmlh=2,vrls=5,mx=2,drlxt=4,zlbg=8,kgl-,hrr-,cxj-,jq-,zxm-,qx=4,bp=2,kzvg=4,bgsm-,vc=4,kcxt=1,cfm-,nmstn-,fsk=7,zp-,bj=9,bdf-,fsk=5,jjfz=9,gr=7,mx=2,tlns-,qs=2,gnbl-,zpk-,jjfz-,qgsx-,mlq=6,nkzqqf-,jp-,cxj=8,dqn=4,htf-,tnn=6,db=1,db=7,ssv-,ml-,bgsm=1,xt-,gnbl-,kf-,mbtmlh-,kxj-,htf=2,dp=4,fx-,tqjk-,prtv-,tglkr-,nz-,lgt=7,shdrs=2,frld=2,vcqq=4,sqr-,pq-,jhkq-,qs=9,nsxl=6,sn-,jh-,vjs=2,dpj=9,sc=2,rl=4,sssb=3,kc=1,lplzh-,gkl=7,sv=1,xgq=8,rfj-,nkhq-,mshn=6,kgl-,lhmph-,xpz-,hs=1,btt-,bsx=3,tr=1,gjj=3,mjsj=4,fhhl=4,mkl=8,ssbh-,cvd=4,hfq=2,zrm-,lzsdjk-,xtg=3,dtm-,nhg=9,bpk=1,bm-,qnr-,ppr=8,nkcd=7,qv=3,mnn=7,nkcd-,llhl=4,cx=2,br-,nh=4,czj-,rdfhng=4,mc=9,gl-,tvz-,gr=5,ljd-,xh-,ghj=7,qrtx=7,vb=3,jcx=9,nnr=1,hdzp-,bpk=5,kbs=6,slhc-,mc-,kcp-,qjb-,qjj-,qdkzn-,nk=7,bd=5,ck=5,ssx-,rc-,ssx-,vczz-,fhhl=2,xpz-,tlns-,lplzh-,jvz-,ntpb-,chg=6,gvbnl=1,btt-,jfl-,lrzk=4,gbrjv-,ssbh=2,ggnc-,pq=2,pjv-,xnxv-,pd=3,kcxt-,qx-,dnt-,vczz-,dhn-,jhkq-,spf-,rns=2,vbz=6,bp-,dk=2,xtx=8,xtq-,pqqmv-,ll=2,hhtcjf-,hpm-,njp-,mjh-,fj-,rvsp-,vlm-,hjkn-,qnkn=5,kvxklg-,gltc=9,sb=4,tl=6,nzd=7,tccm=8,qnkn=8,mtkx-,xh-,dcc=9,bcvm=7,lj-,pm=6,mjh=5,nhg=7,dk=1,qr-,pq=5,fhhl-,vk-,qrdm-,xtx-,gltc=9,lfc-,zpk-,zrm-,ksgkmj=5,vcvct-,qpff=1,jq=5,hhl-,qlfq=9,rf=9,dnt=1,tr=2,tdfsgx=2,fs-,qnl=4,khkgrl-,bzvmmv-,vrls=9,nhs=9,slhc=3,sb=8,fsk=3,mrg-,hvvd-,jhk=7,nmk=2,qt-,dg-,xpz-,cdb=8,mcv=8,xq=2,nntzz-,vn-,nnr-,dkbdvq=2,fhhl-,lqcqp=7,mcv-,nhg=4,ktm-,dtm-,jvb-,pftj-,llhl=4,fzn-,xqltnl=7,djjj-,lsm=1,hfh=9,sssgg=5,rdtv=9,xs-,lplzh=1,hjdc-,ksr=2,sssgg=3,ppr=1,mrg-,qz=3,hz=3,qqhht=5,lvj=7,xxqk=6,zxm=1,vvx-,vb=5,nnr-,fdf=6,mmvth=2,kqbn-,qpff=9,vfts=6,qpn-,cp-,mjh-,qpn=4,brb-,ckx-,tr-,zlq-,fmc-,nkhq=6,sx=7,gt-,hqd=3,tqjk-,ghj-,jhk-,nzd-,ptd=3,gnbl-,mbh-,dlf=8,qdkzn-,hjns-,tdvd-,kxj=2,ckx-,smcc=6,zbj-,bk=1,ppr-,zsk=6,jmjjv=6,zzb=7,hjdc-,nntzz=4,ktm=5,tlt=9,vc=6,ddzv=5,fx=5,rdtv=1,hs=4,pp=6,nf-,qlj=6,qjb-,rqnbp-,vtq=9,kt-,zc-,frld-,pd=7,rhlzp=6,dhn=5,nz=4,hjns-,qqhht=4,lsv-,tjb=3,jhk-,nhs-,slhc-,tnn=1,nkcd=1,xx-,zmmtp-,zzs=4,jr=5,vv=8,pp-,bdf=7,mk=7,cmg-,dnt-,mnsjll-,xjsv=6,ck-,kqbn=7,htf-,vlm=2,mq=2,jlx=2,kg-,hhl-,tl-,lmj-,qv-,fj=4,zzs-,mk=8,rcvrk-,rvsp=5,tlr-,mcv-,ssfn-,bv-,zzb-,hqd=8,nf=9,xqltnl-,hjcbzv=8,hprv=6,nmq=4,mp-,qpff=7,xj-,ppr=1,mjsj-,chp=3,ghj-,dg-,fj=1,xx-,mk=3,qlfq=9,cfm=8,rr=9,grs=4,cg-,cx=9,zgs=2,dn-,xxl-,tfb=1,cjp-,cnt-,bll=4,fspg-,lj=4,hpm-,lzsdjk-,bs=2,zsk=8,dk=6,dkbdvq=8,lmj=3,dzg=8,hdzp-,qgf=6,xt-,dtm-,fq=6,rrcd=2,qnl=2,jdfgx-,cmg-,zsqqz-,llhl=9,drlxt-,dn=3,qgf-,mgq=4,nmk=5,lk=9,mlq=1,mjsj-,cnt=5,kcp-,kssgnb-,grs-,xtx-,nkcd=7,lk=6,xzh-,czclc-,gr-,smcc=6,vcqq-,nr=3,mnsjll=7,rd-,djjj=7,pqqmv-,hjkn-,gcjd-,gr=7,fhhl-,nmq-,cpt-,chp-,hrr-,ggnc=6,hfq=7,lft-,sv-,ppr=9,jlx-,zp=7,pk-,jvvndd=9,jq=5,qnl-,vqr-,drz=7,cp-,tlr=7,stc-,ktm-,svfq-,kbs-,lxq-,cng=6,btq-,cdf=2,rvsp-,fdf-,xjsv-,bzvmmv=8,zq-,vjs=9,dmbj-,lhmph-,vdgk-,nk-,gp-,vd=9,lhm=5,sdh=2,gflrf=3,ptd-,hvvd=2,stc-,hjns-,nf-,csk=4,dlf=2,qlfq-,mq=2,dmbj-,cdb-,pm=4,htf=3,fdf-,mkl-,fntz=9,ksr=1,mdf-,ml=2,xhrp=3,mgq-,tlt=2,rtjqkd-,nt=3,tc-,gbrjv=6,czclc=8,frtvrl-,cpdmvs=1,xzh-,jzh-,ktm-,cxmnl-,cjp-,cbz=7,mnsjll-,dtr-,pjv-,dcnj-,rfdx=2,fcj-,lrszx-,cnt=7,vr=4,bnkf-,fk-,gfczl=4,fntz-,dnhj=9,fhhl=6,bsk-,mjj-,ktm=4,tglkr-,jpc=7,sttmb-,rq=7,cmg=8,lxn=1,kvxklg=9,fjq=8,chp=5,vbhss-,cfm-,ksgkmj-,hdzp-,dg=1,grs-,lp=1,qb=1,bsx-,smcc-,fzn-,xx=3,nt-,mnn=4,nsxl=7,svf=4,dcc=1,gs-,vzx=5,fzn-,vcg-,nkhq-,gt-,cj=5,pp=2,gzl=5,gnbl-,sjdq-,qgf-,stc=4,pskpgz=9,mrl-,zn=6,rfdx-,jzh-,rncb=2,pskpgz-,njp-,tlns=3,sqr=8,kcp=7,xmkxf=4,sv=4,ll-,mrg=2,lrzk-,kfk=5,qnr=6,hz-,ntpb-,vjs=4,hhl-,nmk-,cfm-,fcj=3,hhch-,xzh-,chg=3,tdvd-,vzx=6,sb-,hhkkdc-,pt-,zdqbdm-,pskpgz-,llhl-,tf-,khkgrl=2,hqd-,vbt=1,gbrjv-,kzs=7,pn-,vn-,xxqk-,qt-,tjb=2,frld=2,zsqqz=2,vd-,ssv=6,psh=7,zn=2,drlxt=5,zn=4,dcc=9,nv-,fcj=9,bt-,pjrj=5,hjkn=4,smcc=7,kdh=1,qq-,pjv-,lsm-,hj=8,zmr-,kr-,gjj-,qdkzn-,qlj=2,sssgg=3,ltd=1,fsk=9,vjs-,qgsx=7,kzs=8,kk-,tlr=6,mshn-,hgs=1,vcqq-,gt=7,jpc=3,chg=1,nfx=7,tlt=9,dhn-,tglkr-,kqbn-,dkbdvq-,zgs-,xxqk-,vmgtz-,pjv=7,rfj-,lp=9,hjkn=8,qr=1,ljd=8,htnv=8,rrcd-,zpk-,zf=8,frld=4,hhtcjf-,lrszx=7,csk-,xxl-,cnzs=7,lrszx=8,lj-,xpz-,shjl-,tcp-,dk-,nsxl-,fcj-,gp=6,bnkf=9,kb=9,vlm=9,czj=1,fv-,xjsv-,dx-,mdf-,qjj-,sttmb=2,mbtmlh=3,pk-,qrdm=4,mk-,zn=8,sttmb=8,dp=2,ckx=6,gr=3,dn=2,bsk=3,ll-,nr-,tl=8,rkk=8,dtr-,xxl-,zbj-,rprrh-,ltd=3,zzb-,xtcnp=8,br=2,rq=1,fqs=8,znnhs=1,zjjs=4,dhz=4,xzh=3,qb=1,sb=7,lgt=7,vlm-,mq=8,cpt=4,fd-,bm=7,hhch=1,xhrh=4,lqcqp-,hprfn=9,htf-,mtkx=1,qc=8,rz=1,gjj=3,mrg-,nk-,jvz-,gfczl=5,jvp-,kt-,pt-,vn=4,kb=9,cdq=2,vmgtz-,tcp-,tjb-,qc=4,nr=3,tlns=4,lsv=1,smcc-,mtkx=8,kbs=1,ldjf-,xhrp=7,dzg=7,svf=8,fh=4,bcvm-,zlbg-,qqhht-,jvp=7,nm-,kqbn=7,zp-,smcc-,jpc=7,xnxv-,sttmb=9,xjsv-,xzh-,czh=7,qc-,bs=9,hfhgc-,hjcbzv-,bdh-,kqbn-,nntzz-,zp=6,fntz-,tc=8,vm-,nq-,hjdc=1,dgv=3,dk=6,gjj=4,czh=1,mmvth=9,vtq=3,gfczl-,cx-,vrn-,gzl-,lsv-,xk-,vrn-,fntz-,qr-,ktm=1,hvvd=9,bbt-,rps=1,qkgkf=8,zzb=9,jfl-,drlxt=2,svfq-,zmq-,zn=3,rr=5,qrtx-,ljd=7,vvx-,czh-,cng-,vzx=8,bj-,hhl-,hsl-,lmj=7,dp=3,vmgtz-,lxq=9,mtkx=4,ljc-,ss=9,fsk=9,xb=1,zzdl-,jp-,xtcnp-,lhm=9,cx-,cpt-,frtvrl=8,ssbh=1,bm-,hrr-,cdf-,bpk-,vkzss-,kgl=8,ml=9,smcc-,jfft=1,nsxl-,mjsj=3,hrr=5,hj=3,htf-,qkzp=6,kk=4,tccm-,dn-,hj-,hhtcjf-,vrn=1,xtvtz=8,bz=1,vmgtz-,gghpgg-,frld-,tdfsgx-,mq-,jr-,nk=7,rp=5,sm=9,sssb=7,kssgnb=3,vzn=6,hjdc=1,mtkx=7,dgv-,hv=8,rfdx=6,bs=2,vkzss=1,db=5,vcqq=8,tlt-,ggnc=2,lvj-,zh-,vk-,tr-,hjdc=1,ppr=9,kbs-,pskpgz=9,jmjjv-,vfts-,sqr=4,czh-,xqltnl=6,jvz-,dnt=6,xt=6,ddzv-,jjfz-,cdb=3,js=4,gl=9,dqn=3,fsk=9,kbs=1,frl-,rl-,hfh=9,cxmnl-,vlm-,rncb=2,btq-,tl-,ljc=2,cjp=2,dzfxb=8,dtm-,lhm=7,qlfq=1,zz-,zqbhl-,xxl=3,nfx-,czclc-,ssv-,bsk-,xtg-,pftj=9,zsqqz=8,nq-,zn-,ktjrb-,lrzr=3,tdvd=9,jvvndd=4,slhc-,zdqbdm-,lrszx=1,js-,pqqmv=3,dzg-,rcvrk-,hv=3,hjkn=4,vzx-,rhssrf-,qx=9,kg-,vd=6,mshn=4,hhl-,dnhj=7,nbhhl-,ksr=7,nnr-,qgf=2,xtq=1,dzg-,xzh-,vzn=3,qj-,qnkn=8,psh-,znnhs=2,jvvndd=1,dzfxb-,tcp-,qr-,bs=5,brb=5,sdrf-,dtr-,zmmtp=2,qrtx=5,qrdm=8,lcx-,vrn-,lb-,cpdmvs-,rd-,pcxg=6,cnt-,pt=1,xjsv=1,qj-,vbt-,mp-,mjsj=7,ptd-,tlns-,xf=7,cc=9,mshn-,rdfhng=5,lfxnd=2,spf=9,lk=8,mbh-,cnzs-,crz-,rq-,rd-,lk=4,qhb=6,kzvg-,mdf-,fv=7,brb-,cj=7,dzg=9,gbrjv-,lrzk-,kc-,fx=1,drz-,vm-,tq-,ph=5,kqbn-,qx-,jrhtx-,hhl-,slhc-,bd=8,hfhgc=7,nbhhl=1,rprrh-,gp-,mb=8,xtg-,vdgk=8,drz-,rns=5,jv-,fxm-,svf=4,xs=3,hjns=5,rq-,xk-,bm=1,ppr-,rkk=8,tvz=4,dtm=7,zlq-,nkhq-,ck=8,svfq=9,kfk-,zzb=9,bz-,mp=6,jdfgx=3,kssgnb-,btjs-,ztzh-,lfxnd-,xtx=9,grs=6,hhtcjf-,mc-,frtvrl=1,jvz-,jmjjv=4,mbtmlh-,fsk=9,gs-,ktm-,vqr=2,bm-,sn-,pmhf-,zms-,qkzp=3,dkbdvq=7,xf=7,hrr=4,xqltnl-,lrm=6,xmkxf=8,bk=4,zf-,pskpgz-,lhm-,lfxnd=8,fv-,dnt-,gr-,gcjd-,vcqq-,jfl-,btt-,chg=2,fj=9,kphn=5,jzh=8,mshn=2,dnhj-,dmbj-,hjkn-,pmzl=1,lzsdjk-,tglkr-,xgq=4,bhvxs-,fx-,zsqqz=3,xtg-,hfq-,gt-,dtm-,bgsm=6,lrszx=1,nzd=9,hv=6,xk=1,jcx-,vbz=3,mq=8,dhn=1,qdkzn=9,chg=3,nr=9,ctd-,hj-,gp-,bk=8,mnsjll=8,mcv-,dpc-,hjns-,kcp-,rr=4,rprrh=6,zsqqz=2,kc=8,nntzz=6,hfhgc=6,zzb=9,tfb=4,dtr-,jfl=5,jlx=9,cvd=3,rtjqkd-,zz-,btq=7,lhmph-,hsl-,hs=2,rtjqkd-,zq-,hgs-,jvb=7,gltc=8,hpm-,dnt-,nh=7,ppr=6,czj=4,hz-,zqbhl=8,fqs=1,cng=5,mlq=6,nz=9,kcp=3,lhm-,hth=3,jcx=1,nkhq=2,jfft-,sv-,crz=6,ffr-,ddzv-,ktjrb-,nfx=3,fjq-,mnsjll=6,llhl-,jvvndd=4,vrls-,sqr-,fs=7,hprv-,dg=9,jrhtx=5,xtg=7,nf-,czh=5,qdkzn=1,rl-,bnkf=2,lft=9,htnv=4,xxp=5,xqltnl=9,zlq-,zpk=6,xgq=2,zc-,sx-,ksgkmj-,qr-,hprfn-,zqbhl=4,gghpgg-,rprrh=4,xf-,zdqbdm=2,dqn-,tlr=3,lrzk=7,cdb=2,kzvg-,lrm=3,pq-,qqhht-,nhs-,mtkx-,vzn=3,zzdl=4,hhch-,vczz-,ftct-,pmzl-,dkbdvq-,rq=8,vjs=8,fdf=3,sttmb=3,hjdc=7,cc-,qj-,qrdm=2,bznnxv=5,ckx-,rhlzp=9,brb-,slhc-,xs-,qv=9,hdzp-,bgsm-,ggnc=8,rncb=3,csk-,bdh=3,bcvm=8,xhrh=7,tdvd=2,mbbtz=5,vzx-,dx-,nfgj-,pp-,xt-,zc=9,bnkf=3,cng-,gltc-,zmmtp-,jdfgx-,mrl-,kdh-,vsh=9,psh-,fm-,hsl=6,mb-,cx=6,lks=5,mjsj=6,hn-,gnbl-,ts-,fj=6,rhssrf-,mkl-,gzl-,nm=5,xtcnp=6,lmj-,kzs-,xgq=6,kfk=6,zzdl-,jv-,hprv-,hhch=2,dhz=6,htnv-,vmgtz-,sqr=1,mp-,dgv-,js-,mkl-,dt-,pmzl-,hrr-,dtr-,xzh=5,dmbj-,kzs=1,ss=4,ll-,kvxklg-,gp=5,pk-,cpdmvs=2,vk-,mnn-,jpc=2,fjq=2,nfx-,kbs=2,rfj=3,svfq=5,tpph-,pq-,mshn-,jpc=6,cnzs-,cx=9,kgl-,rc-,lzsdjk-,br=7,cdq-,lzsdjk-,nfx-,znnhs-,js-,tl-,pd=1,xb=3,zbj=8,lks=4,hp-,lmj=8,dzfxb-,jfl-,sssb-,hgs=4,ffr=9,cfm=9,khkgrl-,tlns-,qrtx=3,ck-,pn=2,ssbh-,dtm-,pmjd-,fspg-,zmr=7,xpz=2,mbbtz-,lplzh-,vcqq-,zp-,fm=4,zs-,sx=4,nr-,cdf-,fcj=1,mjj-,fz-,ptd-,nkzqqf-,qdd-,gfczl-,qb-,rd=4,mdf=3,tccm-,gkl-,dkbdvq-,xh-,jlx=4,dk=9,ggnc-,xxp=9,nq-,bsk-,frtvrl=8,gp=9,csk=4,bdh=3,rgt-,jvz-,fxm-,mrg-,kcp-,bk-,ptd=2,khkgrl-,bz-,mp-,njfl-,bnkf-,jvz=5,ljc=1,xhrp=2,hv=5,mrg=1,cj-,vzn-,ksgkmj-,lzsdjk-,tvz=1,rncb-,lcx=6,djjj=2,ss-,cxmnl-,kr=5,jr-,dhn=3,ssfn-,jhk-,ssfn=6,dt=1,nh=3,gt-,bdk=8,qc=5,pftj=1,tf=4,hs-,hsl-,htf=6,fq=5,dpc-,xtx-,jh-,hprv=8,qs=3,lbnpn=4,lzd-,rdtv-,br-,vbhss=8,nntzz=5,hjdc=3,spf-,rhlzp-,jvz-,tpph=9,fz-,xqltnl=3,gp=3,mx=6,cnzs=5,sssgg-,mjsj=6,tdfsgx-,ssv=2,qnr-,vzn-,vk=4,lrszx=9,stc-,lgt=7,dmbj-,nm-,qx=6,spf-,spf-,llhl=8,dqn-,xb=3,lsm=8,kk=2,nq-,mlq-,vczz-,mkl=1,mnsjll=3,jdfgx=5,lb=2,ph=4,lfxnd-,rfj-,qj=9,tnd=4,fx-,ggnc=3,tnd-,nntzz-,lp=9,nh-,qc=5,hfq-,sx=7,jvb=2,qpn-,sqr=9,nmk-,ztzh-,stc-,fm=9,rl=5,ldjf=6,qj=9,zgs=7,dnhj-,zmq-,mshn=1,xtcnp=7,bsk=1,tfb=9,fxm-,br-,rvsp-,czh-,brb-,mbbtz=6,tq=7,rns-,nq-,dhz-,dx-,ckx=5,kr-,tdvd=3,jdfgx=2,jvp=8,mmvth=5,bj=4,kssgnb-,sb-,ltd-,vm=9,lfc-,mp=8,ph=9,xhrh=1,zzs-,lj=1,kssgnb=9,qb=1,lhm-,fspg-,ffr=5,jvz=2,qdkzn-,hhtcjf=6,vczz=3,zlbg-,pmzl=7,vkzss=3,xhrh-,dn-,lvj=9,pjv-,jcx-,kxj-,jhkq-,dtm-,cnt=1,pq-,bm-,pskpgz-,khkgrl=9,hp-,lp=8,nfgj=7,vfd-,kg-,td=7,vrls=2,xzh-,cmg-,xh-,bsk-,bz=6,kc=7,nkzqqf=4,hvvd=3,nh=8,qc-,qx-,tc-,qs=9,ggnc-,qdkzn=9,bznnxv-,jjfz=4,zzs=6,vkzss=4,zxm-,gnbl-,cxj-,tqjk-,fzn=3,cdb-,rkk-,vbz=5,br=1,vfts-,xk-,vbhss=3,chp-,bk=1,rhssrf-,chp=1,tr-,dg=5,vfd-,qdkzn=6,pmzl=2,kzs-,vfts=1,bhvxs-,dzfxb-,td-,qrdm-,vdgk-,cc=9,qgsx=2,zpk-,jvb-,ntpb-,hjkn=5,kzvg-,jvb=1,qjj=6,llhl-,gdjk=6,jfl-,cj-,fxm-,djjj-,rns-,zn=7,znnhs=3,ddft=5,bz=2,mbtmlh=3,jq=6,zq=9,rqnbp-,rvsp=4,xtg=3,vfts=2,xzmsg=7,ck-,bdf-,vr-,slhc=9,bll-,cng-,vn-,zdqbdm-,nhs=3,ksgkmj=4,vm-,nhg-,zzb=4,nm=6,kk=8,zzdl-,lqcqp-,rdfhng-,chp=2,jr-,nt-,hvvd-,zs=8,vtq-,bk-,nntzz-,lhmph=8,sttmb=7,xh-,cvd-,zn-,gr-,bsx-,pjrj=7,qgsx=9,kr-,vrls-,zn=9,hth=1,lhmph-,rgt-,fq-,brb-,qb=3,zlq=5,dlf=1,qkgkf-,rdtv-,xxp-,tgmr=7,jr-,kssgnb=5,td=8,lxn-,tlt=7,rhlzp-,vbt=2,fv-,jvb=5,rd=6,bzvmmv=8,ntpb-,gp=1,svf=1,hjdc=8,kdh-,zz-,vzx=8,xf=9,xjsv-,kt=9,ml=7,lrszx=6,zms=1,rc=4,mshn-,spf-,dpc-,bzvmmv=6,dtm-,tfb-,rc-,ptd-,bbt-,fqs-,vr-,lfc=7,qnr=4,jczj-,xs=1,dpj=3,znnhs-,llhl=9,nmk=3,vjs-,xxl-,svfq-,qr=6,nm-,zdqbdm-,czj-,qv=8,ksgkmj-,mrg=6,pp=5,jhkq-,xtvtz-,rgt=9,hfq=2,cmg=6,ddzv=6,nmk-,bdf=6,nsxl=5,db-,gnbl-,zx-,jvb-,nv-,bdf=8,ssfn-,qhb-,hhl-,svfq-,cvd-,vcg-,btq=1,xpz-,rc-,hprv=5,zrm=8,grs=3,rcvrk=8,tdvd=8,xgq-,gnbl=1,hprfn=4,lgt=1,mbh=9,jczj-,xq-,cng=2,qj=4,zgs-,kzvg=1,fx=3,cdq=8,lhmph-,qdkzn-,kxj-,hjcbzv-,gzl=1,ptd=5,mjsj-,tdvd=6,tcp=7,cvd=3,zsk-,qnr-,qr=5,xj=1,vfts-,qkl-,xtg=3,ss=5,xj-,kqbn=9,jr=7,bhvxs-,ztzh=9,qnl-,qlj=1,mnsjll=9,mp=1,pp=4,xpz=8,xxl=3,sv-,scv-,qhb=7,bhvxs=3,hjcbzv-,lcx-,mjj=8,lqcqp-,hj-,shdrs-,dnt-,fh=2,cfm=6,jfft=6,zqbhl-,fcj=4,rns=7,cp-,nr=9,tlt=3,qs-,kc-,xtx-,lp=5,hp=5,lcx=6,frld-,qdd-,cxj=5,kqbn-,vlm-,rl=6,vdgk=5,rtjqkd=8,xs=1,mbh=3,cg-,pmjd=8,dpj-,hhtcjf=1,gzl=8,js-,bd=3,kgl-,vv=8,brb=6,sv=9,qqhht=5,rq-,bm=5,jvz=3,tlns=1,nkhq=7,qjj=7,bznnxv-,ksr-,cnt=7,cdq-,ssx=2,cng-,mtkx=8,dkbdvq=3,bnkf=4,pk-,sssgg-,zqbhl-,pt-,rprrh=4,pmzl=2,bm=5,qnl=7,mbtmlh=4,lsm=8,pr-,pd-,xhrh=9,hhtcjf-,ctd=9,zh-,bhvxs=1,hjkn=3,vn-,cdf=8,vmgtz-,xxqk-,rq=1,qgsx-,rfj=1,qs=4,xhrh=7,scv=2,vfts-,mmvth=4,qdkzn-,zh-,xtcnp-,nsxl-,bzvmmv-,mrl=3,vb=7,qgsx-,hgs-,mnn=3,qdd=4,jn-,vzx=5,xjsv-,dpj-,bz-,pqqmv=2,ck=5,ftct=8,nzd=5,kdh=1,mq-,htf=2,nnr-,qrdm-,bcvm-,zx-,pm=3,jfl=1,ml=8,mgq-,hhl-,kr=8,xxp-,lrzr-,jzh=5,lqcqp-,kk-,vczz=9,cdf-,zms-,bbt=6,lplzh=8,lhmph-,kxj=1,cxmnl=3,dnhj=9,tlr=9,xxp-,cj=4,vrls-,kzs-,hjns=6,bsx-,vkzss-,ntpb-,vk=9,vd-,dnhj-,hfh=1,prtv=4,lhmph-,ssx=8,tccm-,tccm-,pcxg=6,tc-,nhs=1,vczz=9,zmr-,hgs-,lhmph=4,kgl=6,qjj=5,znnhs=5,lk-,hvvd-,gp-,rhlzp-,hfh=1,tcp-,bpk-,pjrj=6,bs-,dmbj-,dn-,shjl=8,zrm-,dt-,fntz=6,sssgg-,fj-,tglkr-,zrt=8,cnzs-,gp-,sb-,ckx-,tdfsgx=6,lplzh-,ssbh-,zpk-,xhrh-,rq=8,nkcd=3,gdjk-,qc=4,mrg=5,sn=8,br-,xtvtz=2,pmhf-,qz-,gflrf-,htf=3,fntz-,vvx=4,tfb-,frl=4,zz=8,tjb=5,nhs-,lft=2,pcxg-,sv=2,bd-,nz-,vtq-,nhs-,czclc=4,nzd=4,fm=9,mjh-,xx=5,zsqqz=1,dlf-,sqr-,mb=3,mrg=9,cjp=2,zqbhl=7,dp=6,mmvth=8,fcj=5,tr-,qtd-,ss=5,tdvd=5,vbt=3,pskpgz-,tnn=1,jq-,gs-,kzvg=5,tgmr=1,qjb-,rdtv=8,tc-,zxm=3,lft-,dgv=4,qj-,vbz=3,lrzr-,fmc=2,zh-,rc=2,brb-,kvxklg-,shjl=1,jjfz-,sssgg=3,bd=5,jfl-,jvz=1,kb-,jmjjv=9,hp-,kgl=1,hqd=5,bh-,psh-,hprv-,ktjrb=5,tdvd-,mrl-,nk-,sm-,ll=2,jhk-,mjj=5,vv=1,gl=4,jr=8,jhk-,xh=8,nz-,qpn=7,xxp=9,pp=8,kf-,jvvndd=2,vk=6,mx-,dzg=5,pd=5,sn=5,bh-,xs=1,xk=5,dmbj=9,ssv=1,ljc-,mxbq-,bs-,qnl-,zlbg-,qnkn=2,hfq=6,qs-,qhb-,zgs-,lgt-,nhs-,hv-,lxq=1,rns-,pjv-,zp-,ksr-,xqltnl-,dnt=7,qt-,vfd-,hqd-,pm=9,tpph=2,mxbq-,jp=7,hfq=4,tccm=1,dtr-,chg-,zrm-,gvbnl=5,dnhj=3,fdf-,bv-,fcj-,sjdq=4,bzvmmv=2,lb=1,xh=9,nmk=8,qpn=2,kfk-,gghpgg=8,vbt=5,fk=1,xgq=9,pmjd-,ghj-,nhs=7,ldjf=1,vrn=3,qq-,jczj-,hhtcjf-,bm=7,jcx=7,dpc=5,jr=6,lk=6,gp=5,bz-,dtr-,slhc-,mlq-,zs-,ntpb-,lqcqp=1,bpk=6,vvx-,jhkq=6,xzh=6,djjj-,fd-,qrtx-,lrzk-,bm=7,hz=4,hfhgc=9,gp=3,ml-,nq-,pk=7,dhz-,vv-,fx-,fm-,tpph-,db-,tr-,xpz=7,bhvxs-,ll-,hfhgc=7,pcxg-,jp=8,vlm-,bfs=8,dgv-,fqs=7,mbbtz-,hv=8,znnhs-,nk-,pjrj-,qjj-,nnr-,gflrf-,zc-,mk-,jlx-,nf-,vfd-,lk=1,lcx-,nhs=3,sx-,mbbtz=1,mxbq=5,dhz=4,lxq-,xtx-,tq=8,mrf-,drz=1,jhk-,tlt=8,ffr-,bzvmmv=9,qhb-,ss=8,pmzl=6,jhk=8,rvsp=9,lcx-,dmbj=8,bdh=7,qjj=6,xhrp-,hhch=9,jvp=3,bh-,vdgk-,czj=4,jpc-,mbh=8,cc=5,xq-,czh-,nzd=7,kg-,fj-,jr=1,qtd-,rhlzp-,xtcnp-,tqjk-,lk=5,lmj-,jhkq-,zc=7,kg-,mrl-,bsk-,ktjrb=8,nbhhl-,cx=8,bd-,kzvg=7,mlq=8,zpk=8,vbz-,bd=6,bp=7,mgq-,bbt-,sv-,gjj=4,ctd-,js-,mkl-,zzs-,xq-,slhc=8,svf-,vczz=4,lhm-,dzg-,gp-,mjh=9,rps-,vm=6,nsxl=3,ldjf=8,jrhtx=2,fh-,qpn=1,zrt-,kzs-,tf-,ssfn-,qnr=2,grs-,tgmr-,jdfgx=9,nbhhl-,nm=4,bp-,cjp=5,nv=3,tf=3,jfft=1,cng=4,ssfn-,slhc=6,zmr-,rr-,mdf=7,mjh=1,td-,zrm-,rq-,pcxg=8,fz-,jh-,sdrf-,tdfsgx=2,fdf=9,vzn-,zs-,fcj=8,gfczl=8,hn-,gdjk-,rqnbp=5,rp=7,xs=4,llhl=9,kxj=3,cxj-,cbz=8,kphn=9,ntpb=9,nntzz=2,nm=3,fxm-,zjjs=3,ksgkmj=5,zrt=4,sv-,ph=9,lfxnd-,zq-,cmg=2,vbt-,qjj=7,prtv-,dp-,zzs=1,qgf-,zf-,lplzh-,ztzh=4,rp=3,jfft-,lmj=2,mlq=8,rz=8,vvx=4,mgq-,vn=6,zbj=7,zzs=8,jk=7,mcv=3,xxl=2,vlm=9,vcvct-,sqr-,fs=3,kcp-,hjkn=4,vb=4,jhk=1,qq-,nfgj-,vdgk=7,nz-,fdf-,nz-,qpff=1,vc-,fm-,pcxg=5,kgl-,kr=9,fspg=8,ftct=8,sssgg=4,zmq-,hprv=4,pskpgz=6,mshn-,frtvrl=5,bm=4,nfht=1,kxj-,brb=6,nmk-,jhkq-,tdfsgx=7,qt-,dcc-,fcj-,bfs=9,sn=2,fd=3,tr=1,vjs=6,px=6,vr-,ssv=2,sx-,vfd=1,shjl=8,pcxg-,ldjf-,xmkxf=8,hhl=4,qq=7,rq=6,bhvxs=9,ssbh-,vn=6,tglkr=5,zp=5,cbz-,gfczl=3,sx-,hv-,xxp=2,czj-,ddzv-,xxp=8,kg-,kg=6,ss=5,xq-,qgsx-,hth=9,qgf-,jhkq-,cnzs=7,vdgk=1,hhtcjf-,bt-,jrhtx-,vbz-,kcxt=9,qkgkf=9,vbz-,gr=5,nnr=8,pk-,lj=9,xj-,hv-,mdf-,lfxnd-,zxm-,lxn-,zn-,xxp=5,pjv=9,lft=9,rfdx=9,lhmph=1,fg-,gr=4,hz-,lzsdjk-,dk=3,fqs=5,bsk=5,cjp=5,pn-,lp=2,mcv=3,nntzz-,ksr-,crz=7,xqltnl-,lsv-,vdgk-,lbnpn=1,dk-,gcjd-,ssv=6,br-,kfk=2,hjcbzv-,zrm-,hjkn-,qtd=3,scv-,dt-,mrl-,sdrf=8,bj-,rf-,jfl-,kssgnb-,rtjqkd-,dnt=3,ksr-,hjcbzv=7,zzb=6,ldjf=6,pcxg=4,hz=1,qz=5,cpdmvs-,qpff-,gt-,qx-,qhb=6,tgmr-,jzh=2,lqcqp=2,xtx=2,bnkf=5,ldjf-,fjq=9,nq=7,vm-,zn-,lcx-,zxm=4,nfx-,jvvndd=7,vfd-,xb-,zzs=4,vvx-,mxbq=7,crz=6,vjs-,ksr-,pjv-,xjsv-,lvj-,cnt-,rz-,bv=5,frtvrl-,bsx-,vsh-,ljd=8,hfh-,xnxv-,jcx=2,gltc=6,bd=7,dtr-,zp=6,dpc-,rrcd=6,qrtx=7,gbrjv-,ntpb-,fx=3,xgq-,vzx-,lsv=5,shjl=9,pjv-,fq=9,cxmnl-,ck-,dcnj=5,cdb=7,slhc=8,qz-,mx=1,bll-,hfhgc-,bh=3,qhb=6,cdf=5,xb=9,jmjjv-,mnsjll=6,znnhs=3,hhl-,zmmtp-,svf-,zzs=5,kphn-,nzd=5,htf-,zx-,zmr=5,xzh=3,vcvct=6,zx=9,cg=7,rps-,xp-,chg-,lxn-,jvvndd-,ztzh=6,rdfhng=9,qjb=8,ldjf-,sssgg=3,dgv-,hfq-,vqr=6,zbj=2,rncb=9,vfd-,mkl=3,bbt=2,gzl=5,nm-,psh=7,fh-,zpk-,zrt=5,mbtmlh-,cmg=7,drz-,gdjk=6,hprfn-,mp=9,qdd=3,bt=4,bz-,pn=1,tlt-,tlt-,rvsp-,fz=3,spf-,ssx-,xtx-,nhs=9,zs-,pftj-,ztzh-,qv=6,sv=5,dn=8,rd-,ptd=4,rps-,htnv=4,zxm=3,djjj-,lmj=3,btjs-,lhm-,ksgkmj-,vqr=5,lhmph-,cxmnl=2,zzb=5,qjb-,hgs-,rrcd-,tf=8,hprv-,lhm-,pm-,xtvtz=1,qqhht-,ggnc=5,cdf=9,ck-,ltd-,kvxklg-,cxj=7,fdf-,lb=7,rgt=1,jvp=1,btt=1,ktjrb=7,bt=8,sttmb=1,hjkn-,tpph=9,znnhs=3,rns=1,ffr=4,shdrs=6,hjdc=1,xtx-,jmjjv=7,vlm=9,kc=5,tdvd=3,jvp-,crz-,dhz=4,xhrh-,sv-,mb=5,bcvm=2,ss-,vcqq-,ml=6,vcvct=4,pmhf=3,ggnc=9,vfts-,vm-,cvd=2,ksr=7,nz-,zbj=6,sv-,fzn=3,qb=2,fj=7,qr=9,zh=9,zf=2,vcqq=1,lgt-,znnhs=8,vfd=8,ts-,vk=1,vfd-,vdgk-,qgsx-,zz-,hn-,cxmnl-,mgq=3,nr-,ghj-,fk=1,lhmph=6,mlq=3,sssgg=4,jcx=7,sx=3,qnkn-,zbj-,cdf=7,qpn-,grs=2,dtm-,xp=2,rz-,dmbj=2,pk-,bbt=9,xt-,nzd-,mf=6,hhkkdc-,mrg=6,rf-,rz=5,gl=7,sdrf-,zsk=6,mjj=1,dk-,fjq-,qtd-,ktm-,js-,tcp=5,bsk=4,tgmr-,sm-,jh=2,jhk=5,jvz=8,xh=6,mgq-,bdk=9,mlq=7,vtq-,xj=2,bdh=1,bfs=9,lj-,ph-,qtd=9,ptd=1,jp=2,sx=5,lrm=9,hhkkdc=2,nfx=1,bcvm=1,jpc=4,lb-,spf-,jv=8,bdk-,lbnpn-,gs-,lmj=1,pd=6,lxq=9,tl=6,xb-,vcvct=2,rp=9,dgv-,rl=6,kfk=4,tnd=2,fjq-,mlq=1,gbrjv=3,mc-,sjdq-,stc-,lk-,qdkzn-,jh=9,vcvct=7,cj=2,ts=9,bm-,rfdx-,nq=7,tqjk=6,jn-,xjsv-,xtg-,ksgkmj=6,gr=2,gzl-,fs=8,xtx-,dkbdvq=2,vn-,qpff=5,kr=4,rns=1,zmr=4,rvsp-,jhkq-,rps-,htnv=7,tdvd=3,kphn=1,cfm-,zp-,lplzh=4,hn-,zp=1,htnv=9,xtg-,jvb=3,hqd=4,spf=3,mbh=9,njp-,pn-,bnkf=3,bfs-,mq-,fz=4,zmr-,hfh=8,vtq=6,bfs-,tf-,tr-,ssfn=5,bv-,jhkq-,bznnxv=4,rdtv-,xh=7,qc=2,jlx-,zc=8,rv=5,lj=2,qq-,ptd=5,nr=5,zp=7,vzx=7,cx=1,sb=2,kzs-,pmzl-,hjns=6,ll=1,tpph-,pjv=2,vbt=3,gdjk-,ss=6,svf-,hhkkdc-,nmstn-,ksr-,qdkzn-,rrcd=2,zh-,nmq=8,kc-,pr=9,xxp=4,hjdc-,lxn-,vcvct=9,xtg=3,qrtx=5,qr-,hsl=6,njp-,bbt-,xb=1,cbz=8,hbm=6,qr=3,qq-,gvbnl=1,zrm=4,chp=3,jcx=8,zz-,qjj=8,rhssrf-,zlbg-,qv-,xtg-,qqhht-,qb-,hjdc-,mc-,lfc-,chp=3,grs=6,cdq=2,kcp=2,mcv-,tlns=8,pm=5,njfl-,ctd=8,nm=8,mlq=7,nhg-,xtcnp=7,hz-,qv=3,vdgk-,lplzh=2,sdh=1,hjkn=7,hdzp-,ddzv=8,lxq=7,lgt-,cdb-,llhl-,fhhl-,mjj=6,mnn-,qx=5,tc=9,fg=6,vfd=7,lfc-,nv-,zsqqz-,hgs=5,jn=6,drlxt=1,qnl=4,pqqmv-,rtjqkd-,cnt=7,vbz-,vc-,zf-,pmhf=8,vjs-,jvb=9,dn=8,zmr=8,hhtcjf=2,lrszx=3,mjj-,lgt-,vdgk-,pftj=6,fxm-,jvz=8,qtd-,mcv=7,rv-,zpk-,znnhs-,rgt=9,scv=2,vvx=7,kphn-,ptd-,kphn-,xh=6,cj-,vsh=7,czh=6,qs-,hvvd=3,kxj=9,hsl-,sssgg-,slhc=4,dx-,sv=7,kt=6,cmg-,js=6,hpm=5,lrzr-,db-,hbm-,cdq=8,hprfn=1,pftj-,xt-,kc=5,xxl-,cbz=4,kfk=3,rd=8,mmvth-,js-,vb-,qhb-,vcvct=8,db=2,vm-,kc=5,fqs=3,rrcd=4,xs-,dtr-,mcv-,ffr=3,vk-,hrr-,ljc-,mq-,xt-,tlns=4,pftj=8,vbhss=9,jpc=7,cp=9,qb-,mbtmlh=9,mjh-,gkl=6,rz=3,nq=3,qgf-,rc-,xqltnl=7,xh=7,dn=6,jczj=5,sssb=5,lgt-,xtx=4,jp=7,nfgj-,czj-,vv-,br-,hhch-,nq=9,fxm=1,mp-,nk-,qdd-,hth=3,xk=1,mq=8,xpz-,qj=2,hjkn=1,qdd-,gs=7,crz-,kf-,vfd=4,mjj-,cnt-,fhhl-,qtd=2,mrl-,dcc-,chp-,znnhs-,lft=5,pqqmv=7,rl=9,jk=1,xzh-,pq=2,kcp-,mtkx=2,ntpb-,sm=7,xx=5,shdrs-,xf-,dtm=6,lcx=4,zs-,htnv-,zzdl=1,jvz-,dp=3,dqn=3,tf-,dzfxb=3,fntz-,qz=8,qr=6,rr=4,pt=6,mrf=6,cng-,lrm=1,ggnc-,lsm=6,lxq-,bt-,dhn-,hhl-,fmc=4,njfl-,btjs=3,mjsj=6,cp-,fv-,zpk-,vlm-,sc-,zn-,ntpb-,gdjk-,xtcnp-,nv-,rvsp-,tcp-,nhg-,jfl-,rr-,ptd=3,cnzs-,zmmtp=4,ffr-,dg-,xt=3,fj-,ffr=5,ddft-,qs-,scv-,lxq=7,ph-,gr=9,gltc-,vbt-,qkzp-,qb=6,lhmph=9,xb=3,zz=5,zxm=9,nz-,qkgkf-,pt=4,lplzh=6,rps-,ll=5,rps-,kxj-,pk-,mx-,fspg=2,rtjqkd=9
diff --git a/day15/uppga.c b/day15/uppga.c
@@ -0,0 +1,30 @@
+#include "common.h"
+
+static inline char *hashnext(uint64_t *r, char *s) {
+ if (*s == '\0' || *s == '\n')
+ return NULL;
+ uint64_t v = 0;
+ char *cp = s;
+
+ while (*cp != '\0' && *cp != '\n' && *cp != ',') {
+ v = (17 * (v + ((uint64_t)*cp))) & 0xff;
+ cp++;
+ }
+
+ *r = v;
+
+ return cp + 1;
+}
+
+int main(int argc, char **argv) {
+ char **lines;
+ readlines(&lines, "input");
+
+ uint64_t h, summa = 0;
+ char *cp = lines[0];
+ while ((cp = hashnext(&h, cp)) != NULL) {
+ summa += h;
+ }
+
+ printf("%llu\n", summa);
+}
diff --git a/day15/uppgb.c b/day15/uppgb.c
@@ -0,0 +1,139 @@
+#include "common.h"
+
+static inline uint64_t hash(char *s) {
+ uint64_t v = 0;
+ char *cp = s;
+
+ while (*cp != '\0' && *cp != '-' && *cp != '=') {
+ v = (17 * (v + ((uint64_t)*cp))) & 0xff;
+ cp++;
+ }
+
+ return v;
+}
+
+static inline stack_str parse(char *line) {
+ char *cp = line;
+
+ stack_str stack;
+ stack_str_init(&stack);
+
+ while (*cp != '\0' && *cp != '\n') {
+ stack_str_push(&stack, cp);
+ while (*cp != '\0' && *cp != '\n' && *cp != ',') {
+ cp++;
+ }
+ cp++;
+ }
+
+ return stack;
+}
+
+static inline char opn(char *s) {
+ char *c = s;
+ while (*c != '-' && *c != '=')
+ c++;
+
+ return *c;
+}
+
+static inline int cmp(char *s, char *t) {
+ char *cs = s;
+ char *ct = t;
+
+ while (*cs != '-' && *cs != '=' && *ct != '-' && *ct != '=') {
+ if (*cs != *ct)
+ return 1;
+ cs++;
+ ct++;
+ }
+
+ if (*cs == '=' && *ct == '-')
+ return 0;
+
+ if (*cs != *ct)
+ return 1;
+
+ return 0;
+}
+
+typedef TAILQ_HEAD(listhead, entry) lhead_t;
+
+typedef struct entry {
+ char *s;
+ uint64_t fl;
+ TAILQ_ENTRY(entry) entries;
+} entry_t;
+
+static inline void doop(char op, char *s, lhead_t *box) {
+ if (op == '-') {
+ entry_t *np;
+ TAILQ_FOREACH(np, box, entries) {
+ if (cmp(np->s, s) == 0) {
+ // remove np from list
+ TAILQ_REMOVE(box, np, entries);
+ free(np);
+ return;
+ }
+ }
+ } else {
+ uint64_t fl;
+ sread_next_u64(&fl, s);
+ entry_t *np;
+ TAILQ_FOREACH(np, box, entries) {
+ if (cmp(np->s, s) == 0) {
+ // CHANGE np
+ np->s = s;
+ np->fl = fl;
+ return;
+ }
+ }
+
+ // was not in list, add it to the end
+ entry_t *ne = malloc(sizeof(entry_t));
+ ne->s = s;
+ ne->fl = fl;
+ TAILQ_INSERT_TAIL(box, ne, entries);
+ }
+}
+
+static inline uint64_t boxval(lhead_t *box) {
+ entry_t *np;
+ uint64_t slot = 1;
+ uint64_t v = 0;
+
+ TAILQ_FOREACH(np, box, entries) {
+ v += slot * (np->fl);
+ slot++;
+ }
+
+ return v;
+}
+
+int main(int argc, char **argv) {
+ char **lines;
+ size_t i;
+ readlines(&lines, "input");
+
+ stack_str ops = parse(lines[0]);
+
+ // initialize dlinked lists
+ lhead_t lls[256];
+ for (i = 0; i < 256; i++) {
+ TAILQ_INIT(&lls[i]);
+ }
+
+ // operational state
+ for (i = 0; i < ops.nmemb; i++) {
+ uint64_t box = hash(ops.data[i]);
+ doop(opn(ops.data[i]), ops.data[i], &lls[box]);
+ }
+
+ // count sum
+ uint64_t summa = 0;
+ for (i = 0; i < 256; i++) {
+ summa += (i + 1) * boxval(&lls[i]);
+ }
+
+ printf("%llu\n", summa);
+}
diff --git a/day16/Makefile b/day16/Makefile
@@ -0,0 +1,30 @@
+CC=clang
+CFLAGS+=-std=c99 -pedantic -Wall -Werror -Wstrict-prototypes
+CFLAGS+=-Wmissing-prototypes -Wmissing-declarations -Wshadow
+CFLAGS+=-Wpointer-arith -Wcast-qual -Wsign-compare
+CFLAGS+=-O2 -g
+CFLAGS+=-fstack-protector-all -Wtype-limits -fno-common
+CFLAGS+=-fno-builtin
+CFLAGS+=-I/usr/local/include
+CFLAGS+=-I../utils
+#LDFLAGS=
+
+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) $(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)
+
+utils:
+ make -C ../utils
+
+clean:
+ rm -rf common.o uppga uppgb
diff --git a/day16/common.c b/day16/common.c
@@ -0,0 +1,3 @@
+#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,13 @@
+#ifndef COMMON_H_
+#define COMMON_H_
+
+#include <assert.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <reading.h>
+
+size_t fn(char **lines, size_t nlines);
+
+#endif
diff --git a/day16/exinput b/day16/exinput
@@ -0,0 +1,10 @@
+.|...\....
+|.-.\.....
+.....|-...
+........|.
+..........
+.........\
+..../.\\..
+.-.-/..|..
+.|....-|.\
+..//.|....
diff --git a/day16/input b/day16/input
@@ -0,0 +1,110 @@
+\.................-....-.-.|....................|......./.|.\................|...........|....--..............
+............-...................|.............|..-.......-/..............-....\...............................
+|.......//...........................................|...............-......../.....\....................\....
+....|......-.-.............-......\.....\......../..................../.......................................
+..\..\../................../.............-............|....-.........................|......|...............|.
+-..|........................./.................\.........\./.............\..|..-...-.............\............
+.\......||-..................../................-................./....|........................|.............
+..............\./...........-.........../-................-.........\...\........../-.......|.................
+....-..........-.-.....\......................../.......-..........-/.....................||................|.
+./..........|/............................\./............................./....../........\...-|............\-
+........\.............................-...../............---...........|...............|......\\..............
+........//....|.\......./...\.............|..............\............./...........-.|..-.............|.......
+...................\...........-/..-......\...|........-.|................\-.......|........\.................
+|.|....../|............\./..-........\..............................-.....................|....../............
+............-....................-..............-..-................|.//.............-.............-..........
+..........-.......-......|-................./........../...\........-.......................-..\.......\......
+................../....|............-....../................./.....................|.................-........
+...\..............--..|.....||.....\.............\../................................................-.-...../
+.........-......|....-.................-.......\-................./..|...................|\.....\.....|.|-....
+......................-......................-............/....................\...../...\..../...............
+...../......-...............\...-....|......../.........\................................|.........../........
+........../.......\..............-...............\........-|....-......-.............|...........|........./..
+./...............\....../....../..../...................................................|.....|.|../......./..
+....|\........\-...../...................-.............\.\..................................././..........\...
+....................................-..../......................-..///......-...|.|..........................|
+.........-\.....-...........|........./..........-..\.....\./...................-........................-....
+....../.......././......--.....|.\..-...-....\..........................-....-...-..|.|.....|.......\-./......
+...-....................-................|.............-../........|../........-.............|\...............
+...../...........-......../................|................|.....\.....-.............../...|....../\.........
+./...\.....\..-./.........................|................................-....................-.............
+.............\|.../....\\.....\..|...........\.....................|......|.|.....|.....-............\.\......
+........................|......-..........-.../......-........|...../.\|...-................................|.
+.......\...-...\..........|.....\...................\.........|..........-/.........\...................../...
+.-|.......|............./..|./....-.../...\............-......../..............-.......//...-...........||.\..
+..|..\./..-........\..|....-..\.........../..............................|..\..................../..|...../-..
+.|.........-.\...........................\..../......./....||............\..........|............-.\|.........
+....................\..../|............................\.../..|........./...../............||........\....../.
+....................../.....|...................|......|.................|..|.......|................|........
+.....................\.........-..../.........../../..-......\.................|.../....................../...
+........\.-................/........\...../....../.|.\...|/../..........................................-.....
+....................................|......./...../............-................-/..|.-....................\..
+..|.........................-....................../...|.....|.............../.........../.....|\.............
+.......................................|.\.|.......................-.......|..............\............-./....
+..........//................\..|./................-.................-..../../|................................
+.|......................................./............/..-.......-.|.........................\|..|............
+............................/.-..................-./..../..............|-.........-|..........................
+.................-...|................\.........|\...............................\...........\...//...........
+........\..|.|--.............|.......\.................|......|\./.........................\.|................
+.-|.............|\|.....\|././...|..\.............\..\...................\...........\...../..................
+..../..............-..|...|.........-.........\.....-...........-.....|...\.-....-../.................\.......
+........\.|........\\.........-...............-.......-..................................../..........|.......
+...............-...................\/...............\..-\...........|.-........-.\-.....\....\..../......-....
+.../-......./..............|.......|..//......-....................../.|....\......|..\.........../-\.........
+.-....|./....-.../....../.....-..............\..-..\..-............\................|...|..........-.......|..
+|......../...................\..../....\......./..|.................\...............\.........\../.|......../.
+../............/........|..|.......................................\../\...............\............/.......\.
+........-.-...\........../.......-....-............./.............-......./................\..........-.......
+.../-................/......|/........-......|..........|..-..............|/..........................-.......
+......./............../...................|../...../................./../..........\../.....\....\............
+..............-..|../-........................|...\.../...-/..........\.......\......\.................-....-.
+......................................-/.\........................../......-..\..\........\...............|..\
+.............-.........../-|........-........\....-.....\....../..\........................\......|.......\...
+.././....................|\.../\.........\.|.............../..../...|......./.\...|.......\.........|.........
+......................./........./-./...........................|/...\........-.../.................||........
+..............|./........\..............\.............................|/................../............|.-..|.
+.........................-......../........./.....|....-..-.-..............-.-......../.......\...\./.........
+.-............../../....\//......../...|......|......\..................-......\.....-....\|.........|........
+..............-.....................\.................\.|...-............................|......\.............
+\\.....|...........\............|............................../............................................\.
+.-........../|...\..............-...............................\...........\.....|......\..........\.........
+.\............\.|....-........./....../../.....-..\........|...............-..................|............-.|
+.....\......-.........-.........|....../..-....|.....\..../....|........-.....................................
+..........\-..-..../\.....................\.........-...........|..../-.......................\....-..........
+...../............./..|..................../............../../.........|...............-../...................
+.....|...../.....|......-.............................|...........-......................./............/......
+.....................||./.-.................-.........\.\..................-..............\...--.........\....
+.|......-......-.\.......-......\....\..\..|.........../......./.....................-..........|.............
+.....\.....\............................--..................|..-........\....\...\.|.\.-...........\...\......
+./...........\.......\/......|........./..|................\-................/....\...................\.\.....
+..|...............................-.........-.|/......|.....|........\........................................
+.......|............-............../............-......../..-...\|-...-..../...........-..........-..-/.......
+............................-..\.......................................-.........................\..........-.
+........................\.........|................||...-....\......\.....\.................\...\\....../.....
+....\../.....-.......-.................-|...................-../.|-............|........-|......./../...\.....
+..................................................\.......|......./..\./......../....|....-|.-................
+....../.........|.......|...|.......\.../|...............-.......-\..\......././..................|..\.|...../
+............|.....\...........-.............................../.....-.................-.../............/.../..
+...../.......\............................|.....\....\................/..................\......../...........
+..................-....\.........\|................/|......../.-................|...\......................--.
+......-..-.....................................-\.........|.../.....................|..|.-.....\...|....\....-
+......-......-.................-......|..................................................|....................
+..\...............|......../........-......./.............../...........-..........|/.....///\.....-..........
+.........../..|.............../..........\|.........................\...|.....\||....\...|.|/.....-....../....
+...../...../.....-............................................|........|............|.........................
+......-../\................../..............\............\.................../|...........|.............\.....
+...........-..........................-....\..\..|.-..............................................\........|..
+/.--..//....\...............................-............|..././..............................................
+/...............|.........../..../......................\.....|............|...........|...................-..
+..-................\../|......../...................../...........\..|.|\../..................................
+....|...../.....-......\.........................-.....//...............|.........-.......|...-....--.........
+....|..\.-..../....................|..........\............./...........\.../.................................
+............................\...................................../.......................|...........\.......
+.........../.....-.....................\..\.-..|............-...............\.........................-.......
+......-.......-\.\......\..-.-........./...........\..........|........................\.....-.....\..........
+..............-....../.-............./........../..............\-....-.../...../.-............\......./.-.....
+......|...................................................||..../...|\.....................-.../...\........|.
+......|.//........................-...../...........-..\...|......|..................../........../...........
+.....................................................|.........//...........|\.....\....................|.../.
+............-..||...........|....../....................\...\................................../.......|......
+..\....\......./-\.\...........-\................|.........../................||.../.....-...........\........
diff --git a/day16/uppga.c b/day16/uppga.c
@@ -0,0 +1,227 @@
+#include "common.h"
+#include <sys/queue.h>
+
+#define NDIRS 4
+enum direction { RIGHT, DOWN, LEFT, UP };
+
+typedef struct {
+ size_t r;
+ size_t c;
+ enum direction dir;
+} walker;
+
+typedef SIMPLEQ_HEAD(listhead, entry) head_t;
+typedef struct entry {
+ walker v;
+ SIMPLEQ_ENTRY(entry) entries;
+} entry_t;
+
+int main(int argc, char **argv) {
+ char **lines;
+ size_t nrows = readlines(&lines, "input");
+
+ size_t ncols = strnlen(lines[0], 1024);
+ assert(ncols < 1024);
+ ncols--;
+
+ uint8_t hit[NDIRS][nrows][ncols];
+ size_t i, j, k;
+ for (k = 0; k < NDIRS; k++) {
+ for (i = 0; i < nrows; i++) {
+ for (j = 0; j < ncols; j++) {
+ hit[k][i][j] = 0;
+ }
+ }
+ }
+
+ // init queue
+ head_t head = SIMPLEQ_HEAD_INITIALIZER(head);
+
+ // initialize the start
+ walker start = {.r = 0, .c = 0, .dir = RIGHT};
+ entry_t *se = malloc(sizeof(*se));
+ se->v = start;
+ SIMPLEQ_INSERT_HEAD(&head, se, entries);
+ hit[RIGHT][0][0] = 1;
+
+ entry_t *c;
+ while (!SIMPLEQ_EMPTY(&head)) {
+ c = SIMPLEQ_FIRST(&head);
+ SIMPLEQ_REMOVE_HEAD(&head, entries);
+
+ walker t = c->v;
+ printf("Walker (%zu, %zu, %zu)\n", t.dir, t.r, t.c);
+ switch (t.dir) {
+ case RIGHT:
+ if (lines[t.r][t.c] == '.' || lines[t.r][t.c] == '-') {
+ if (t.c < ncols - 1 && !hit[RIGHT][t.r][t.c + 1]) {
+ (c->v).c++;
+ SIMPLEQ_INSERT_TAIL(&head, c, entries);
+ hit[RIGHT][t.r][t.c + 1] = 1;
+ } else {
+ free(c);
+ }
+ } else if (lines[t.r][t.c] == '\\') {
+ if (t.r < nrows - 1 && !hit[DOWN][t.r + 1][t.c]) {
+ (c->v).r++;
+ (c->v).dir = DOWN;
+ SIMPLEQ_INSERT_TAIL(&head, c, entries);
+ hit[DOWN][t.r + 1][t.c] = 1;
+ } else {
+ free(c);
+ }
+ } else if (lines[t.r][t.c] == '/' || lines[t.r][t.c] == '|') {
+ if (t.r > 0 && !hit[UP][t.r - 1][t.c]) {
+ (c->v).r--;
+ (c->v).dir = UP;
+ SIMPLEQ_INSERT_TAIL(&head, c, entries);
+ hit[UP][t.r - 1][t.c] = 1;
+ } else {
+ free(c);
+ }
+
+ if (lines[t.r][t.c] == '|' && t.r < nrows - 1 &&
+ !hit[DOWN][t.r + 1][t.c]) {
+ entry_t *nc = malloc(sizeof(*nc));
+ (nc->v).c = t.c;
+ (nc->v).r = t.r + 1;
+ (nc->v).dir = DOWN;
+ SIMPLEQ_INSERT_TAIL(&head, nc, entries);
+ hit[DOWN][t.r + 1][t.c] = 1;
+ }
+ }
+ break;
+ case DOWN:
+ if (lines[t.r][t.c] == '.' || lines[t.r][t.c] == '|') {
+ if (t.r < nrows - 1 && !hit[DOWN][t.r + 1][t.c]) {
+ (c->v).r++;
+ SIMPLEQ_INSERT_TAIL(&head, c, entries);
+ hit[DOWN][t.r + 1][t.c] = 1;
+ } else {
+ free(c);
+ }
+ } else if (lines[t.r][t.c] == '\\') {
+ if (t.c < ncols - 1 && !hit[RIGHT][t.r][t.c + 1]) {
+ (c->v).c++;
+ (c->v).dir = RIGHT;
+ SIMPLEQ_INSERT_TAIL(&head, c, entries);
+ hit[RIGHT][t.r][t.c + 1] = 1;
+ } else {
+ free(c);
+ }
+ } else if (lines[t.r][t.c] == '/' || lines[t.r][t.c] == '-') {
+ if (t.c > 0 && !hit[LEFT][t.r][t.c - 1]) {
+ (c->v).c--;
+ (c->v).dir = LEFT;
+ SIMPLEQ_INSERT_TAIL(&head, c, entries);
+ hit[LEFT][t.r][t.c - 1] = 1;
+ } else {
+ free(c);
+ }
+
+ if (lines[t.r][t.c] == '-' && t.c < ncols - 1 &&
+ !hit[RIGHT][t.r][t.c + 1]) {
+ entry_t *nc = malloc(sizeof(*nc));
+ (nc->v).c = t.c + 1;
+ (nc->v).r = t.r;
+ (nc->v).dir = RIGHT;
+ SIMPLEQ_INSERT_TAIL(&head, nc, entries);
+ hit[RIGHT][t.r][t.c + 1] = 1;
+ }
+ }
+ break;
+ case LEFT:
+ if (lines[t.r][t.c] == '.' || lines[t.r][t.c] == '-') {
+ if (t.c > 0 && !hit[LEFT][t.r][t.c - 1]) {
+ (c->v).c--;
+ SIMPLEQ_INSERT_TAIL(&head, c, entries);
+ hit[LEFT][t.r][t.c - 1] = 1;
+ } else {
+ free(c);
+ }
+ } else if (lines[t.r][t.c] == '\\') {
+ if (t.r > 0 && !hit[UP][t.r - 1][t.c]) {
+ (c->v).r--;
+ (c->v).dir = UP;
+ SIMPLEQ_INSERT_TAIL(&head, c, entries);
+ hit[UP][t.r - 1][t.c] = 1;
+ } else {
+ free(c);
+ }
+ } else if (lines[t.r][t.c] == '/' || lines[t.r][t.c] == '|') {
+ if (t.r < nrows - 1 && !hit[DOWN][t.r + 1][t.c]) {
+ (c->v).r++;
+ (c->v).dir = DOWN;
+ SIMPLEQ_INSERT_TAIL(&head, c, entries);
+ hit[DOWN][t.r + 1][t.c] = 1;
+ } else {
+ free(c);
+ }
+
+ if (lines[t.r][t.c] == '|' && t.r > 0 && !hit[UP][t.r - 1][t.c]) {
+ entry_t *nc = malloc(sizeof(*nc));
+ (nc->v).c = t.c;
+ (nc->v).r = t.r - 1;
+ (nc->v).dir = UP;
+ SIMPLEQ_INSERT_TAIL(&head, nc, entries);
+ hit[UP][t.r - 1][t.c] = 1;
+ }
+ }
+ break;
+ case UP:
+ if (lines[t.r][t.c] == '.' || lines[t.r][t.c] == '|') {
+ if (t.r > 0 && !hit[UP][t.r - 1][t.c]) {
+ (c->v).r--;
+ SIMPLEQ_INSERT_TAIL(&head, c, entries);
+ hit[UP][t.r - 1][t.c] = 1;
+ } else {
+ free(c);
+ }
+ } else if (lines[t.r][t.c] == '\\') {
+ if (t.c > 0 && !hit[LEFT][t.r][t.c - 1]) {
+ (c->v).c--;
+ (c->v).dir = LEFT;
+ SIMPLEQ_INSERT_TAIL(&head, c, entries);
+ hit[LEFT][t.r][t.c - 1] = 1;
+ } else {
+ free(c);
+ }
+ } else if (lines[t.r][t.c] == '/' || lines[t.r][t.c] == '-') {
+ if (t.c < ncols - 1 && !hit[RIGHT][t.r][t.c + 1]) {
+ (c->v).c++;
+ (c->v).dir = RIGHT;
+ SIMPLEQ_INSERT_TAIL(&head, c, entries);
+ hit[RIGHT][t.r][t.c + 1] = 1;
+ } else {
+ free(c);
+ }
+
+ if (lines[t.r][t.c] == '-' && t.c > 0 && !hit[LEFT][t.r][t.c - 1]) {
+ entry_t *nc = malloc(sizeof(*nc));
+ (nc->v).c = t.c - 1;
+ (nc->v).r = t.r;
+ (nc->v).dir = LEFT;
+ SIMPLEQ_INSERT_TAIL(&head, nc, entries);
+ hit[LEFT][t.r][t.c - 1] = 1;
+ }
+ }
+ break;
+ }
+ }
+
+ uint64_t count = 0;
+ for (i = 0; i < nrows; i++) {
+ for (j = 0; j < ncols; j++) {
+ if (hit[RIGHT][i][j] || hit[LEFT][i][j] || hit[DOWN][i][j] ||
+ hit[UP][i][j]) {
+ printf("#");
+ count++;
+ } else {
+ printf(".");
+ }
+ }
+ printf("\n");
+ }
+
+ printf("%llu\n", count);
+}
diff --git a/day16/uppgb.c b/day16/uppgb.c
@@ -0,0 +1,298 @@
+#include "common.h"
+#include <sys/queue.h>
+
+#define NDIRS 4
+enum direction { RIGHT, DOWN, LEFT, UP };
+
+typedef struct {
+ size_t r;
+ size_t c;
+ enum direction dir;
+} walker;
+
+typedef SIMPLEQ_HEAD(listhead, entry) head_t;
+typedef struct entry {
+ walker v;
+ SIMPLEQ_ENTRY(entry) entries;
+} entry_t;
+
+static inline uint64_t energizer_count(size_t start_r, size_t start_c,
+ enum direction start_dir, size_t nrows,
+ size_t ncols, char **lines,
+ uint8_t ***hit) {
+ size_t i, j;
+ // init queue
+ head_t head = SIMPLEQ_HEAD_INITIALIZER(head);
+
+ // initialize the start
+ walker start = {.r = start_r, .c = start_c, .dir = start_dir};
+ entry_t *se = malloc(sizeof(*se));
+ se->v = start;
+ SIMPLEQ_INSERT_HEAD(&head, se, entries);
+ hit[start_dir][start_r][start_c] = 1;
+
+ entry_t *c;
+ while (!SIMPLEQ_EMPTY(&head)) {
+ c = SIMPLEQ_FIRST(&head);
+ SIMPLEQ_REMOVE_HEAD(&head, entries);
+
+ walker t = c->v;
+ switch (t.dir) {
+ case RIGHT:
+ if (lines[t.r][t.c] == '.' || lines[t.r][t.c] == '-') {
+ if (t.c < ncols - 1 && !hit[RIGHT][t.r][t.c + 1]) {
+ (c->v).c++;
+ SIMPLEQ_INSERT_TAIL(&head, c, entries);
+ hit[RIGHT][t.r][t.c + 1] = 1;
+ } else {
+ free(c);
+ }
+ } else if (lines[t.r][t.c] == '\\') {
+ if (t.r < nrows - 1 && !hit[DOWN][t.r + 1][t.c]) {
+ (c->v).r++;
+ (c->v).dir = DOWN;
+ SIMPLEQ_INSERT_TAIL(&head, c, entries);
+ hit[DOWN][t.r + 1][t.c] = 1;
+ } else {
+ free(c);
+ }
+ } else if (lines[t.r][t.c] == '/' || lines[t.r][t.c] == '|') {
+ if (t.r > 0 && !hit[UP][t.r - 1][t.c]) {
+ (c->v).r--;
+ (c->v).dir = UP;
+ SIMPLEQ_INSERT_TAIL(&head, c, entries);
+ hit[UP][t.r - 1][t.c] = 1;
+ } else {
+ free(c);
+ }
+
+ if (lines[t.r][t.c] == '|' && t.r < nrows - 1 &&
+ !hit[DOWN][t.r + 1][t.c]) {
+ entry_t *nc = malloc(sizeof(*nc));
+ (nc->v).c = t.c;
+ (nc->v).r = t.r + 1;
+ (nc->v).dir = DOWN;
+ SIMPLEQ_INSERT_TAIL(&head, nc, entries);
+ hit[DOWN][t.r + 1][t.c] = 1;
+ }
+ }
+ break;
+ case DOWN:
+ if (lines[t.r][t.c] == '.' || lines[t.r][t.c] == '|') {
+ if (t.r < nrows - 1 && !hit[DOWN][t.r + 1][t.c]) {
+ (c->v).r++;
+ SIMPLEQ_INSERT_TAIL(&head, c, entries);
+ hit[DOWN][t.r + 1][t.c] = 1;
+ } else {
+ free(c);
+ }
+ } else if (lines[t.r][t.c] == '\\') {
+ if (t.c < ncols - 1 && !hit[RIGHT][t.r][t.c + 1]) {
+ (c->v).c++;
+ (c->v).dir = RIGHT;
+ SIMPLEQ_INSERT_TAIL(&head, c, entries);
+ hit[RIGHT][t.r][t.c + 1] = 1;
+ } else {
+ free(c);
+ }
+ } else if (lines[t.r][t.c] == '/' || lines[t.r][t.c] == '-') {
+ if (t.c > 0 && !hit[LEFT][t.r][t.c - 1]) {
+ (c->v).c--;
+ (c->v).dir = LEFT;
+ SIMPLEQ_INSERT_TAIL(&head, c, entries);
+ hit[LEFT][t.r][t.c - 1] = 1;
+ } else {
+ free(c);
+ }
+
+ if (lines[t.r][t.c] == '-' && t.c < ncols - 1 &&
+ !hit[RIGHT][t.r][t.c + 1]) {
+ entry_t *nc = malloc(sizeof(*nc));
+ (nc->v).c = t.c + 1;
+ (nc->v).r = t.r;
+ (nc->v).dir = RIGHT;
+ SIMPLEQ_INSERT_TAIL(&head, nc, entries);
+ hit[RIGHT][t.r][t.c + 1] = 1;
+ }
+ }
+ break;
+ case LEFT:
+ if (lines[t.r][t.c] == '.' || lines[t.r][t.c] == '-') {
+ if (t.c > 0 && !hit[LEFT][t.r][t.c - 1]) {
+ (c->v).c--;
+ SIMPLEQ_INSERT_TAIL(&head, c, entries);
+ hit[LEFT][t.r][t.c - 1] = 1;
+ } else {
+ free(c);
+ }
+ } else if (lines[t.r][t.c] == '\\') {
+ if (t.r > 0 && !hit[UP][t.r - 1][t.c]) {
+ (c->v).r--;
+ (c->v).dir = UP;
+ SIMPLEQ_INSERT_TAIL(&head, c, entries);
+ hit[UP][t.r - 1][t.c] = 1;
+ } else {
+ free(c);
+ }
+ } else if (lines[t.r][t.c] == '/' || lines[t.r][t.c] == '|') {
+ if (t.r < nrows - 1 && !hit[DOWN][t.r + 1][t.c]) {
+ (c->v).r++;
+ (c->v).dir = DOWN;
+ SIMPLEQ_INSERT_TAIL(&head, c, entries);
+ hit[DOWN][t.r + 1][t.c] = 1;
+ } else {
+ free(c);
+ }
+
+ if (lines[t.r][t.c] == '|' && t.r > 0 && !hit[UP][t.r - 1][t.c]) {
+ entry_t *nc = malloc(sizeof(*nc));
+ (nc->v).c = t.c;
+ (nc->v).r = t.r - 1;
+ (nc->v).dir = UP;
+ SIMPLEQ_INSERT_TAIL(&head, nc, entries);
+ hit[UP][t.r - 1][t.c] = 1;
+ }
+ }
+ break;
+ case UP:
+ if (lines[t.r][t.c] == '.' || lines[t.r][t.c] == '|') {
+ if (t.r > 0 && !hit[UP][t.r - 1][t.c]) {
+ (c->v).r--;
+ SIMPLEQ_INSERT_TAIL(&head, c, entries);
+ hit[UP][t.r - 1][t.c] = 1;
+ } else {
+ free(c);
+ }
+ } else if (lines[t.r][t.c] == '\\') {
+ if (t.c > 0 && !hit[LEFT][t.r][t.c - 1]) {
+ (c->v).c--;
+ (c->v).dir = LEFT;
+ SIMPLEQ_INSERT_TAIL(&head, c, entries);
+ hit[LEFT][t.r][t.c - 1] = 1;
+ } else {
+ free(c);
+ }
+ } else if (lines[t.r][t.c] == '/' || lines[t.r][t.c] == '-') {
+ if (t.c < ncols - 1 && !hit[RIGHT][t.r][t.c + 1]) {
+ (c->v).c++;
+ (c->v).dir = RIGHT;
+ SIMPLEQ_INSERT_TAIL(&head, c, entries);
+ hit[RIGHT][t.r][t.c + 1] = 1;
+ } else {
+ free(c);
+ }
+
+ if (lines[t.r][t.c] == '-' && t.c > 0 && !hit[LEFT][t.r][t.c - 1]) {
+ entry_t *nc = malloc(sizeof(*nc));
+ (nc->v).c = t.c - 1;
+ (nc->v).r = t.r;
+ (nc->v).dir = LEFT;
+ SIMPLEQ_INSERT_TAIL(&head, nc, entries);
+ hit[LEFT][t.r][t.c - 1] = 1;
+ }
+ }
+ break;
+ }
+ }
+
+ uint64_t count = 0;
+ for (i = 0; i < nrows; i++) {
+ for (j = 0; j < ncols; j++) {
+ if (hit[RIGHT][i][j] || hit[LEFT][i][j] || hit[DOWN][i][j] ||
+ hit[UP][i][j]) {
+ count++;
+ }
+ }
+ }
+
+ return count;
+}
+
+static inline void zeroise_hits(uint8_t ***hit, size_t nrows, size_t ncols) {
+ size_t i, j, k;
+ for (k = 0; k < NDIRS; k++) {
+ hit[k] = malloc(nrows * sizeof(*hit[k]));
+ for (i = 0; i < nrows; i++) {
+ hit[k][i] = malloc(ncols * sizeof(*hit[k][i]));
+ for (j = 0; j < ncols; j++) {
+ hit[k][i][j] = 0;
+ }
+ }
+ }
+}
+
+int main(int argc, char **argv) {
+ char **lines;
+ size_t nrows = readlines(&lines, "input");
+
+ size_t ncols = strnlen(lines[0], 1024);
+ assert(ncols < 1024);
+ ncols--;
+
+ uint8_t **hit[NDIRS];
+ size_t i, j, k;
+ for (k = 0; k < NDIRS; k++) {
+ hit[k] = malloc(nrows * sizeof(*hit[k]));
+ for (i = 0; i < nrows; i++) {
+ hit[k][i] = malloc(ncols * sizeof(*hit[k][i]));
+ for (j = 0; j < ncols; j++) {
+ hit[k][i][j] = 0;
+ }
+ }
+ }
+
+ uint64_t max_count = 0;
+ uint64_t count;
+
+ // top row, downwards
+ for (i = 0; i < ncols; i++) {
+ count = energizer_count(0, i, DOWN, nrows, ncols, lines, hit);
+ if (count > max_count)
+ max_count = count;
+ zeroise_hits(hit, nrows, ncols);
+ }
+
+ // bottom row, upwards
+ for (i = 0; i < ncols; i++) {
+ count = energizer_count(nrows - 1, i, UP, nrows, ncols, lines, hit);
+ if (count > max_count)
+ max_count = count;
+ zeroise_hits(hit, nrows, ncols);
+ }
+
+ // left side, rightwards
+ for (i = 0; i < nrows; i++) {
+ count = energizer_count(i, 0, RIGHT, nrows, ncols, lines, hit);
+ if (count > max_count)
+ max_count = count;
+ zeroise_hits(hit, nrows, ncols);
+ }
+
+ // right side, leftwards
+ for (i = 0; i < nrows; i++) {
+ count = energizer_count(i, ncols - 1, LEFT, nrows, ncols, lines, hit);
+ if (count > max_count)
+ max_count = count;
+ zeroise_hits(hit, nrows, ncols);
+ }
+
+ // remaining corners
+ count = energizer_count(0, 0, RIGHT, nrows, ncols, lines, hit);
+ if (count > max_count)
+ max_count = count;
+ zeroise_hits(hit, nrows, ncols);
+ count = energizer_count(0, ncols - 1, LEFT, nrows, ncols, lines, hit);
+ if (count > max_count)
+ max_count = count;
+ zeroise_hits(hit, nrows, ncols);
+ count = energizer_count(nrows - 1, 0, RIGHT, nrows, ncols, lines, hit);
+ if (count > max_count)
+ max_count = count;
+ zeroise_hits(hit, nrows, ncols);
+ count = energizer_count(nrows - 1, ncols - 1, LEFT, nrows, ncols, lines, hit);
+ if (count > max_count)
+ max_count = count;
+ zeroise_hits(hit, nrows, ncols);
+
+ printf("%llu\n", max_count);
+}
diff --git a/day17/Makefile b/day17/Makefile
@@ -0,0 +1,30 @@
+CC=clang
+CFLAGS+=-std=c99 -pedantic -Wall -Werror -Wstrict-prototypes
+CFLAGS+=-Wmissing-prototypes -Wmissing-declarations -Wshadow
+CFLAGS+=-Wpointer-arith -Wcast-qual -Wsign-compare
+CFLAGS+=-O2 -g
+CFLAGS+=-fstack-protector-all -Wtype-limits -fno-common
+CFLAGS+=-fno-builtin
+CFLAGS+=-I/usr/local/include
+CFLAGS+=-I../utils
+#LDFLAGS=
+
+UTILS=../utils/reading.o ../utils/wdg.o ../utils/stack_u64.o ../utils/fheap.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) $(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)
+
+utils:
+ make -C ../utils
+
+clean:
+ rm -rf common.o uppga uppgb
diff --git a/day17/common.c b/day17/common.c
@@ -0,0 +1,3 @@
+#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,14 @@
+#ifndef COMMON_H_
+#define COMMON_H_
+
+#include <assert.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <reading.h>
+#include <wdg.h>
+
+size_t fn(char **lines, size_t nlines);
+
+#endif
diff --git a/day17/exinput b/day17/exinput
@@ -0,0 +1,13 @@
+2413432311323
+3215453535623
+3255245654254
+3446585845452
+4546657867536
+1438598798454
+4457876987766
+3637877979653
+4654967986887
+4564679986453
+1224686865563
+2546548887735
+4322674655533
diff --git a/day17/input b/day17/input
@@ -0,0 +1,141 @@
+333213136361262336321612214531777457112145343436646554277834586842636477377358665483232322865545123271135255712112742775561145666154365233356
+625436214642112116663631316165754345156613447614784645884723775385422237785533457846422687888517441575665644164125345724771731422533345336535
+135464262413363523172353673663343124614327663325483447348582478365458326464522365884857228745883344645545337271265517463212456153534241544452
+463341164253235233654257664712176156221273446338438725387868466637872246443458373458772474446735864427171225417624722447465614145334226531133
+612123231364647651775663426212224226114337776577776736788424832776656343782563357835523563646643373362516426762263641757743221457544513132115
+554121446241214313746711736452662635625733462823288665545675563668763743787742653833765545345747825838821335355445434347415641445636564324243
+224451135242133732146576324716743753368865727642288276285674826268356773857358774272262757346428753268886423252537566456457145362241413235356
+312115633663242411233636615741633726487283228864835444425576777233878745223464452866553565685646725656653473162633463643521135773411433452466
+542364224173757771326524416535552277757354762743288837354468764353627364676267546484532727724264832675772357663444464333544311464653635434155
+644453415415675332722151756256718248247685882878285324462473375646475283722538546752748236463677656374757244824312452134314757122175246666133
+553335516731473766365715331215568572352758878273527332573426865584372534367686638785426548725847452264452655432363227522743746771746731616324
+133445474224722676227554462116647666753275526734788533873228633423522662378822462553685245662683348523576827224635133441463776656147576542321
+262263545476415133716375434754684868667682745356337755425335477366862483227738582326352468542752785886234837282845863613725264761734336443244
+114557561615633115446342258245858844385456266756554434328822765476533686573637497788623453646223225852468238675466763313713633227154741356245
+611315162633241542646131578684535533767564585652735786467776834489896877967363837453335767245825426445885342673428236331451157547442775237312
+362261614652576557153353266488324456657568285858237439538887578466544663574533349347999664436466843472663827648852522875316714732344324217372
+154236775775512321522263368636678482445745255477872966786867669355994753645973978496654594795457367226453428858886655252654623377164654233436
+462622424671674313226637785458826766472883676833993634453836356375787779937773696649358983467446647337585265887587723374463642735172144752645
+256461325176535257663462355464575334764872223438763949469848778946443559566434444799354636443886736785674266463345527548557615613664272723332
+624227517633531434243827827654636862345763525366656758486948446474677985365493464466378853868458497378656656647884675348243277163765174172612
+642426252112436471458742474775766555755482666556764666989755347483839876866543593833948554547649543695673778734785343556567234476436622452236
+472761551511731356577488843522288387648575847749585654676577859987674545338478446453935695888655834749368252388424646347784477427672675234731
+747257136413274266658434523648663224583865945533979664865739647394863547663534658684836947849398659354975525423267856334772333414472751271125
+574343547662773544664738635233783383586446637996489896655677988659366366569546668595949965836367778345574626644234463758638787822267745754521
+367475241771674622685256576755377256694657754777544899383684634438534485979934747656784795398385666575337783432384738285554737675522715746365
+256367447543715652882652564564844549667487979647384545688783886347534748746799385454464568597377867697868876544676868477782387732724561552121
+261235663177628353884845384445766258763957538398695337944456734653958794684775489984866453396736953989445799737336434633265843536845722326147
+431276435456537534853737352526378373785887936397348334479754963636988696675746463374338676858375353484947593688636237753457284385777117617624
+421367347552372223365324757658483977886994994547997755837953398686686495795587856558739768889585363493453579446427556683583574426622272442257
+653441321737655477657783556762464689667939878673459467647756948694579899586649949485693964996883964648379558954548747354857488783362127442566
+515161447757685543432764636463458639776554884767986333854576485676459546765778469857646486376565785857443977735796532864253257624473821333334
+336171521157845857727533754249765675378444363369739966487567564657564788675786859867955577864736596843659475696378544727675554642784241753632
+623372113877373226883677764958453497559443687766594489754655444467966644745947494698459586785645959777965677437493446724843825534677422225442
+236731618585276273353786287559939845985699963868795668657679996977589756994768598496447448576699786446978776785836952358253352634682675575162
+765546725582536686487447374798889846794833537458484957646996958598746684878684958848884578574656384796834539634597853385236344482474876472666
+235141347247436634846668336949436933994444973649584458877948958567497986597747594579955455786945889674656448794468553656367688688576238422422
+671623678362665454588528544384845379775883686557595448549476796988894494486867784996978797854689456778495488399676989768386537635625688831242
+514567273474547255558849794485665888753549445498649654858986448467857554544489744945685865544486656543767539535947995573778388352332288357236
+421323835776877754277637737948643468887899675798595548644885557689854854755598964995897678954896674945488794549443555993763265444882527744633
+354668742484843385355475877734984796958775599649956999999868487764495968495996998799544585565676488647789369959545359597757558327676228242324
+223675455323285573553448797956956995447989558679767596794986699975765799696477454587975754758775874888765498885699494634477672743525548872573
+476176284827585535382536674788367479838589886659789789675958497767575745594699578578798877588865566954496744386339878768748227448658776552362
+675625837477642733439383847993547559885769745955958866975847899547878879759976747796969499588689558956864465635487346833935452386378264867816
+472576623464266256473345754344444687595755546988945978967684649897557995775998977845644887549855889776779634755544666998999672672342225572236
+723338425874676478785895383956556476546955695985859465659544888989996856667888856697795988445756499858565899394779558798674387882836464633723
+753728823447466882883747584457899843886998789895745784456685775586887577578765568686646979944897697865577785359537559569439878872222674682675
+274684763532572374694739777585794889467744468465856969675999788859799587656669956766879888694794447678648759598739793358559772824233728356645
+115256466578823832558738735747633445985469799749547867559586775788896687689676778758799785564977797499978848453988848336553978432627386327573
+548252468286265749598354987757696464686857494949578959857786799756957966686965775569557987846877876965964586958467884766384759555228862634247
+775472876326246686637894874745853649677794865574684765688797569775786779676665589897676756784645888896665785543377644867338379482443888857873
+644246825637683644835877767347453454568867554444775599777767668577979986777676558668678688677679776689769699579869596396588947647254276727432
+675667637753876445999597848375487698587994465886656589877797669767788999875799765675659757957578557549945978889843335993675545354636824673588
+453657476346684869637675496555556899746757988568488977766655889967896758557996798965985989857698968976595894997539483568475599986552355853787
+632248555553887766398487683844487988644864579699765575897969566597999875796789796868695775556589856859985497684784986459989377837883752727386
+266885253575644787699874544547358568447586577656878599657789988877699865956869569876989796775779644456759775589884987483797956747657856577762
+723737537288886965937656574853968596447486789966589956855986786958985788878986767699969598779956745799646979669779964733354855388722376852482
+443568274582252776976439948936677979955468588859687866879589988898686988555665587768558588765557864897448688757653998979337985377854464534445
+447864347254476796783339876544897778998589886776989758966555866986869698869987597675579987966765886976856455866796939445755784944224278247282
+286764482526429646636893847639887457964499865677657686675598857859797898986769757875786568567875884684897845464566539854353669377286744552562
+884623287654836563345579989899869797774668448589998785767869696687897686898796989867595959779585698588455599575769555743843637455423642847562
+473473534468357576875845833637898889894456886876658898586788889999978988998996766667995685987759868969954665459945743358543335675522322378342
+558656456533693883798863894469449475765876655569858666587798989687787787989969897758776576759555957456874769876788793436438855695738227383863
+775323532357798584683386967869946765585998787866977987768899897967977677787668867979997875686697856578774577566474536533944646986828353322626
+636525836872783447833786838746487985757947559969566995787998789678697887868999886776987796867865978774949956548865588585333454467763683243723
+223783768826293857378738893588985777747665455658759689799898778786898798968769968866675997995587875974646549667698977489885365856652626534534
+655668564837447467734565736667964785484656976967858568999686677669768867778699977967988896858859975554449795969546794984867597638648248862288
+225343788236467744769383578758544899859678585565557767667976969786769668786977967696677777767879769879599956585486565669653579739367484637542
+835548267463785585868885946675784945686995679868879868987996776666887886779978868697689999897889796585884675744998754566869986454554226637285
+524428887552843774745688555798844499576574787766799978865898668987896987898688678969787697657777676868954858888788978685799658846625432887244
+763757348466458486656985748946874858799455676675987865666678777698899997898866986677866879785687579874469459574889673643598465975777433358366
+558623257663757383557737659894456765449758668885695585688999896679878866779769888776767959786989978696448594745469878439358857637358376632635
+528622755875457489733889333676448449454678675689757776677677989696976997989988998776976656885665797787967855898746764557993438689586832535665
+262728464482859769395553766495674944869965999668566886969668676777777997768868787977768658859995696654799457798859898374396568466488756437887
+487364277357887467848976636677547566648654786665587569798866998968969679896669978778669565988899885979674848554559648349968485933658775276677
+256557832538447785573836549555759676868974976586768988799986797966866968688667679787685978567778888955456854966856893685889888958764585648486
+855327664424565667757758383684697655957747577978978775569899977977699667776898969778876576599586557597548664594777895375789973774584645288543
+732845238734368499538864859548756666479886668687697768598879889678988699668687669688977859865889687898469679897598943336499683959942888535428
+458542434722763964465544385478485684455675996566988868659799887966987786679967897869965595997757965798487494979485589377554593895588267246482
+685847653777387636587598637367844947984698996755976878779587879698766699987897976799568875579798897684584584986654768893364665848656732765345
+762585858463375454454757776765559455786986498756689585998968787967679696669978887887688575658778696897888854989458553333897338689655835452286
+667873648672677658987454838677545846469568967886596768986598796689987767768689666768986658987869955676568588688768453475384649894476834537652
+842528743554868476638843667989678696874765796896959858759975698996797697976896867888777589667795556658457584544444987934878388869422286538442
+665343556563653997694469347978779548957944896859765588765596979887999677667789969589887866968899686678674894597485654658977459957726383878528
+328824677886664984396688493979448944877675767875999859577958979976669668997796865999595779786956688644899745994747993439474788339373534756228
+355756624245748345976656569348866554494757766868566879567996775777969987877698797776568579757957884846984866766974746746679776886436337862352
+355757567353465353488558943489856995554566447865897697675796898598867787679676599676998886658795658757497445698747499484766988999524476665632
+846657543354688449334738753488965977658866855499795568898766969857755689976595969566968775778979897599779888747778646949389737938563864722776
+222542436248338757373365596953577857876777785799965997596579779865977868956968975778576689656575877994977994789888957578689985758278542255648
+826824626578323678956737348575645548667794498456877779558696685766765996577578587987677557956655865887766685575597559586696339864465556545445
+672427854774774447537349755387458787447985567486958868665967999968578888699789679579765855665666979559547795958783794639459777774442844848878
+452738222778884766739495654588679795558448477676597569955979565868955588879678799665558655888789467848675579858647645878346849574448882222864
+758576763255686269387767336544539998768579756648557995595656978897967599569788776975596788679985698969567697489998968793955383784544678786632
+678436753644435345347447966785579845484646744646487695989759998868659588985955685776856855858876655597799764746838845569653937223437636586333
+153356642488363235694785688879876855588546969589468567687885587869879886789976696579686967894679667978785876977786753437476588524434273755854
+317882332358268727633385869964735386459785875794857867997665676899967595976585567676855598555645898564749684567698568497736368755887663276756
+553352323553345584655944375958334686544568859455468796685877879698899655875768559585886794875996949678754578849953483443664676458224858845353
+226242868452584232838385446446584795649549968885595968669559887868595888787986597867775869477996957548958997745474643897437962535233473847335
+763437726764765464384839593494346588548966488976888467686695997587595769966888579976969574885694897878495979536355474365933684556223554783653
+334278427343676884873643567798477894397499659898464896868445778678559678867597585695856677759484646474967738743563443894378377283723754866354
+364424658235542285759346854636443367549844976595677469978794477788586986958755885599989755694446697474644964964983966865983577367685328757466
+455622346675434466627968485848334339354654996796977484977857577887756998698686754756945458949654447788745764956687878957977434537343783638652
+414184424528876752586855777635698734866576769557959785596469664746649494559498845858666498789995498898658847578497464938567723887863346627657
+222772455675785688574998639973555974944766976784479574958877596999849664659945847467647789846894574575635438985969979554995728363778854553125
+677628437436684347656498938477378693894696449576775986548874779449786764447597479766688898875689864965776667499493345574866436336567337437624
+727144464542867245566869335935377934486434974797786595457564598959848687776647496647465959978878559954334348436574447499645564648783242651735
+674465558434274722483688736769576358375786454868584589888544764896746786474855594477756874777796878944535948989854563367676767484465444776326
+726533354666455265533323549584966633794448865544599665579849559497987549997649674549948764954685654349464854738689883675423622887538654821713
+535573223637762777632285839887974778679897479369667476556956869879497768758647674887896647544666687975893857695458543723255688642672675862221
+255535736242852283868554325347575397384336774436484858866587586755899486587655454967555665966975663696979486933568746833678573262445584616646
+214572456854867737354845558369476949957347579668976958674554696576744766648687859866476774777643597768347583663398885752627665835224846512477
+371732321862355823583888685844948884786873347664969678964485466654478449789884489776849689977577875398656486579666646252236884842427525351222
+755452776637557847683266785359855837945944434565975844659787695696599787667855996799896894795583563369965993837535988483426388337385551317346
+624247422144477474527542264625377545399353835655777686676558457988798589686775496667468777664876676594688543354784668676457344367483543224435
+726747757662436335676345653676447795979833784595875464445795867894945684668894664784796997383764953754343447734898852834456338785274333454615
+656524125146784236674758852648558449357375838974493447769796646554486847575545464888994338434735849538353478789986482347532782254363661472563
+741673514746232538637764537446675846398449657483463375339458595884669445554943846844543788465649464966859863755825887888234583773257611734354
+115447175112756867445654567638362867738959786833688557394833846766836963768548698489347967855973377359398374424534763322552454276872625532313
+646447735554116277864467783735634526644379536385485867549646689936365936747569865533745486769389548684434696386454368652483866265564264175517
+156357554736777347244836373377643868656397864867543567474734466399984876557668389778368878535399696963467657336387568483474722445664715556671
+676531166544312447583457363455235228663973454388438947673946746397554543958554839695589977738346656754557864443875267837373884832321325454352
+375454737124536248825826374335662725588486787449847987633835885576444673594585963544539687578738858696895377838727858622246743261771513171412
+663221374752176732356433254854467623222337544745757575986873573348797879683544358747747883345378444998345746855624868354582726326427315146522
+372672327573647444768323574353783836558756863845757974999357964793355369499865757489588866744979345496744543385375627278633243325452754777727
+274411174533334575377634754324275384762783855996735464353753454977454863488377875438734385846633365787658277884763677557882653763245234776223
+146347645243261273336652374224464433425686378576955887786883747389484868679879937578846538888495848456473877527237835533565641525351147615326
+141327513341666141456432262572624453542782332474487533834446535778573599686333378976786438944868387632546466422733238663662467436527227326373
+452334645227737122357346433753223664266624686726288755858638875989736854855937375897383455453552262745532864542645456757322527154263366545246
+564567126412756234244374586823572827374582865645538367879397839863933576769579345934496455586668763835224477367878667425336151337125473517231
+522573127256225475151321676282788662828282654287378334654664485457379835977568695853846443237655738445627723762862432252247713467242214222715
+115232137775553663237162765368267344427487347824665373483627845573784686839985736626727684228876547543784372385582862455642317132377274374326
+614413156371526427352242352155873282328737854473556666586484765738353332376774777335743758274258857326568365427873811553131613135216564354355
+253143425547637746352146673345427633575267732435583484844824334674266868882434835445546486887675482737678485652343545677362731672733355235426
+135416521244316712675247627473738882768645567522443286388764423448534575553633387378644626683283266657388887325266535244771737424147617432243
+224264636446232647421555321542226827527468366836655546266327524662542748584562245765823264636467576284785684627137242762421431155713541156551
+125223515312471412437476611237727888843547672522485265335266476756823553686844257655425377577535653447587823487447715644722565471412322644515
+466226253356466742613422245771772648283625753376568357583424862627265425238836236538423663853668245256256886743613661555715336473155535446153
+156113463546647546677356722765372325222684267767736523785588826535245724585442626474425786735443647537842265534261737657677635756761552664461
+413165222554534642614256513354313511531447235383325856686642346288744536764733824582786672755644735786636555447622131315536651514411612546144
+122656344636144672343462327767372421575444642365688282487355348223472385562684363233663426485262384645652447136253111261762331217515423142461
+625544236663123525632771524343756333375737354285885448862737335573726334374686245844372776387666268514551657774225657652271651412245212411451
+423126354124653331672162233413635177574771624528322686824883233468774665567775866376682464873886553453552265645627675251266551441231365256263
diff --git a/day17/uppga.c b/day17/uppga.c
@@ -0,0 +1,111 @@
+#include "common.h"
+
+#define NDIRS 4
+#define NMOVES 3
+#define MAX_NBRS 2048
+
+typedef struct {
+ int64_t r;
+ int64_t c;
+ size_t d;
+ uint64_t acc;
+} nbr_t;
+
+const int64_t dirm[4][2][2] = {{{0, -1}, {0, +1}},
+ {{+1, 0}, {-1, 0}},
+ {{0, -1}, {0, +1}},
+ {{+1, 0}, {-1, 0}}};
+
+static inline size_t dirr(const int64_t dir[2]) {
+ if (dir[0] == 0) {
+ if (dir[1] == -1)
+ return 3;
+ return 1;
+ } else {
+ if (dir[0] == -1)
+ return 0;
+ return 2;
+ }
+}
+
+static inline void nbrs_append(nbr_t *out, size_t *nout, int64_t r, int64_t c,
+ size_t d, uint64_t acc) {
+ assert(*nout < MAX_NBRS);
+ out[*nout] = (nbr_t){.r = r, .c = c, .d = d, .acc = acc};
+ (*nout)++;
+}
+
+static inline void pnbrs(nbr_t *out, size_t *nout, int64_t r, int64_t c,
+ size_t d, int64_t nr, int64_t nc, uint64_t **cost,
+ size_t lb, size_t ub) {
+ *nout = 0;
+ size_t i;
+ for (i = 0; i < 2; i++) {
+ int64_t dd[2] = {dirm[d][i][0], dirm[d][i][1]};
+ size_t acc = 0;
+ size_t ste = 0;
+ int64_t rr = r;
+ int64_t cc = c;
+ while (0 <= r && r < nr && 0 <= c && c < nc && ste <= ub) {
+ rr += dd[0];
+ cc += dd[1];
+ ste++;
+ if (0 <= rr && rr < nr && 0 <= cc && cc < nc) {
+ acc += cost[rr][cc];
+ if (ste >= lb)
+ nbrs_append(out, nout, rr, cc, dirr(dd), acc);
+ }
+ }
+ }
+}
+
+static inline size_t tuple_to_node(int64_t r, int64_t c, size_t d, size_t nc) {
+ return ((size_t)r) * nc * NDIRS + ((size_t)c) * NDIRS + d;
+}
+
+int main(int argc, char **argv) {
+ char **lines;
+ size_t nr = readlines(&lines, "input");
+
+ size_t nc = strlen(lines[0]) - 1;
+
+ uint64_t **costs = malloc(nr * sizeof(*costs));
+ size_t i, j, k, l, nnbrs, nv, nw;
+ for (i = 0; i < nr; i++)
+ costs[i] = malloc(nc * sizeof(**costs));
+ for (i = 0; i < nr; i++) {
+ for (j = 0; j < nc; j++) {
+ costs[i][j] = (uint64_t)(lines[i][j] - '0');
+ }
+ }
+
+ nbr_t *nbrs = malloc(MAX_NBRS * sizeof(*nbrs));
+ size_t nvertices = nr * nc * NDIRS + 2;
+ wdg_t g;
+ wdg_init(&g, nvertices);
+
+ for (i = 0; i < nr; i++) {
+ for (j = 0; j < nc; j++) {
+ for (k = 0; k < NDIRS; k++) {
+ pnbrs(nbrs, &nnbrs, i, j, k, nr, nc, costs, 0, 2);
+ nv = tuple_to_node(i, j, k, nc);
+ for (l = 0; l < nnbrs; l++) {
+ nw = tuple_to_node(nbrs[l].r, nbrs[l].c, nbrs[l].d, nc);
+ wdg_add_edge(&g, nv, nw, nbrs[l].acc);
+ }
+ }
+ }
+ }
+ free(nbrs);
+
+ size_t start = nvertices - 2;
+ size_t end = nvertices - 1;
+
+ for (i = 0; i < NDIRS; i++)
+ wdg_add_edge(&g, tuple_to_node(nr - 1, nc - 1, i, nc), end, 0);
+ wdg_add_edge(&g, start, tuple_to_node(0, 0, 0, nc), 0);
+ wdg_add_edge(&g, start, tuple_to_node(0, 0, 3, nc), 0);
+
+ uint64_t tot = wdg_dijkstra(&g, start, end);
+ printf("%llu\n", tot);
+}
diff --git a/day17/uppgb.c b/day17/uppgb.c
@@ -0,0 +1,111 @@
+#include "common.h"
+
+#define NDIRS 4
+#define NMOVES 3
+#define MAX_NBRS 2048
+
+typedef struct {
+ int64_t r;
+ int64_t c;
+ size_t d;
+ uint64_t acc;
+} nbr_t;
+
+const int64_t dirm[4][2][2] = {{{0, -1}, {0, +1}},
+ {{+1, 0}, {-1, 0}},
+ {{0, -1}, {0, +1}},
+ {{+1, 0}, {-1, 0}}};
+
+static inline size_t dirr(const int64_t dir[2]) {
+ if (dir[0] == 0) {
+ if (dir[1] == -1)
+ return 3;
+ return 1;
+ } else {
+ if (dir[0] == -1)
+ return 0;
+ return 2;
+ }
+}
+
+static inline void nbrs_append(nbr_t *out, size_t *nout, int64_t r, int64_t c,
+ size_t d, uint64_t acc) {
+ assert(*nout < MAX_NBRS);
+ out[*nout] = (nbr_t){.r = r, .c = c, .d = d, .acc = acc};
+ (*nout)++;
+}
+
+static inline void pnbrs(nbr_t *out, size_t *nout, int64_t r, int64_t c,
+ size_t d, int64_t nr, int64_t nc, uint64_t **cost,
+ size_t lb, size_t ub) {
+ *nout = 0;
+ size_t i;
+ for (i = 0; i < 2; i++) {
+ int64_t dd[2] = {dirm[d][i][0], dirm[d][i][1]};
+ size_t acc = 0;
+ size_t ste = 0;
+ int64_t rr = r;
+ int64_t cc = c;
+ while (0 <= r && r < nr && 0 <= c && c < nc && ste <= ub) {
+ rr += dd[0];
+ cc += dd[1];
+ ste++;
+ if (0 <= rr && rr < nr && 0 <= cc && cc < nc) {
+ acc += cost[rr][cc];
+ if (ste >= lb)
+ nbrs_append(out, nout, rr, cc, dirr(dd), acc);
+ }
+ }
+ }
+}
+
+static inline size_t tuple_to_node(int64_t r, int64_t c, size_t d, size_t nc) {
+ return ((size_t)r) * nc * NDIRS + ((size_t)c) * NDIRS + d;
+}
+
+int main(int argc, char **argv) {
+ char **lines;
+ size_t nr = readlines(&lines, "input");
+
+ size_t nc = strlen(lines[0]) - 1;
+
+ uint64_t **costs = malloc(nr * sizeof(*costs));
+ size_t i, j, k, l, nnbrs, nv, nw;
+ for (i = 0; i < nr; i++)
+ costs[i] = malloc(nc * sizeof(**costs));
+ for (i = 0; i < nr; i++) {
+ for (j = 0; j < nc; j++) {
+ costs[i][j] = (uint64_t)(lines[i][j] - '0');
+ }
+ }
+
+ nbr_t *nbrs = malloc(MAX_NBRS * sizeof(*nbrs));
+ size_t nvertices = nr * nc * NDIRS + 2;
+ wdg_t g;
+ wdg_init(&g, nvertices);
+
+ for (i = 0; i < nr; i++) {
+ for (j = 0; j < nc; j++) {
+ for (k = 0; k < NDIRS; k++) {
+ pnbrs(nbrs, &nnbrs, i, j, k, nr, nc, costs, 4, 9);
+ nv = tuple_to_node(i, j, k, nc);
+ for (l = 0; l < nnbrs; l++) {
+ nw = tuple_to_node(nbrs[l].r, nbrs[l].c, nbrs[l].d, nc);
+ wdg_add_edge(&g, nv, nw, nbrs[l].acc);
+ }
+ }
+ }
+ }
+ free(nbrs);
+
+ size_t start = nvertices - 2;
+ size_t end = nvertices - 1;
+
+ for (i = 0; i < NDIRS; i++)
+ wdg_add_edge(&g, tuple_to_node(nr - 1, nc - 1, i, nc), end, 0);
+ wdg_add_edge(&g, start, tuple_to_node(0, 0, 0, nc), 0);
+ wdg_add_edge(&g, start, tuple_to_node(0, 0, 3, nc), 0);
+
+ uint64_t tot = wdg_dijkstra(&g, start, end);
+ printf("%llu\n", tot);
+}
diff --git a/day18/Makefile b/day18/Makefile
@@ -0,0 +1,30 @@
+CC=clang
+CFLAGS+=-std=c99 -pedantic -Wall -Werror -Wstrict-prototypes
+CFLAGS+=-Wmissing-prototypes -Wmissing-declarations -Wshadow
+CFLAGS+=-Wpointer-arith -Wcast-qual -Wsign-compare
+CFLAGS+=-O2 -g
+CFLAGS+=-fstack-protector-all -Wtype-limits -fno-common
+CFLAGS+=-fno-builtin
+CFLAGS+=-I/usr/local/include
+CFLAGS+=-I../utils
+#LDFLAGS=
+
+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) $(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)
+
+utils:
+ make -C ../utils
+
+clean:
+ rm -rf common.o uppga uppgb
diff --git a/day18/common.c b/day18/common.c
@@ -0,0 +1,22 @@
+#include "common.h"
+
+static inline int64_t iabs(const int64_t x) { return x >= 0 ? x : -x; }
+
+int64_t area(const pos_t *cornetto, const size_t n) {
+ size_t i;
+
+ int64_t exterior = 0;
+ for (i = 0; i < n - 1; i++) {
+ exterior += iabs(cornetto[i].x - cornetto[i + 1].x);
+ exterior += iabs(cornetto[i].y - cornetto[i + 1].y);
+ }
+
+ // shoelace formula for interior area
+ int64_t interior = 0;
+ for (i = 0; i < n - 1; i++)
+ interior += (cornetto[i].x * cornetto[i + 1].y) -
+ (cornetto[i + 1].x * cornetto[i].y);
+
+ // compensate error with pick's thm
+ return (iabs(interior) - exterior) / 2 + 1 + exterior;
+}
diff --git a/day18/common.h b/day18/common.h
@@ -0,0 +1,16 @@
+#ifndef COMMON_H_
+#define COMMON_H_
+
+#include <assert.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+typedef struct {
+ int64_t x;
+ int64_t y;
+} pos_t;
+
+int64_t area(const pos_t *cornetto, const size_t n);
+
+#endif
diff --git a/day18/exinput b/day18/exinput
@@ -0,0 +1,14 @@
+R 6 (#70c710)
+D 5 (#0dc571)
+L 2 (#5713f0)
+D 2 (#d2c081)
+R 2 (#59c680)
+D 2 (#411b91)
+L 5 (#8ceee2)
+U 2 (#caa173)
+L 1 (#1b58a2)
+U 2 (#caa171)
+R 2 (#7807d2)
+U 3 (#a77fa3)
+L 2 (#015232)
+U 2 (#7a21e3)
diff --git a/day18/input b/day18/input
@@ -0,0 +1,640 @@
+L 4 (#248a72)
+U 3 (#295c13)
+L 4 (#49e802)
+U 5 (#5ff8b3)
+R 3 (#0df642)
+U 2 (#15b973)
+R 5 (#6cfb92)
+U 11 (#4e3cd3)
+L 4 (#422dd0)
+D 5 (#303fe3)
+L 7 (#6225e0)
+D 2 (#58bd63)
+L 9 (#6225e2)
+D 8 (#2b1703)
+L 6 (#422dd2)
+D 9 (#2eb9b3)
+L 2 (#10f270)
+D 10 (#0677b3)
+L 4 (#190450)
+U 11 (#55b4e3)
+L 4 (#361732)
+U 3 (#034663)
+L 4 (#37f902)
+U 6 (#19bb73)
+R 8 (#6e1030)
+U 8 (#4cad93)
+L 4 (#2509d0)
+U 6 (#1e1e61)
+L 5 (#3d3b90)
+U 8 (#28ec81)
+L 2 (#3f9200)
+U 5 (#437871)
+L 6 (#174bc0)
+D 5 (#3b58a1)
+L 11 (#064a60)
+U 5 (#539da3)
+L 4 (#1ea0d0)
+D 7 (#1909b3)
+L 2 (#296a52)
+D 9 (#6780c3)
+L 3 (#296a50)
+U 11 (#356893)
+L 2 (#0eb430)
+U 5 (#019203)
+L 5 (#4eea10)
+U 4 (#436533)
+L 4 (#20aeb0)
+U 4 (#2fb883)
+L 6 (#5046c0)
+U 11 (#392293)
+R 8 (#2567a0)
+U 3 (#57ee03)
+R 12 (#270540)
+U 2 (#358173)
+R 6 (#289e40)
+U 2 (#77b991)
+R 4 (#016c10)
+U 11 (#351091)
+R 2 (#714f90)
+U 6 (#4add71)
+L 11 (#00eab0)
+D 5 (#2f8361)
+L 8 (#192200)
+U 5 (#1416c1)
+L 13 (#775d30)
+U 3 (#3d3d63)
+L 8 (#6e4710)
+U 3 (#28cfd3)
+L 8 (#389880)
+U 5 (#28cfd1)
+L 7 (#4cd750)
+D 5 (#1d56e3)
+L 3 (#2789e2)
+D 5 (#5d7573)
+R 9 (#1b1372)
+D 5 (#1965a3)
+R 4 (#111052)
+D 2 (#5a2861)
+R 10 (#37f1c2)
+D 3 (#0b7ad1)
+R 5 (#012162)
+U 5 (#226f43)
+R 4 (#583cd2)
+D 5 (#4333f3)
+R 5 (#0eb952)
+D 3 (#22a273)
+L 2 (#34c5d0)
+D 3 (#355f11)
+L 5 (#13a460)
+D 4 (#355f13)
+L 6 (#3e2900)
+U 4 (#28d423)
+L 8 (#042432)
+D 3 (#4378f3)
+L 6 (#18a200)
+D 5 (#16a843)
+L 5 (#18a202)
+D 7 (#46fdd3)
+L 5 (#2a4802)
+D 5 (#2a4d23)
+L 5 (#6049d2)
+D 4 (#0a4023)
+L 4 (#09afb2)
+U 4 (#687713)
+L 5 (#4b85f2)
+D 4 (#0e1a53)
+L 8 (#331b60)
+U 6 (#270d83)
+L 6 (#331b62)
+U 6 (#25dba3)
+L 6 (#412e82)
+D 6 (#5e2e73)
+L 8 (#1de802)
+U 6 (#1e7143)
+L 4 (#4e7e82)
+U 3 (#160d63)
+L 5 (#19d230)
+U 3 (#36a4a3)
+R 3 (#19d232)
+U 6 (#4c63b3)
+R 10 (#0d2862)
+U 5 (#0ec351)
+R 11 (#593c62)
+U 6 (#12de21)
+R 2 (#08d482)
+U 4 (#277081)
+R 3 (#10eee0)
+U 4 (#382b91)
+L 4 (#512200)
+U 7 (#1279f1)
+L 3 (#229312)
+U 6 (#422721)
+R 6 (#71ddd2)
+U 6 (#093871)
+R 13 (#0d5622)
+D 5 (#093873)
+R 7 (#4c34e2)
+U 6 (#5b1743)
+R 2 (#4779a2)
+D 6 (#1cc6e3)
+R 7 (#3c13a0)
+U 5 (#3b60f3)
+R 4 (#3c13a2)
+U 9 (#229f83)
+R 3 (#0a6ff2)
+D 2 (#06d231)
+R 8 (#0298b2)
+D 11 (#4eb6a1)
+R 7 (#0298b0)
+U 8 (#438ce1)
+R 7 (#0e69e2)
+U 5 (#2d3e73)
+R 8 (#40b2c2)
+U 6 (#64cb53)
+L 2 (#40b2c0)
+U 3 (#0215c3)
+L 3 (#2cbf42)
+U 4 (#00c523)
+L 7 (#1fc3d2)
+D 4 (#68a633)
+L 5 (#1fc3d0)
+U 5 (#149853)
+L 5 (#2cbf40)
+U 9 (#0b9613)
+L 3 (#1e7f00)
+U 8 (#2fc533)
+L 7 (#3d7180)
+U 3 (#33f3a3)
+R 9 (#66d340)
+U 2 (#0fa1f1)
+R 4 (#0546c0)
+D 6 (#4c00b3)
+R 8 (#483b50)
+U 6 (#4c00b1)
+R 4 (#2fc7c0)
+U 2 (#0fa1f3)
+R 7 (#377280)
+U 6 (#200c43)
+R 5 (#429ef0)
+U 3 (#3a90f1)
+R 5 (#226142)
+U 4 (#2740c1)
+R 5 (#41ac62)
+U 3 (#275423)
+R 2 (#3ba072)
+U 11 (#275421)
+R 4 (#27ea92)
+D 8 (#402001)
+R 2 (#3456c0)
+D 6 (#5a4541)
+R 3 (#4d1400)
+U 4 (#5a4543)
+R 6 (#462de0)
+U 8 (#3fcdb1)
+R 6 (#1f2d90)
+U 6 (#4e7851)
+R 3 (#41eb30)
+D 6 (#4e7853)
+R 4 (#1aa1c0)
+D 10 (#0a4073)
+R 6 (#2134b2)
+D 7 (#164e43)
+R 4 (#200c72)
+D 5 (#3beca3)
+R 6 (#7445e0)
+U 3 (#2cda83)
+R 4 (#7445e2)
+U 3 (#475553)
+L 5 (#200c70)
+U 10 (#23fb33)
+R 5 (#2134b0)
+U 7 (#3c98d3)
+L 4 (#4cfc80)
+U 5 (#0f0e71)
+R 8 (#3c1d22)
+U 10 (#23a311)
+R 6 (#05da32)
+D 5 (#6229c1)
+R 5 (#41f750)
+D 8 (#1f4191)
+R 3 (#3530f0)
+D 13 (#4d3941)
+R 3 (#6215e0)
+D 9 (#2fe911)
+R 6 (#05cf90)
+U 4 (#25c901)
+R 2 (#335232)
+U 12 (#271371)
+R 2 (#335230)
+U 5 (#2bd1d1)
+L 9 (#1ffad0)
+U 6 (#6f6bc1)
+R 9 (#099600)
+U 5 (#13bee1)
+R 3 (#5aa820)
+U 3 (#3546c1)
+R 6 (#4dd5f0)
+D 11 (#495be1)
+R 6 (#60c8e0)
+U 11 (#4bd201)
+R 4 (#367f30)
+D 4 (#43dbc1)
+R 6 (#4bb740)
+U 12 (#07ce11)
+R 6 (#4b4d70)
+D 12 (#3e29e1)
+R 5 (#313fc0)
+U 4 (#293d51)
+R 4 (#1b4860)
+U 11 (#514571)
+R 4 (#5c11a2)
+U 4 (#444841)
+R 8 (#5c11a0)
+U 2 (#3e6c51)
+R 11 (#16dab0)
+U 7 (#26baf1)
+R 2 (#32e240)
+U 5 (#26baf3)
+R 6 (#2f0a70)
+U 6 (#11a821)
+R 3 (#527fc0)
+U 7 (#468b31)
+R 6 (#0641a0)
+U 10 (#20f351)
+R 7 (#547a90)
+U 12 (#1dbf11)
+R 2 (#17d0d2)
+U 10 (#159981)
+R 6 (#634e12)
+U 5 (#4ff021)
+R 10 (#006122)
+D 6 (#6589a3)
+R 3 (#1a74f2)
+D 2 (#19b911)
+R 12 (#3ed5f2)
+D 5 (#28ab31)
+R 3 (#09dd82)
+D 5 (#614c01)
+R 6 (#284d32)
+D 9 (#06b521)
+R 8 (#4dfad2)
+D 7 (#5b0f61)
+R 2 (#0fff22)
+D 5 (#1e6ff1)
+R 2 (#47b352)
+D 9 (#29c291)
+R 5 (#352ef2)
+D 3 (#042d11)
+R 4 (#262542)
+D 7 (#042d13)
+R 4 (#21e8f2)
+D 3 (#18cc21)
+R 3 (#16ed70)
+U 9 (#270ea1)
+R 7 (#4391e0)
+U 9 (#270ea3)
+R 4 (#22bdd0)
+D 3 (#3b72b1)
+R 7 (#1fd4b2)
+D 8 (#01bfe1)
+L 7 (#3d18a2)
+D 7 (#20dac1)
+R 4 (#67d990)
+D 4 (#1acd93)
+L 7 (#017410)
+D 2 (#6e4923)
+L 7 (#10bdd0)
+D 13 (#0650b3)
+L 2 (#072660)
+U 13 (#221151)
+L 6 (#41d720)
+D 3 (#5bc831)
+L 4 (#252450)
+D 9 (#118de1)
+R 6 (#05b1d0)
+D 4 (#247721)
+R 9 (#2b6b10)
+U 4 (#60da41)
+R 10 (#470c42)
+D 3 (#4fdc91)
+R 2 (#470c40)
+D 8 (#189db1)
+L 5 (#4a1f70)
+D 7 (#07e141)
+L 3 (#2524b0)
+D 5 (#2a6ce1)
+L 11 (#1a2e50)
+D 2 (#4f08c1)
+L 3 (#3b7ec0)
+D 9 (#65e011)
+L 8 (#24b9a0)
+D 6 (#196c61)
+L 5 (#540b20)
+D 6 (#243801)
+L 2 (#397ce0)
+D 3 (#411a41)
+L 12 (#397ce2)
+D 2 (#526d51)
+L 2 (#5b5810)
+D 5 (#2e96d3)
+L 8 (#6c4f80)
+U 6 (#274453)
+L 3 (#077010)
+U 5 (#37f603)
+R 5 (#73bf92)
+U 4 (#29ee73)
+R 11 (#5ffd40)
+U 5 (#3e12d3)
+L 4 (#4b4e32)
+U 12 (#114e01)
+L 2 (#45d0b2)
+U 4 (#114e03)
+L 6 (#4b8b02)
+U 9 (#3eff03)
+L 4 (#6968d0)
+U 4 (#3d4d33)
+L 6 (#1dd0e0)
+D 2 (#436023)
+L 9 (#58b812)
+D 6 (#423003)
+L 7 (#2e81a2)
+D 3 (#3d9e13)
+L 11 (#305450)
+D 6 (#2667f3)
+L 7 (#3a8470)
+D 8 (#293191)
+R 3 (#207ee0)
+D 4 (#293193)
+R 3 (#2c4360)
+D 4 (#2667f1)
+R 7 (#250ee0)
+U 4 (#70e1c3)
+R 4 (#2907d0)
+D 6 (#0b69a1)
+R 6 (#3babc0)
+D 6 (#7698c3)
+R 2 (#2752c0)
+D 3 (#7698c1)
+L 4 (#2dc550)
+D 11 (#4ec121)
+L 8 (#199d00)
+U 11 (#33f261)
+L 7 (#3b4e30)
+D 5 (#24e991)
+L 6 (#0aaeb2)
+U 9 (#15a993)
+L 5 (#59ed02)
+U 2 (#15a991)
+L 5 (#2c0432)
+U 10 (#337e81)
+L 7 (#248670)
+D 2 (#511d31)
+L 3 (#52ebc0)
+D 13 (#511d33)
+L 4 (#192db0)
+D 7 (#3dcf11)
+L 2 (#285030)
+D 3 (#15acc1)
+L 6 (#3a6c70)
+D 5 (#36f281)
+L 4 (#44fd02)
+U 5 (#4e8821)
+L 4 (#473972)
+U 5 (#2ab9f1)
+L 8 (#60aaa0)
+U 5 (#35c651)
+L 3 (#4736b2)
+U 10 (#4741d1)
+L 3 (#1973f2)
+U 5 (#1b5031)
+L 3 (#3c6532)
+D 5 (#49bd31)
+L 4 (#5e3f60)
+D 3 (#4a2011)
+L 4 (#2ba190)
+D 6 (#4a2013)
+L 3 (#653430)
+D 7 (#10dda1)
+L 11 (#2532d2)
+D 3 (#675311)
+L 4 (#27d642)
+D 6 (#02cae1)
+L 10 (#466652)
+D 7 (#34cef3)
+R 3 (#263692)
+D 7 (#34cef1)
+R 8 (#2c59d2)
+D 5 (#31afe1)
+L 8 (#091562)
+D 5 (#12c861)
+R 4 (#47a772)
+D 5 (#68a5b1)
+L 7 (#1f79a2)
+D 4 (#3b3c13)
+R 10 (#0e7122)
+D 4 (#087363)
+R 4 (#3e26c2)
+U 13 (#4953f3)
+R 3 (#5ac862)
+U 3 (#4953f1)
+R 3 (#13cfe2)
+D 5 (#087361)
+R 11 (#57f7a2)
+D 4 (#3b3c11)
+L 11 (#6dcb32)
+D 7 (#35e653)
+R 6 (#525282)
+D 5 (#3dac93)
+R 9 (#377082)
+D 6 (#2afda1)
+R 10 (#3e6422)
+D 10 (#220471)
+R 10 (#37ebf2)
+D 2 (#4d0213)
+R 5 (#2fa2f2)
+D 4 (#30df53)
+R 5 (#617e00)
+U 6 (#536393)
+R 5 (#496510)
+D 6 (#5f6733)
+R 4 (#3bf9b0)
+D 3 (#5f6731)
+R 4 (#48d940)
+D 3 (#35a5d3)
+R 4 (#284a82)
+D 9 (#445b23)
+L 4 (#2535c2)
+D 4 (#3f8b43)
+R 2 (#41a002)
+D 7 (#20b143)
+R 3 (#63ae42)
+U 8 (#328b03)
+R 9 (#383210)
+U 3 (#1ce143)
+R 7 (#383212)
+U 6 (#2ed603)
+R 5 (#00c512)
+U 6 (#6dea43)
+R 6 (#00c510)
+U 7 (#0f0643)
+R 3 (#4292a2)
+U 7 (#684961)
+R 3 (#03de80)
+U 5 (#46e0b1)
+R 6 (#3d4ae2)
+D 5 (#1d5fc1)
+R 7 (#3d4ae0)
+U 13 (#470ab1)
+R 5 (#03de82)
+U 4 (#282c71)
+R 6 (#5520f2)
+D 5 (#2f0981)
+R 2 (#5520f0)
+D 12 (#4081a1)
+R 6 (#22a272)
+U 5 (#284c53)
+R 8 (#081202)
+D 5 (#0b7831)
+R 4 (#3e4552)
+D 13 (#0b7833)
+R 5 (#38e092)
+U 11 (#284c51)
+R 2 (#550082)
+U 2 (#175033)
+R 6 (#036dc2)
+D 3 (#068791)
+R 9 (#3ff6f2)
+D 5 (#4a5783)
+R 13 (#4d5f92)
+D 6 (#3e3423)
+L 12 (#4f62d2)
+D 7 (#5e4363)
+L 3 (#0f7032)
+U 7 (#285261)
+L 12 (#4ea392)
+D 5 (#4c2dc1)
+L 4 (#0d2822)
+D 5 (#4c2dc3)
+R 9 (#518da2)
+D 2 (#41b3b1)
+R 7 (#023270)
+D 3 (#13d6e1)
+R 11 (#0874c0)
+D 3 (#2026c1)
+R 4 (#68f3a0)
+D 7 (#2026c3)
+L 8 (#208470)
+D 4 (#09bd81)
+L 3 (#193a10)
+D 7 (#5f3491)
+L 4 (#08cad2)
+D 10 (#068793)
+L 10 (#48acb2)
+D 4 (#20e341)
+L 7 (#6137a2)
+D 8 (#20e343)
+L 7 (#0bf292)
+D 7 (#5b5f13)
+L 8 (#2b2532)
+D 3 (#034073)
+L 5 (#3c7bb2)
+D 11 (#09c643)
+L 3 (#0d6e52)
+U 3 (#569d23)
+L 5 (#63fed0)
+U 4 (#162193)
+L 4 (#2eb310)
+U 3 (#655e23)
+L 10 (#42f8e0)
+U 4 (#341983)
+R 14 (#3dbbc0)
+U 5 (#551b13)
+L 5 (#2a94f0)
+U 6 (#05ae53)
+L 2 (#09db90)
+U 5 (#2c9e13)
+L 8 (#4c6d10)
+D 10 (#40ffb3)
+L 3 (#306c30)
+D 2 (#338911)
+L 6 (#4bed00)
+D 7 (#338913)
+R 7 (#12aae0)
+D 4 (#459613)
+L 7 (#75d3a2)
+D 7 (#37ad61)
+L 6 (#6dcf92)
+D 4 (#3b7703)
+R 9 (#0ee2b2)
+D 4 (#514c13)
+R 6 (#0ee2b0)
+D 3 (#2863b3)
+L 8 (#52eee2)
+D 8 (#2fc771)
+L 7 (#5be782)
+D 4 (#2f39a1)
+L 6 (#5be780)
+U 4 (#5625b1)
+L 2 (#5588c2)
+U 14 (#37ad63)
+L 3 (#0681e2)
+U 4 (#085481)
+L 3 (#037432)
+U 12 (#31ed51)
+L 4 (#6791e2)
+D 5 (#3546d3)
+L 6 (#4419e2)
+D 10 (#3546d1)
+L 4 (#2c1a72)
+D 10 (#5bead1)
+L 3 (#3b3252)
+D 9 (#3390c1)
+L 3 (#1d78c2)
+D 5 (#488d71)
+R 10 (#244042)
+D 2 (#10d1e1)
+R 5 (#3fd582)
+D 5 (#5025a1)
+L 3 (#381b70)
+D 11 (#771831)
+L 7 (#2abf50)
+U 11 (#17be81)
+L 5 (#1eb3c0)
+D 5 (#3d9c61)
+L 5 (#5f4de2)
+D 8 (#278361)
+L 2 (#2b95b2)
+D 9 (#2cb0b1)
+L 4 (#4a0182)
+D 6 (#2c6bb3)
+L 2 (#499642)
+D 5 (#4c76d3)
+L 8 (#2fe412)
+U 9 (#07b893)
+L 2 (#236d52)
+U 8 (#3956a3)
+L 7 (#34f252)
+U 3 (#52bbf1)
+L 7 (#189470)
+U 4 (#54b661)
+L 9 (#189472)
+U 7 (#0110f1)
+L 3 (#409bf2)
+U 3 (#46d3e3)
+L 5 (#4c0f82)
+U 11 (#215e73)
+L 4 (#4c0f80)
+U 7 (#4050f3)
+L 9 (#39b192)
+U 7 (#28b043)
+L 3 (#011270)
+U 7 (#1f6693)
+R 7 (#73c390)
+U 2 (#2c4113)
+R 5 (#0321c0)
+U 8 (#2f2903)
+L 12 (#5ab560)
+U 3 (#4dd983)
+L 6 (#38b7d2)
+U 12 (#03c8c3)
diff --git a/day18/uppga.c b/day18/uppga.c
@@ -0,0 +1,48 @@
+#include "common.h"
+
+#define MAXCORNERS 2048
+
+static inline pos_t to_move(const char dir, const int64_t n) {
+ pos_t res;
+ switch (dir) {
+ case 'U':
+ res = (pos_t){0, n};
+ break;
+ case 'R':
+ res = (pos_t){n, 0};
+ break;
+ case 'D':
+ res = (pos_t){0, -n};
+ break;
+ case 'L':
+ res = (pos_t){-n, 0};
+ break;
+ }
+ return res;
+}
+
+int main() {
+ pos_t cornetto[MAXCORNERS];
+ cornetto[0].x = 0;
+ cornetto[0].y = 0;
+ size_t ncornetto = 1;
+ FILE *f = fopen("input", "r");
+ char col[8];
+ col[7] = '\0';
+ char dir;
+ int64_t n;
+
+ while (ncornetto < MAXCORNERS &&
+ fscanf(f, "%c %lld (%7s)\n", &dir, &n, &col) != EOF) {
+ pos_t move = to_move(dir, n);
+ cornetto[ncornetto].x = cornetto[ncornetto - 1].x + move.x;
+ cornetto[ncornetto].y = cornetto[ncornetto - 1].y + move.y;
+ ncornetto++;
+ }
+ assert(ncornetto < MAXCORNERS);
+
+ int64_t a = area(cornetto, ncornetto);
+ printf("area = %lld\n", a);
+
+ fclose(f);
+}
diff --git a/day18/uppgb.c b/day18/uppgb.c
@@ -0,0 +1,65 @@
+#include "common.h"
+
+#define MAXCORNERS 2048
+
+static inline int64_t hex_to_n(const char *s, const size_t n) {
+ size_t i;
+ int64_t r = 0;
+
+ for (i = 0; i < n; i++) {
+ assert(('0' <= s[i] && s[i] <= '9') || ('a' <= s[i] && s[i] <= 'f'));
+ r <<= 4;
+ if (s[i] <= '9')
+ r += (int64_t)(s[i] - '0');
+ else
+ r += (int64_t)(s[i] - 'a') + 10;
+ }
+
+ return r;
+}
+
+static inline pos_t to_move(const char *s) {
+ pos_t res;
+ int64_t n = hex_to_n(&s[1], 5);
+ switch (s[6]) {
+ case '0':
+ res = (pos_t){n, 0};
+ break;
+ case '1':
+ res = (pos_t){0, -n};
+ break;
+ case '2':
+ res = (pos_t){-n, 0};
+ break;
+ case '3':
+ res = (pos_t){0, n};
+ break;
+ }
+ return res;
+}
+
+int main() {
+ pos_t cornetto[MAXCORNERS];
+ cornetto[0].x = 0;
+ cornetto[0].y = 0;
+ size_t ncornetto = 1;
+ FILE *f = fopen("input", "r");
+ char col[8];
+ col[7] = '\0';
+ char dir;
+ int64_t n;
+
+ while (ncornetto < MAXCORNERS &&
+ fscanf(f, "%c %lld (%7s)\n", &dir, &n, &col) != EOF) {
+ pos_t move = to_move(col);
+ cornetto[ncornetto].x = cornetto[ncornetto - 1].x + move.x;
+ cornetto[ncornetto].y = cornetto[ncornetto - 1].y + move.y;
+ ncornetto++;
+ }
+ assert(ncornetto < MAXCORNERS);
+
+ int64_t a = area(cornetto, ncornetto);
+ printf("area = %lld\n", a);
+
+ fclose(f);
+}
diff --git a/day19/Makefile b/day19/Makefile
@@ -0,0 +1,30 @@
+CC=clang
+CFLAGS+=-std=c99 -pedantic -Wall -Werror -Wstrict-prototypes
+CFLAGS+=-Wmissing-prototypes -Wmissing-declarations -Wshadow
+CFLAGS+=-Wpointer-arith -Wcast-qual -Wsign-compare
+CFLAGS+=-O2 -g
+CFLAGS+=-fstack-protector-all -Wtype-limits -fno-common
+CFLAGS+=-fno-builtin
+CFLAGS+=-I/usr/local/include
+CFLAGS+=-I../utils
+#LDFLAGS=
+
+UTILS=../utils/reading.o ../utils/sd.o ../utils/stack_sd.o ../utils/dict.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) $(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)
+
+utils:
+ make -C ../utils
+
+clean:
+ rm -rf common.o uppga uppgb
diff --git a/day19/common.c b/day19/common.c
@@ -0,0 +1,107 @@
+#include "common.h"
+#include "reading.h"
+
+void print_dict(dict_t *d) {
+ size_t i, j;
+
+ for (i = 0; i < d->nalloc; i++) {
+ for (j = 0; j < (d->keys[i]).nmemb; j++) {
+ printf("%s: ", (d->keys[i]).data[j].data);
+ size_t x = *((size_t *)(d->values[i]).data[j]);
+ printf("%llu\n", x);
+ }
+ }
+}
+
+static inline size_t cadd(dict_t *d, char *name) {
+ sd sdname;
+ sd_init_str(&sdname, name);
+ void *p = dict_lookup(d, sdname);
+
+ if (p == NULL) {
+ size_t r = d->nelts;
+ size_t *v = malloc(sizeof(*v));
+ *v = r;
+
+ dict_insert(d, sdname, v);
+
+ return r;
+ }
+
+ return *((size_t *)p);
+}
+
+static inline void parseconds(cond_t *cds, dict_t *d, char *conds, size_t row) {
+ size_t ncds = 0;
+ char *ss = strtok(conds, ",");
+ while (ss != NULL) {
+ if (strstr(ss, ":")) {
+ int64_t x;
+ char *cp = sread_next_i64(&x, ss) + 1;
+ size_t i = cadd(d, cp);
+
+ cds[ncds].from = row;
+ cds[ncds].to = i;
+ switch (ss[0]) {
+ case 'x':
+ cds[ncds].entry = 0;
+ break;
+ case 'm':
+ cds[ncds].entry = 1;
+ break;
+ case 'a':
+ cds[ncds].entry = 2;
+ break;
+ default:
+ cds[ncds].entry = 3;
+ }
+ cds[ncds].cond = ss[1];
+ cds[ncds].bound = x;
+ ncds++;
+ } else {
+ cds[ncds].from = row;
+ cds[ncds].cond = '!';
+ cds[ncds].bound = -1;
+ cds[ncds].to = cadd(d, ss);
+ ncds++;
+ }
+ ss = strtok(NULL, ",");
+ }
+}
+
+stack_u64 *parse(dict_t *d, size_t *nconds, cond_t **r, char **lines,
+ size_t nlines) {
+ size_t i;
+ for (i = 0; i < nlines; i++) {
+ if (strlen(lines[i]) < 2)
+ break;
+ char *sa = strtok(lines[i], "{}");
+ size_t row = cadd(d, sa);
+ char *ss = sa;
+ while (ss != NULL) {
+ ss = strtok(NULL, "{}");
+ parseconds(r[i], d, ss, row);
+ }
+ }
+
+ *nconds = i;
+
+ stack_u64 *values = malloc(4 * sizeof(*values));
+ for (i = 0; i < 4; i++)
+ stack_u64_init(&values[i]);
+
+ for (i = *nconds + 1; i < nlines; i++) {
+ char *cp = lines[i];
+ uint64_t tmp;
+ cp = sread_next_u64(&tmp, cp);
+ stack_u64_push(&values[0], tmp);
+ cp = sread_next_u64(&tmp, cp);
+ stack_u64_push(&values[1], tmp);
+ cp = sread_next_u64(&tmp, cp);
+ stack_u64_push(&values[2], tmp);
+ cp = sread_next_u64(&tmp, cp);
+ stack_u64_push(&values[3], tmp);
+ }
+
+ return values;
+}
diff --git a/day19/common.h b/day19/common.h
@@ -0,0 +1,28 @@
+#ifndef COMMON_H_
+#define COMMON_H_
+
+#include <assert.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <dict.h>
+#include <reading.h>
+#include <stack_u64.h>
+
+#define MAX_NEQ 512
+
+typedef struct {
+ size_t from;
+ size_t to;
+
+ size_t entry;
+ char cond;
+ int64_t bound;
+} cond_t;
+
+stack_u64 *parse(dict_t *d, size_t *nconds, cond_t **r, char **lines,
+ size_t nlines);
+void print_dict(dict_t *d);
+
+#endif
diff --git a/day19/exinput b/day19/exinput
@@ -0,0 +1,17 @@
+px{a<2006:qkq,m>2090:A,rfg}
+pv{a>1716:R,A}
+lnx{m>1548:A,A}
+rfg{s<537:gd,x>2440:R,A}
+qs{s>3448:A,lnx}
+qkq{x<1416:A,crn}
+crn{x>2662:A,R}
+in{s<1351:px,qqz}
+qqz{s>2770:qs,m<1801:hdj,R}
+gd{a>3333:R,R}
+hdj{m>838:A,pv}
+
+{x=787,m=2655,a=1222,s=2876}
+{x=1679,m=44,a=2067,s=496}
+{x=2036,m=264,a=79,s=2244}
+{x=2461,m=1339,a=466,s=291}
+{x=2127,m=1623,a=2188,s=1013}
diff --git a/day19/input b/day19/input
@@ -0,0 +1,707 @@
+mxd{s>519:A,A}
+mjc{s>2178:R,R}
+fn{s<595:A,x<2401:R,m<3068:A,A}
+kvf{a<3294:R,s<1556:dxz,ks}
+hds{s>2669:R,s>2466:A,x>551:R,R}
+gs{m<360:zd,gx}
+grj{m<1473:A,x<458:R,R}
+kp{s>435:R,R}
+smm{s<3630:R,s>3642:R,R}
+kph{m>1270:A,x>1603:A,m>1212:A,A}
+nds{a>121:A,a>56:R,R}
+ctd{a>1355:A,s<3418:A,s>3430:R,fbg}
+hm{s<3783:R,a<915:A,s<3899:A,A}
+fd{x>1077:R,s<1020:dm,s<1296:A,nhn}
+vn{s>2595:A,s<2499:R,x<2900:R,xp}
+hcd{a>861:kb,s>2244:lb,R}
+dtz{s<2555:R,A}
+mfl{a>1580:klc,R}
+hv{x<2511:R,x>2650:R,R}
+pzq{m<957:rtd,m<1311:R,s>736:vsr,vz}
+jbh{x<1440:R,s>2176:A,R}
+bp{s<2134:R,a>423:A,a<148:A,A}
+nhn{a<1115:A,A}
+qk{a<940:mms,m<3456:A,dg}
+zrz{x>3467:tjz,a<3096:hmq,bnj}
+cpz{m<3765:A,m>3881:R,x>3232:A,R}
+kb{x<589:R,x<854:A,R}
+xss{s>2931:tx,s>2577:A,ptf}
+ljb{a>1580:A,a>1518:A,A}
+bl{a<1603:nps,bdf}
+gd{x>2903:rvd,m>2692:qqz,s<1587:tcm,xhj}
+cnm{x>3317:A,a<2446:A,a>2972:A,A}
+dxd{x>3626:A,x>3578:A,x<3558:R,R}
+kt{a<2459:jg,a<3181:pg,x>1274:mtm,zh}
+qr{s>1547:R,x>2576:R,x<2219:A,R}
+tbb{s>3694:A,m>3236:tgn,dc}
+mjx{s>1488:A,x>2441:R,rq}
+slz{s>3682:kng,A}
+xl{a>2352:R,R}
+zn{x>499:R,m>520:A,A}
+vc{x>2938:R,a>1346:A,A}
+nc{x>2666:dvd,xzx}
+pml{m<2772:ml,nsx}
+rtf{a<325:A,a<520:A,m>1148:R,A}
+rd{m>1726:kn,a>1532:vn,x<2966:brb,xfh}
+kkh{s>1789:A,A}
+jsj{a>1984:lch,m>2372:xss,hk}
+cnr{s<1910:R,m>3349:R,A}
+dxz{s>1400:A,R}
+sh{s<3261:R,m>337:A,m<262:A,R}
+tfm{a<1214:R,m>527:A,x>1422:A,R}
+fq{m<887:R,m<1036:A,m<1112:R,A}
+fl{s>1735:R,s>1721:A,R}
+sfp{m<2598:A,s<2962:A,A}
+hff{m<3389:pnx,s>1790:jnf,qk}
+rbf{m<291:mb,x<1523:dtz,mp}
+db{m<859:A,A}
+ck{x>2345:A,A}
+lgr{x<3690:dxd,A}
+xp{x>3015:R,a>2631:R,A}
+vtv{m<2179:hcd,gl}
+tq{x>2684:A,x>2429:R,m<2407:npq,R}
+ppc{x<2658:A,m>2166:A,R}
+hk{s<2925:ck,A}
+gqp{x<2320:R,a>2596:A,m<2142:R,A}
+pgj{s<3781:kdt,m>2547:nq,a<1362:xfb,rz}
+mp{a>2394:dfx,A}
+vh{a<376:R,R}
+hb{m>3496:R,m<3482:R,s<1786:A,A}
+zp{x>502:hm,blv}
+gf{s>3664:A,m>3751:A,A}
+tg{m<1097:A,s<2083:gv,A}
+cz{m>948:A,x>1835:hp,A}
+fqr{a<3412:lp,mld}
+bc{m>770:R,s<234:hx,zhv}
+mcz{m<399:ndb,sf}
+pb{s<3639:vg,xv}
+drn{x<2337:jzj,a>2468:ps,s<1692:rh,sjn}
+lxd{a>1948:jzc,sfp}
+ktn{x>3118:rf,x<2569:rcn,a<1483:qmv,bl}
+kbn{s<1896:A,A}
+sgg{a<3024:md,x<3474:cpz,s>1888:nf,gcs}
+zz{x>2261:fn,a<2097:jlc,a<3041:R,mxd}
+rhc{s<1222:jfr,m<717:zsg,x<3086:dnh,lt}
+gz{s>1877:hjf,x>2844:A,m<1240:R,csz}
+gj{a<3514:R,krn}
+dmb{x<3801:lgr,lzf}
+mg{a<826:A,s>2329:A,A}
+rg{a<3454:R,m<3961:R,R}
+tdn{a>636:A,x>2674:A,a<418:A,A}
+pk{s>1111:A,a<1136:R,A}
+jj{a<693:A,s<2070:R,x<3277:R,A}
+fcm{s<1672:A,a>2998:R,R}
+xsx{x>1604:pk,x>1286:pzl,fd}
+mzg{m>3808:A,s>1865:gb,R}
+fg{a>2650:dh,a<1401:R,a>2074:R,A}
+tz{a>1106:cx,m>3282:btl,s>2141:qj,df}
+ll{s>3709:ppc,m>2043:hmt,s<3670:R,A}
+cx{s<2250:A,s>2317:rs,a<1440:pnm,ljb}
+fgz{s>1826:A,A}
+gx{x>1640:R,x<1380:A,x>1501:A,R}
+mxx{x<1623:R,a<1522:R,m>996:R,R}
+pmr{s>2942:A,x<3819:A,a>2520:R,R}
+sj{a<406:A,A}
+nhv{a<2366:nx,x>3240:A,fl}
+hf{s>1092:jml,a<1133:R,s>902:ghr,A}
+fvm{s>2186:R,a<746:pxt,R}
+zq{s>2330:R,A}
+jzj{s>1843:cnr,x<2093:znr,m>3323:A,hvr}
+bpc{a>3794:R,R}
+tkk{m>2092:R,R}
+rb{x>2846:R,R}
+ql{a>1897:R,R}
+gv{m<1131:A,x<1429:A,x>1526:R,A}
+ncr{s<2301:R,R}
+xv{s<3816:ll,s<3897:rbn,st}
+hnd{a<2278:nns,m<870:R,A}
+bqz{s<2364:A,R}
+fp{s<726:rl,kt}
+ltb{a>1269:A,x>777:A,x<658:A,R}
+pxt{s>1993:A,R}
+zx{a>796:R,A}
+jvs{a<3103:A,s<1870:A,A}
+rsm{s>2707:A,x<835:R,A}
+xpx{a>607:R,s<2014:A,A}
+fqk{m<912:A,A}
+nrx{x<376:kbn,vs}
+brb{m>708:cxk,R}
+gcs{s<1809:A,s>1841:R,m<3834:A,R}
+rkk{s<1770:A,m>3321:A,A}
+fr{a>2675:A,s>522:A,R}
+xfb{s>3857:lfr,a<683:vh,s>3818:dr,nlf}
+ddk{a>1547:rr,jk}
+rvf{s<1673:mrn,x>1239:kf,jnk}
+dvp{a<3744:hs,s<2210:R,s<2319:A,txk}
+vx{x>1553:ht,x<1391:A,A}
+ml{s>2170:vcq,rb}
+mbl{m>3905:A,A}
+qfs{m<1155:nhz,hh}
+mkc{m<2142:R,s>3264:R,A}
+xj{a<1868:R,x>3465:R,R}
+bj{m<3328:R,R}
+hp{a<2543:R,x<1887:R,s<2030:R,R}
+jzc{x<2727:A,x<2778:R,R}
+kch{m>3627:R,R}
+bsl{x>3681:R,s<1591:A,R}
+nps{a<1538:A,R}
+dsc{a>714:A,m<374:R,a>341:R,A}
+tm{a>2000:xqv,a>1222:rgk,rhc}
+gnv{x>752:fqr,s<3125:zhc,xjg}
+rr{a<3101:R,A}
+lx{s>3010:bz,mfl}
+sjn{x<2761:hv,s>1824:bj,x<2926:A,rkk}
+rc{s<2605:qmc,m<869:R,m<895:R,fqk}
+xct{m>2544:R,A}
+mq{a<1980:A,m>1455:R,x<3654:A,A}
+lp{a>2759:A,s>2867:A,R}
+hsv{x<2410:R,a<1560:A,R}
+jg{m>2929:lkf,x>1020:xhc,s>1167:jgp,A}
+mrl{m<1092:A,A}
+vg{s>3504:sps,x>3181:tr,s<3449:ctd,hfg}
+sv{x<2066:R,a<849:R,a<1058:A,R}
+srk{a>1926:R,a>896:mc,jdq}
+tj{x>1519:R,R}
+fbg{a>773:R,a<489:R,m<2598:R,R}
+fj{m>1112:A,A}
+bb{m<726:A,R}
+fm{x<1701:R,a<2535:A,R}
+npq{a<3739:A,x<2236:A,R}
+zj{x>2673:jcd,zrb}
+qq{s<1726:A,s>1888:R,s<1833:R,R}
+zhv{a<1161:A,a<1955:R,m>297:A,R}
+lt{a>784:tpp,s>1791:nmv,m<1272:grb,ssv}
+gt{m>1318:A,R}
+xhs{m<2996:R,m<3102:A,A}
+bjb{m>936:lr,x>1510:rc,hnd}
+rtd{s>556:A,m>564:A,R}
+qqz{s<1611:A,m>2941:A,pt}
+pnn{s<3780:R,s>3867:A,a>1248:zn,R}
+jlc{a<772:A,m<2926:R,s<614:A,A}
+zrb{s>750:nrc,s<378:lcv,zz}
+vfg{s<2430:R,cms}
+cms{a>3222:A,m>583:R,x<406:A,A}
+vcq{m>2434:A,a>2745:R,s<2311:A,R}
+xrv{a<1662:qgp,x<3696:xg,tgr}
+hxt{s>1068:fsf,x>3036:xj,s<679:sdh,cbc}
+srt{m>2894:dvp,s<2153:tq,s>2284:scj,nhs}
+mpd{a>628:R,a<214:A,x<1355:A,A}
+rml{a<504:A,A}
+tb{m>3398:R,s>1543:A,a<3609:A,R}
+ptr{m>688:R,a<948:R,s<634:A,A}
+klc{x<1710:R,a<2591:A,m>3078:A,R}
+ks{s<1651:R,x>2702:A,s>1697:R,A}
+xhc{s<1351:R,R}
+fh{s<3401:kq,pb}
+rqn{m<1266:mpd,x>1369:R,gt}
+cs{x>564:mm,x<218:tlj,gqv}
+jt{x>2871:A,m<3444:A,a<1753:R,A}
+hjf{m>1046:A,m>370:A,s>1968:A,A}
+nrc{m<2804:lm,xq}
+sz{x>2574:A,R}
+qbv{m>249:A,s>574:A,R}
+pfp{m>375:R,A}
+btq{a<998:flp,m>3485:prd,bqz}
+gp{a<2326:dp,ms}
+pfl{s<1868:R,a<1886:R,a<1950:R,R}
+spt{m<1224:pnn,m>1788:zp,lft}
+jfr{a<775:pzq,fz}
+lc{s<1767:qv,x<3091:mzg,a>2124:sgg,jgb}
+jnk{a>2431:gnv,s>2865:kfx,kv}
+md{m<3718:A,A}
+bdf{x>2867:R,m>409:R,m<263:R,R}
+pzl{s>745:fk,m<858:tfm,pv}
+tp{a<2486:A,x<3506:A,s<2745:R,A}
+krn{m>1248:R,x<3069:R,a>3769:R,R}
+nth{m>897:grj,gkv}
+mtm{m>3187:kch,x<1564:R,vcj}
+nlf{a>980:A,s>3799:A,x<675:A,R}
+kv{m<1769:nth,m<2749:vtv,btq}
+ns{x<3280:R,s>2163:A,m<3814:A,A}
+dt{a<1402:A,s>1581:A,R}
+rcd{s<667:R,a>1341:A,A}
+lf{m>1315:R,a<599:A,sv}
+vf{m<3625:zlg,x>887:gf,m<3771:A,A}
+bst{m>2531:R,x>975:A,s>3379:A,R}
+nxj{a<2198:R,A}
+kng{a>1758:A,x<811:A,s<3709:A,A}
+lkf{m<3494:A,x<1200:A,s<1219:A,A}
+sps{s<3575:scm,x>3109:mq,hsv}
+pvf{m>143:fm,s>3306:R,qp}
+zm{x<3406:R,s>1900:A,A}
+ltd{s>3415:nxj,A}
+kg{m>620:R,x<1505:mnf,A}
+zsg{x<3003:rt,mcz}
+rvd{m<2705:cnm,a>2203:jr,m>2882:xhs,R}
+hl{s>3663:R,A}
+tld{a>1063:A,a>955:A,x<2857:A,A}
+rbn{s>3864:pq,m<1667:xd,R}
+jsl{x>1423:A,R}
+sx{m>103:A,a>1372:A,a<646:A,R}
+zd{x<1679:th,s>3668:kdv,R}
+tng{s>3386:A,s>3265:A,R}
+ndb{s>1881:R,A}
+pbc{m>2958:A,a<161:R,x>2337:R,R}
+bz{x<1717:nt,s>3541:A,R}
+pg{x<748:A,x<1189:A,R}
+qj{x<2963:ncr,s<2293:A,zg}
+pq{m>1496:A,x<3163:A,s<3885:A,R}
+ps{a<3453:bbm,x>2688:cvs,s>1696:bpc,A}
+vr{s<354:R,x>3463:A,A}
+txk{m<3329:R,R}
+pd{a>3073:A,m<2888:R,a>2488:R,R}
+cvs{a<3678:A,m<3350:A,A}
+rfd{a>2749:gj,s<2064:gz,s<2237:dv,lhj}
+rs{s>2347:R,A}
+xgz{x<2320:R,m>2708:jvs,m>2392:sft,A}
+vsv{x<525:bh,s>3758:ltb,a<901:vf,slz}
+fb{x<2194:A,A}
+mb{m>156:A,sx}
+mbk{s>626:R,x<3367:A,a<1710:R,A}
+hfg{m<2134:A,ls}
+vs{m<2976:R,a>3344:A,s>1902:R,A}
+flp{a>345:R,x<610:nds,a<206:zq,bq}
+zvh{s<1707:gd,x<2927:vmc,x>3534:dmb,kk}
+sdh{x<2625:A,x<2851:R,x<2954:hjd,R}
+mkh{s>91:R,A}
+jcd{x>3192:qrj,lpp}
+prd{s<2306:R,x<527:sd,m<3790:A,A}
+nhk{a>2558:nr,x>947:xsx,jq}
+bs{x>872:xnk,R}
+mj{s>3566:vx,m>220:vxs,pvf}
+dvd{s<1171:cd,zb}
+dnh{s<1836:mjx,x>2503:fvm,x<2148:lf,cl}
+rp{a<1064:A,R}
+jq{s<668:bc,x>630:sk,hf}
+bxx{x<698:R,m>450:R,x>895:R,R}
+ffr{s>2956:A,x>3052:R,a>2253:R,vc}
+skc{a<1537:R,A}
+cj{x>3013:R,R}
+rh{m<3295:gc,s<1617:dt,a<1261:tdn,A}
+zmq{m>418:A,x>2611:A,x<2507:R,A}
+tnb{a<1929:R,s>2762:A,a<2077:A,A}
+nmv{x>3526:R,m<1470:mrl,a>511:jj,R}
+nhz{s>2629:tj,x<1585:tg,hr}
+klt{m>693:fdc,a>3064:qbv,a<2475:pfp,sm}
+sk{a<1384:nrb,m>925:A,A}
+tf{s>3306:A,A}
+zb{m>1510:A,a>1550:R,A}
+flb{s<315:A,s<429:R,x>3549:A,R}
+sm{x>2731:A,x>2377:zmq,fb}
+rmc{m<706:kg,s<3092:jm,x>1635:ltd,ddk}
+rhg{x<979:fj,a>3057:R,qsp}
+qmc{a<2647:A,x<1729:A,R}
+btl{m>3623:ns,A}
+fvf{a>1549:A,m>2971:A,R}
+lzf{m<2457:hfs,a>1458:pd,A}
+hvr{x<2204:R,s<1629:A,A}
+xkv{m>2738:A,m>2301:A,x<3267:A,R}
+nrb{s<1224:A,s>1500:R,R}
+cd{a>1580:A,R}
+ghr{x<381:A,x<518:A,a<2082:A,R}
+fsf{m<414:R,pfl}
+ms{a<3420:A,vb}
+jgb{m<3826:R,s<1908:R,mbl}
+qvc{x>742:R,x<658:A,A}
+qgp{m>2561:R,m>1286:A,m<635:dsc,A}
+hjd{s>239:R,a<1869:A,x<2912:R,A}
+ld{m<1560:R,m>1848:A,a>2812:bnp,cn}
+dg{s<1695:R,R}
+jvg{a<3844:A,R}
+vzk{a<1812:tz,a<3244:pml,srt}
+qbp{s>3332:hl,m<962:R,m>988:ts,A}
+tpp{x<3399:R,m<1206:fq,a>977:A,qkf}
+bnp{x<3279:R,R}
+hh{x>1536:qmf,s<2606:llk,a>1794:qrd,rqn}
+lfr{s<3907:R,R}
+hx{s<136:A,s<191:A,a<1049:R,A}
+st{s<3963:R,a<1925:A,a<2975:ch,tkk}
+hr{a<2659:A,m<1091:R,m<1115:hbt,R}
+cbc{s>927:R,s>822:ql,A}
+bbm{m<3364:A,x>2593:A,R}
+htt{m>2896:A,s<2769:A,x>234:jb,A}
+xqv{s<1321:klt,s>1763:rfd,jh}
+hbn{a<3438:gqr,db}
+rpb{x>2821:R,s>968:R,s>513:A,A}
+kdv{x<1793:A,A}
+jr{s<1637:R,s<1661:R,A}
+scj{s>2329:A,a>3569:jvg,R}
+csz{m>1654:R,s<1822:A,s<1857:R,R}
+nq{s<3919:A,A}
+dc{a>3341:A,x<299:A,m>2827:A,R}
+zs{x<513:kp,a<2462:A,qvc}
+dmt{m<855:R,x<1459:R,R}
+kn{s>2507:A,jv}
+mc{a>1432:A,R}
+pnx{x>3628:R,m<3272:fgz,a<1141:A,A}
+mrn{m>2067:fp,nhk}
+sf{a>681:R,s<1871:A,R}
+qcj{s>1900:A,a>503:A,a<306:pbc,sj}
+xjg{m<2126:hgq,tbb}
+vxn{a<2585:R,s>1926:jbh,dmt}
+nns{s>2674:R,A}
+qmf{x<1694:kph,m<1255:khs,x<1873:R,hd}
+gqv{m<2093:njt,tf}
+mh{s<3488:A,a<1691:R,R}
+znr{x<2042:R,R}
+zf{s>3085:mk,x>2867:ffr,lxd}
+bq{a<276:A,A}
+vxs{x<1573:tng,s<3367:sh,m<365:sb,ntj}
+in{x<1964:rvf,nz}
+jk{m<783:R,A}
+xg{s<3030:tp,mkc}
+ktt{x>1621:cz,m<901:vxn,fg}
+nz{s>2383:fh,m>2006:hdk,tm}
+ts{a<3384:R,s>3147:R,x<1720:R,R}
+nt{s>3568:R,x>1597:R,R}
+tvz{x>1752:A,A}
+rt{s<1808:nl,x>2618:A,m<473:bp,xpx}
+dpk{m<2452:R,R}
+vp{m>875:R,m<403:R,x<3856:A,A}
+nh{s<2072:R,a<688:R,m<2798:A,A}
+hgq{m<991:A,A}
+pts{x<1515:gp,lx}
+jml{a<1169:A,A}
+tx{x>2304:R,R}
+rcn{a>1547:dss,R}
+xhj{m>2445:R,R}
+th{s<3511:A,a>859:A,x<1514:R,R}
+vz{s>426:A,A}
+gkv{a>1349:bxx,s<2201:A,A}
+zh{x>827:R,x>374:A,R}
+fk{s<1359:R,R}
+jlf{m>553:rmc,s<3172:rbf,a>1384:mj,gs}
+lm{m<2274:R,m>2567:R,A}
+mms{s<1666:A,R}
+jgp{s>1460:A,m<2389:A,R}
+mk{a<2190:zx,x>2929:A,R}
+sft{x<2599:R,s>1841:R,x<2724:R,R}
+xzx{m>1160:gnt,vv}
+blv{a>1485:A,s>3754:A,R}
+pgf{a<32:R,R}
+njt{s<3288:R,m>776:R,A}
+tr{s>3459:mh,A}
+tlj{s>3128:rp,ddt}
+jhz{x>2072:R,R}
+jb{x<329:A,m<2444:R,m>2696:A,R}
+gl{s<2413:A,x>600:rsm,R}
+dh{a<3462:R,s>2042:A,R}
+lft{m<1450:A,s>3773:A,s<3663:smm,A}
+pnm{a>1315:R,x>3142:A,x<2517:R,R}
+rq{s<1359:R,s<1424:R,x<2279:R,R}
+nsx{a<2609:mjc,s<2240:A,a<2883:R,R}
+dm{s>528:A,s>211:R,s<125:A,A}
+rgk{m>703:nc,a<1731:ktn,hxt}
+df{a>447:nh,a>167:A,a>62:dpk,pgf}
+xcz{s<1073:R,a>3114:R,R}
+tjz{x>3822:A,m<3377:kkh,m>3470:hb,qq}
+ch{a<2397:A,m<1402:A,A}
+fdc{x<2650:R,s>585:xcz,flb}
+hbt{m>1103:A,m<1096:A,R}
+llk{x<1394:njh,s>2044:sr,a>2453:R,zpc}
+rz{m<2451:tn,R}
+kk{s>1825:vcx,s<1776:nhv,srk}
+pv{x>1448:R,x<1372:R,a<1453:R,R}
+jh{m<1018:kvf,ld}
+nx{m>2411:A,A}
+sb{x>1750:R,m<273:R,R}
+jm{a>1824:R,m>784:A,m>756:mg,A}
+ls{x>2462:A,a>2579:A,a<1281:R,R}
+cn{s>1580:A,R}
+sd{s>2497:A,R}
+grb{m<952:bsl,A}
+gqr{s<3365:R,R}
+lch{a<3078:gqp,a<3493:zjd,x<2193:mnp,A}
+rl{x<1045:zs,a>2417:zr,xvr}
+jdq{x>3267:A,s>1799:A,a>426:A,R}
+vb{m>2271:R,R}
+lr{m<987:pm,m>1001:A,a<2338:mxx,R}
+zg{a>638:A,R}
+tcm{m<2415:qr,s>1537:A,s>1522:A,gzx}
+zlg{x>927:A,R}
+nhs{m<2318:A,a<3708:A,s>2209:A,R}
+hfs{m>2160:R,s<1821:R,A}
+pt{x>2456:R,m>2791:R,R}
+qrd{s>3510:A,jsl}
+ssv{m>1662:R,m>1485:A,a>434:R,A}
+vsr{s>958:A,x<2658:R,R}
+dr{s<3834:R,x>459:A,R}
+hnz{a<2548:ggc,m>898:qbp,hbn}
+cl{m<1339:R,A}
+gnt{a>1526:A,m<1641:A,R}
+zhc{m<1599:vfg,s<2173:nrx,x>408:hds,htt}
+bh{m<3521:R,R}
+dp{a>1160:tnb,m>2742:A,A}
+hmt{s<3683:A,m<3306:R,R}
+qv{a<2401:R,m<3796:fcm,m<3902:R,rg}
+lcv{s>190:fvf,x>2218:kj,a<1608:A,jhz}
+xfh{s<2582:A,x>3082:R,a<682:rtf,bb}
+hs{s>2202:A,A}
+tlz{a<1339:A,x<3492:A,R}
+xz{m<3730:R,s<288:R,A}
+tgr{m>2513:pmr,vp}
+njh{a>1699:R,R}
+qrj{x>3725:R,x>3418:R,x>3312:mbk,xkv}
+lhj{x>2846:A,m>688:xl,mqq}
+mm{x<811:R,s<3133:R,m>1758:bst,R}
+ddt{x<144:R,m<2631:R,s<2963:A,R}
+tgn{m<3525:A,m<3732:R,A}
+ggc{x<1595:A,A}
+mnp{x>2076:A,a>3706:A,a>3581:A,R}
+kq{x>3221:xrv,x<2561:jsj,s>2750:zf,rd}
+jv{m>2751:R,A}
+zr{m<3280:A,a>3115:xz,s<260:R,fr}
+khs{x<1821:R,A}
+vmc{a>1367:xgz,m<2458:sz,m>2809:qcj,jlr}
+ds{s>2997:hnz,s<2376:ktt,bjb}
+hd{s<2994:R,m<1314:R,A}
+dfx{s<2255:R,A}
+lb{m<1935:R,R}
+mld{s<2852:R,s<3570:R,A}
+kfx{s<3568:cs,m<2259:spt,m<2931:pgj,vsv}
+ntj{a<2847:R,s<3467:R,m<455:A,R}
+lpp{m>2971:jt,s>772:lcd,s>441:R,cj}
+nm{s>3697:R,x>680:R,A}
+qmv{m>420:rpb,x>2803:R,s>1192:R,rcd}
+gzx{m>2575:R,m>2502:R,x<2559:R,A}
+ht{a<2585:R,A}
+xnk{s>314:R,a>3184:A,R}
+zpc{m<1253:R,s<1810:A,s<1890:R,R}
+kf{m>1348:pts,m<831:jlf,m>1015:qfs,ds}
+jlr{m<2643:R,s>1881:rml,R}
+sr{s<2325:R,s<2491:R,A}
+gc{s<1618:A,A}
+dss{s>1521:A,a<1652:R,R}
+rf{s>880:A,a>1402:vr,tlz}
+vv{s>1399:A,s<766:R,x<2276:A,A}
+vcj{m<2719:A,m<2895:R,m>3075:R,R}
+nl{a>645:R,s>1428:A,x<2406:A,A}
+hmq{x<3189:R,A}
+xvr{x>1530:tvz,s<307:R,R}
+kdt{m>2670:skc,a>1618:nm,R}
+fz{m<1112:ptr,s>460:A,s>223:tld,mkh}
+qkf{m>1594:R,A}
+zjd{x>2246:A,R}
+cxk{s>2529:A,x<2803:R,A}
+vcx{s<1906:xct,R}
+tn{x>494:A,m<2336:R,R}
+qp{x<1627:A,m>79:A,R}
+dv{m<676:A,a<2495:A,R}
+kj{s<79:R,m>3174:A,x<2409:A,R}
+xd{x>2885:A,A}
+bnj{s>1720:R,s<1599:tb,A}
+hdk{s<1511:zj,s>2012:vzk,m<3167:zvh,bqs}
+bqs{m>3533:lc,x<3049:drn,a<2535:hff,zrz}
+scm{x>3137:A,a<1743:R,R}
+mnf{m<584:A,R}
+jnf{m<3441:zm,R}
+ptf{m<3310:R,R}
+pm{a>2017:A,A}
+nr{s>779:rhg,bs}
+mqq{m<354:R,s>2296:R,m<538:R,A}
+nf{x<3798:A,x>3904:A,A}
+qsp{a>2768:R,A}
+lcd{s<1089:R,A}
+xq{a<2663:R,x<2423:R,R}
+gb{s>1963:R,s<1910:R,s>1932:R,A}
+
+{x=167,m=55,a=1771,s=1356}
+{x=181,m=2122,a=368,s=35}
+{x=7,m=82,a=973,s=146}
+{x=403,m=13,a=2480,s=951}
+{x=3462,m=1363,a=155,s=1427}
+{x=2478,m=1629,a=870,s=1846}
+{x=2277,m=2806,a=45,s=1016}
+{x=304,m=3023,a=985,s=2710}
+{x=1030,m=1949,a=1987,s=637}
+{x=1214,m=93,a=103,s=371}
+{x=695,m=194,a=808,s=2631}
+{x=937,m=560,a=1650,s=909}
+{x=591,m=73,a=328,s=201}
+{x=466,m=1081,a=459,s=93}
+{x=971,m=1229,a=136,s=405}
+{x=1928,m=1019,a=358,s=2002}
+{x=1226,m=1802,a=68,s=103}
+{x=218,m=541,a=68,s=2452}
+{x=1254,m=1081,a=104,s=717}
+{x=410,m=312,a=3840,s=5}
+{x=39,m=1983,a=1174,s=650}
+{x=2166,m=358,a=209,s=1963}
+{x=1084,m=88,a=1945,s=202}
+{x=1118,m=214,a=964,s=109}
+{x=1456,m=263,a=665,s=755}
+{x=1613,m=329,a=520,s=1608}
+{x=306,m=717,a=360,s=2287}
+{x=2054,m=677,a=3554,s=43}
+{x=1347,m=272,a=2322,s=227}
+{x=845,m=401,a=1148,s=267}
+{x=457,m=1646,a=3093,s=60}
+{x=288,m=385,a=9,s=475}
+{x=2578,m=769,a=1043,s=103}
+{x=1595,m=772,a=32,s=1172}
+{x=234,m=481,a=334,s=1066}
+{x=1861,m=197,a=866,s=2379}
+{x=217,m=420,a=2923,s=471}
+{x=986,m=3304,a=5,s=520}
+{x=793,m=736,a=490,s=607}
+{x=1568,m=310,a=45,s=632}
+{x=469,m=1521,a=931,s=1247}
+{x=2279,m=2275,a=659,s=1259}
+{x=276,m=478,a=1563,s=2412}
+{x=3147,m=2306,a=184,s=410}
+{x=2325,m=2211,a=75,s=2725}
+{x=1789,m=217,a=710,s=451}
+{x=294,m=1241,a=1904,s=296}
+{x=712,m=1127,a=98,s=1173}
+{x=293,m=1902,a=925,s=1712}
+{x=1134,m=169,a=2106,s=386}
+{x=2465,m=1452,a=593,s=666}
+{x=2301,m=472,a=1948,s=1278}
+{x=1222,m=610,a=1653,s=378}
+{x=396,m=484,a=189,s=897}
+{x=1113,m=807,a=3134,s=1041}
+{x=483,m=284,a=956,s=46}
+{x=471,m=290,a=154,s=40}
+{x=62,m=2156,a=56,s=54}
+{x=934,m=57,a=1516,s=2947}
+{x=53,m=246,a=828,s=302}
+{x=2368,m=1025,a=289,s=1195}
+{x=4,m=1010,a=55,s=3303}
+{x=344,m=490,a=1308,s=1740}
+{x=464,m=225,a=2385,s=471}
+{x=3369,m=2507,a=62,s=495}
+{x=1432,m=2375,a=1,s=20}
+{x=14,m=462,a=559,s=723}
+{x=118,m=1038,a=12,s=362}
+{x=209,m=1489,a=1692,s=297}
+{x=364,m=1340,a=499,s=103}
+{x=710,m=958,a=1587,s=2595}
+{x=902,m=1749,a=279,s=835}
+{x=1929,m=1622,a=1379,s=2167}
+{x=1055,m=8,a=2965,s=3432}
+{x=185,m=2467,a=1169,s=273}
+{x=2638,m=2352,a=518,s=41}
+{x=666,m=538,a=1586,s=956}
+{x=33,m=40,a=2217,s=132}
+{x=44,m=1095,a=208,s=130}
+{x=2392,m=1825,a=619,s=755}
+{x=3163,m=258,a=144,s=3259}
+{x=680,m=362,a=1286,s=384}
+{x=539,m=2592,a=205,s=3243}
+{x=264,m=363,a=1008,s=2371}
+{x=48,m=976,a=168,s=237}
+{x=231,m=551,a=893,s=389}
+{x=554,m=2283,a=2981,s=471}
+{x=434,m=215,a=872,s=58}
+{x=1483,m=1540,a=3479,s=1527}
+{x=376,m=1806,a=272,s=1004}
+{x=2692,m=60,a=1460,s=1300}
+{x=243,m=679,a=693,s=820}
+{x=1736,m=2489,a=239,s=1635}
+{x=580,m=1740,a=347,s=751}
+{x=1044,m=829,a=1190,s=714}
+{x=1729,m=451,a=329,s=994}
+{x=3015,m=555,a=1594,s=440}
+{x=330,m=1177,a=1038,s=1301}
+{x=1097,m=73,a=631,s=160}
+{x=1587,m=2301,a=108,s=189}
+{x=23,m=400,a=377,s=1195}
+{x=814,m=1336,a=533,s=631}
+{x=340,m=366,a=473,s=2707}
+{x=1904,m=306,a=3361,s=704}
+{x=2085,m=476,a=1417,s=1613}
+{x=3466,m=1381,a=753,s=24}
+{x=1568,m=54,a=229,s=273}
+{x=105,m=31,a=2344,s=1014}
+{x=1686,m=112,a=92,s=27}
+{x=297,m=3335,a=119,s=2812}
+{x=603,m=50,a=1443,s=993}
+{x=1093,m=402,a=1216,s=4}
+{x=2854,m=271,a=1232,s=918}
+{x=2583,m=3016,a=61,s=1070}
+{x=2312,m=16,a=2531,s=621}
+{x=1274,m=2156,a=309,s=1886}
+{x=298,m=13,a=1344,s=90}
+{x=1111,m=962,a=531,s=1474}
+{x=286,m=2539,a=196,s=537}
+{x=634,m=575,a=1300,s=836}
+{x=653,m=2299,a=2516,s=2252}
+{x=1897,m=815,a=312,s=12}
+{x=108,m=622,a=425,s=605}
+{x=2906,m=387,a=730,s=2323}
+{x=3,m=1920,a=727,s=430}
+{x=1525,m=2819,a=1426,s=1662}
+{x=109,m=799,a=318,s=208}
+{x=526,m=1332,a=2025,s=221}
+{x=222,m=1040,a=2630,s=2804}
+{x=69,m=222,a=214,s=2401}
+{x=28,m=1905,a=1349,s=738}
+{x=1309,m=109,a=656,s=1085}
+{x=418,m=113,a=1640,s=1816}
+{x=3359,m=236,a=2,s=23}
+{x=1210,m=595,a=2850,s=1716}
+{x=239,m=103,a=2064,s=74}
+{x=695,m=692,a=1143,s=1811}
+{x=1293,m=915,a=1941,s=566}
+{x=526,m=424,a=180,s=1076}
+{x=142,m=358,a=2591,s=2768}
+{x=2210,m=107,a=15,s=556}
+{x=708,m=544,a=1873,s=1891}
+{x=2495,m=554,a=128,s=23}
+{x=685,m=33,a=1516,s=982}
+{x=423,m=5,a=1000,s=1720}
+{x=2827,m=831,a=746,s=821}
+{x=416,m=68,a=538,s=1106}
+{x=150,m=1049,a=336,s=444}
+{x=121,m=799,a=548,s=145}
+{x=3461,m=3082,a=807,s=1205}
+{x=797,m=347,a=222,s=197}
+{x=1318,m=978,a=2614,s=1001}
+{x=2011,m=1317,a=161,s=1171}
+{x=13,m=204,a=881,s=838}
+{x=1126,m=2843,a=1405,s=277}
+{x=3093,m=796,a=1817,s=34}
+{x=2207,m=408,a=350,s=523}
+{x=1825,m=115,a=957,s=2567}
+{x=402,m=3773,a=2272,s=269}
+{x=393,m=224,a=169,s=109}
+{x=1594,m=28,a=1453,s=851}
+{x=1193,m=3463,a=248,s=3253}
+{x=1760,m=1054,a=361,s=1020}
+{x=2628,m=632,a=953,s=186}
+{x=566,m=965,a=2764,s=1}
+{x=694,m=2976,a=1084,s=128}
+{x=1239,m=29,a=3522,s=713}
+{x=220,m=152,a=708,s=876}
+{x=978,m=803,a=1013,s=43}
+{x=1515,m=927,a=2182,s=1121}
+{x=2695,m=1511,a=1138,s=8}
+{x=168,m=1231,a=176,s=719}
+{x=507,m=125,a=1519,s=2347}
+{x=1419,m=182,a=1705,s=806}
+{x=1673,m=46,a=1494,s=1888}
+{x=243,m=2688,a=251,s=645}
+{x=2502,m=121,a=11,s=499}
+{x=677,m=473,a=503,s=313}
+{x=1337,m=1294,a=796,s=308}
+{x=1002,m=545,a=491,s=1120}
+{x=427,m=2097,a=875,s=1445}
+{x=102,m=1611,a=851,s=299}
+{x=292,m=1248,a=2702,s=1652}
+{x=238,m=2250,a=94,s=455}
+{x=658,m=1188,a=550,s=833}
+{x=12,m=1659,a=511,s=1834}
+{x=601,m=985,a=43,s=591}
+{x=1740,m=1657,a=532,s=854}
+{x=212,m=1432,a=3425,s=16}
+{x=1337,m=7,a=1973,s=1675}
+{x=1734,m=3260,a=933,s=1438}
+{x=220,m=402,a=338,s=169}
+{x=228,m=1134,a=688,s=1626}
+{x=336,m=1293,a=61,s=453}
+{x=68,m=601,a=563,s=2913}
+{x=2261,m=331,a=617,s=1674}
+{x=144,m=107,a=1741,s=665}
+{x=301,m=207,a=2263,s=37}
+{x=1007,m=2727,a=323,s=1823}
+{x=193,m=3683,a=43,s=167}
diff --git a/day19/uppga.c b/day19/uppga.c
@@ -0,0 +1,95 @@
+#include "common.h"
+
+// linear search for indices is really, really terrible,
+// but I just want to get to part b now...
+static inline size_t coi(size_t c, cond_t **co, size_t ncond) {
+ size_t i;
+ for (i = 0; i < ncond; i++) {
+ if (co[i][0].from == c)
+ return i;
+ }
+ return SIZE_MAX;
+}
+
+typedef struct {
+ uint64_t v[4];
+} part_t;
+
+static inline int part_satisfies(part_t x, cond_t c) {
+ switch (c.cond) {
+ case '<':
+ return x.v[c.entry] < (uint64_t)c.bound;
+ case '>':
+ return x.v[c.entry] > (uint64_t)c.bound;
+ default:
+ assert(c.cond == '=');
+ return x.v[c.entry] == (uint64_t)c.bound;
+ }
+}
+
+static inline int check_part_recurse(part_t x, cond_t **co, size_t ncond,
+ size_t current, size_t accepted,
+ size_t rejected) {
+ if (current == accepted)
+ return 1;
+ if (current == rejected)
+ return 0;
+
+ size_t cnt = coi(current, co, ncond);
+
+ size_t j = 0;
+ while (co[cnt][j].bound != -1) {
+ if (part_satisfies(x, co[cnt][j])) {
+ return check_part_recurse(x, co, ncond, co[cnt][j].to, accepted,
+ rejected);
+ }
+ j++;
+ }
+ return check_part_recurse(x, co, ncond, co[cnt][j].to, accepted, rejected);
+}
+
+static inline int check_part(part_t x, cond_t **co, size_t nconds,
+ size_t accepted, size_t rejected, size_t in) {
+ return check_part_recurse(x, co, nconds, in, accepted, rejected);
+}
+
+int main(int argc, char **argv) {
+ char **lines;
+ size_t nlines = readlines(&lines, "input");
+ size_t i, nconds;
+
+ cond_t *co[nlines];
+ for (i = 0; i < nlines; i++)
+ co[i] = malloc(sizeof(*co[i]) * 512);
+
+ dict_t names;
+ dict_init(&names);
+ stack_u64 *v = parse(&names, &nconds, co, lines, nlines);
+
+ // print_dict(&names);
+
+ sd accepted_sd, rejected_sd, in_sd;
+ sd_init_str(&accepted_sd, "A");
+ sd_init_str(&rejected_sd, "R");
+ sd_init_str(&in_sd, "in");
+ size_t accepted = *(size_t *)dict_lookup(&names, accepted_sd);
+ size_t rejected = *(size_t *)dict_lookup(&names, rejected_sd);
+ size_t in = *(size_t *)dict_lookup(&names, in_sd);
+
+ uint64_t add = 0;
+ for (i = 0; i < v[0].nmemb; i++) {
+ part_t tpart;
+ tpart.v[0] = v[0].data[i];
+ tpart.v[1] = v[1].data[i];
+ tpart.v[2] = v[2].data[i];
+ tpart.v[3] = v[3].data[i];
+ if (check_part(tpart, co, nconds, accepted, rejected, in)) {
+ add += tpart.v[0] + tpart.v[1] + tpart.v[2] + tpart.v[3];
+ }
+ }
+
+ for (i = 0; i < nlines; i++)
+ free(co[i]);
+
+ printf("%llu\n", add);
+}
diff --git a/day19/uppgb.c b/day19/uppgb.c
@@ -0,0 +1,389 @@
+#include <assert.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/queue.h>
+
+#include <dict.h>
+#include <reading.h>
+#include <stack_u64.h>
+
+dict_t *names;
+
+#define MAX_CONDITIONS 32
+#define MAX_NBRS 2048
+
+typedef struct {
+ uint64_t bounds[4][2];
+} cond_t;
+
+typedef struct {
+ size_t n;
+ size_t entry[MAX_CONDITIONS];
+ size_t iftru[MAX_CONDITIONS];
+ cond_t condition[MAX_CONDITIONS];
+} cond_list_t;
+
+typedef struct {
+ size_t nnbrs;
+ size_t *nbrs;
+ cond_t *cond;
+} edge_list_t;
+
+static inline size_t add_name(char *name) {
+ sd sdname;
+ sd_init_str(&sdname, name);
+ void *p = dict_lookup(names, sdname);
+
+ if (p != NULL) {
+ return *(size_t *)p;
+ } else {
+ size_t *x = malloc(sizeof(*x));
+ *x = names->nelts;
+ dict_insert(names, sdname, x);
+
+ return *x;
+ }
+}
+
+static inline void parse_end_condition(cond_list_t *res, char *s) {
+ assert(res->n < MAX_CONDITIONS);
+ cond_t v = {
+ .bounds = {
+ {0, UINT64_MAX}, {0, UINT64_MAX}, {0, UINT64_MAX}, {0, UINT64_MAX}}};
+ res->condition[res->n] = v;
+ res->entry[res->n] = SIZE_MAX;
+ res->iftru[res->n] = add_name(s);
+ res->n++;
+}
+
+static inline void parse_mid_condition(cond_list_t *res, char *s) {
+ assert(res->n < MAX_CONDITIONS);
+
+ size_t entry = SIZE_MAX;
+ switch (s[0]) {
+ case 'x':
+ entry = 0;
+ break;
+ case 'm':
+ entry = 1;
+ break;
+ case 'a':
+ entry = 2;
+ break;
+ case 's':
+ entry = 3;
+ break;
+ }
+
+ assert(entry != SIZE_MAX);
+ assert(entry < 5);
+
+ cond_t v = {
+ .bounds = {
+ {0, UINT64_MAX}, {0, UINT64_MAX}, {0, UINT64_MAX}, {0, UINT64_MAX}}};
+ res->condition[res->n] = v;
+
+ uint64_t bound_value;
+ char *cp = sread_next_u64(&bound_value, s);
+ assert(cp[0] == ':');
+ cp++;
+ res->iftru[res->n] = add_name(cp);
+
+ switch (s[1]) {
+ case '>':
+ res->condition[res->n].bounds[entry][0] = bound_value;
+ break;
+ case '<':
+ res->condition[res->n].bounds[entry][1] = bound_value;
+ break;
+ case '=':
+ assert(bound_value > 0);
+ assert(bound_value < UINT64_MAX);
+ res->condition[res->n].bounds[entry][0] = bound_value - 1;
+ res->condition[res->n].bounds[entry][1] = bound_value + 1;
+ break;
+ default:
+ assert(1 == 2);
+ }
+
+ res->entry[res->n] = entry;
+ res->n++;
+}
+
+static inline cond_list_t parse_conds(char *s) {
+ cond_list_t res;
+ res.n = 0;
+
+ char *sa = strtok(s, ",");
+ while (sa != NULL) {
+ if (!strstr(sa, ":")) {
+ parse_end_condition(&res, sa);
+ } else {
+ parse_mid_condition(&res, sa);
+ }
+ sa = strtok(NULL, ",");
+ }
+
+ return res;
+}
+
+static inline cond_list_t parse_line(stack_u64 *linerow, char *line) {
+ cond_list_t r;
+
+ if (strlen(line) < 2) {
+ r.n = SIZE_MAX;
+ return r;
+ }
+
+ char *sa = strtok(line, "{}");
+ size_t row = add_name(sa);
+ sa = strtok(NULL, "{}");
+ while (sa != NULL) {
+ r = parse_conds(sa);
+ sa = strtok(NULL, "{}");
+ }
+
+ stack_u64_push(linerow, row);
+
+ return r;
+}
+
+static inline cond_list_t tail_cond_list(cond_list_t clist) {
+ cond_list_t r;
+ r.n = clist.n - 1;
+
+ size_t i;
+ for (i = 0; i < r.n; i++) {
+ r.entry[i] = clist.entry[i + 1];
+ r.iftru[i] = clist.iftru[i + 1];
+ r.condition[i] = clist.condition[i + 1];
+ }
+
+ return r;
+}
+
+static inline uint64_t mmax(const uint64_t x, const uint64_t y) {
+ return x < y ? y : x;
+}
+
+static inline uint64_t mmin(const uint64_t x, const uint64_t y) {
+ return x < y ? x : y;
+}
+
+static inline void append_list(cond_list_t *r, cond_list_t *a) {
+ assert(r->n + a->n <= MAX_CONDITIONS);
+
+ size_t i;
+ for (i = 0; i < a->n; i++) {
+ r->entry[r->n] = a->entry[i];
+ r->condition[r->n] = a->condition[i];
+ r->iftru[r->n] = a->iftru[i];
+ r->n++;
+ }
+}
+
+static cond_list_t exclusive_conditions(cond_list_t clist, cond_t base) {
+ if (clist.n == 1) {
+ assert(clist.entry[0] == SIZE_MAX); // end condition
+ cond_list_t ret;
+ ret.n = 1;
+ ret.condition[0] = base;
+ return ret;
+ }
+
+ size_t entry = clist.entry[0];
+ cond_list_t tail = tail_cond_list(clist);
+ cond_t head = clist.condition[0];
+
+ cond_t andro = base;
+ int halist = 0;
+ cond_list_t alist;
+ int hblist = 0;
+ cond_list_t blist;
+ andro.bounds[entry][0] = mmax(base.bounds[entry][0], head.bounds[entry][0]);
+ andro.bounds[entry][1] = mmin(base.bounds[entry][1], head.bounds[entry][1]);
+
+ if (head.bounds[entry][0] != 0) {
+ // recurse a
+ halist = 1;
+ cond_t nbase = base;
+ nbase.bounds[entry][0] = base.bounds[entry][0];
+ nbase.bounds[entry][1] =
+ mmin(base.bounds[entry][1], head.bounds[entry][0] + 1);
+ alist = exclusive_conditions(tail, nbase);
+ }
+
+ if (head.bounds[entry][1] != UINT64_MAX) {
+ // recurse b
+ hblist = 1;
+ cond_t nbase = base;
+ nbase.bounds[entry][1] = base.bounds[entry][1];
+ nbase.bounds[entry][0] =
+ mmax(base.bounds[entry][0], head.bounds[entry][1] - 1);
+ blist = exclusive_conditions(tail, nbase);
+ }
+
+ cond_list_t ret;
+ ret.n = 1;
+ ret.condition[0] = andro;
+
+ if (halist) {
+ // append alist to ret
+ append_list(&ret, &alist);
+ }
+
+ if (hblist) {
+ // append blist to ret
+ append_list(&ret, &blist);
+ }
+
+ return ret;
+}
+
+static inline void add_edge(edge_list_t *rgraph, size_t from, size_t to,
+ cond_t cond) {
+ size_t nn = rgraph[from].nnbrs;
+ assert(nn < MAX_NBRS);
+ rgraph[from].nbrs[nn] = to;
+ rgraph[from].cond[nn] = cond;
+ rgraph[from].nnbrs++;
+}
+
+static inline void reverse_graph(edge_list_t *rgraph, size_t n,
+ cond_list_t *clists, size_t nclists,
+ stack_u64 *froms) {
+ size_t i, j;
+ for (i = 0; i < nclists; i++) {
+ for (j = 0; j < clists[i].n; j++) {
+ add_edge(rgraph, clists[i].iftru[j], froms->data[i],
+ clists[i].condition[j]);
+ }
+ }
+}
+
+static inline cond_t intersect_condition(cond_t ca, cond_t cb) {
+ return (cond_t){.bounds = {{mmax(ca.bounds[0][0], cb.bounds[0][0]),
+ mmin(ca.bounds[0][1], cb.bounds[0][1])},
+ {mmax(ca.bounds[1][0], cb.bounds[1][0]),
+ mmin(ca.bounds[1][1], cb.bounds[1][1])},
+ {mmax(ca.bounds[2][0], cb.bounds[2][0]),
+ mmin(ca.bounds[2][1], cb.bounds[2][1])},
+ {mmax(ca.bounds[3][0], cb.bounds[3][0]),
+ mmin(ca.bounds[3][1], cb.bounds[3][1])}}};
+}
+
+static inline int sensible_condition(cond_t c) {
+ if (c.bounds[0][0] + 2 > c.bounds[0][1])
+ return 0;
+ if (c.bounds[1][0] + 2 > c.bounds[1][1])
+ return 0;
+ if (c.bounds[2][0] + 2 > c.bounds[2][1])
+ return 0;
+ if (c.bounds[3][0] + 2 > c.bounds[3][1])
+ return 0;
+ return 1;
+}
+
+static inline uint64_t count_cond(cond_t c) {
+ uint64_t p = 1;
+ p *= (c.bounds[0][1] - 1 - c.bounds[0][0]);
+ p *= (c.bounds[1][1] - 1 - c.bounds[1][0]);
+ p *= (c.bounds[2][1] - 1 - c.bounds[2][0]);
+ p *= (c.bounds[3][1] - 1 - c.bounds[3][0]);
+ return p;
+}
+
+typedef struct entry {
+ size_t vx;
+ cond_t cond;
+
+ SIMPLEQ_ENTRY(entry) entries;
+} entry_t;
+
+static inline uint64_t allpath_cond(edge_list_t *rgraph, size_t start,
+ size_t end, cond_t scond) {
+ uint64_t sumsi = 0;
+
+ SIMPLEQ_HEAD(listhead, entry) head = SIMPLEQ_HEAD_INITIALIZER(head);
+ entry_t *np = malloc(sizeof(*np));
+ np->vx = start;
+ np->cond = scond;
+ SIMPLEQ_INSERT_HEAD(&head, np, entries);
+
+ while (!SIMPLEQ_EMPTY(&head)) {
+ np = SIMPLEQ_FIRST(&head);
+ SIMPLEQ_REMOVE_HEAD(&head, entries);
+
+ if (np->vx == end) {
+ sumsi += count_cond(np->cond);
+ } else {
+ size_t i;
+ for (i = 0; i < rgraph[np->vx].nnbrs; i++) {
+ cond_t ic = intersect_condition(rgraph[np->vx].cond[i], np->cond);
+ if (sensible_condition(ic)) {
+ entry_t *nnp = malloc(sizeof(*nnp));
+ nnp->vx = rgraph[np->vx].nbrs[i];
+ nnp->cond = ic;
+ SIMPLEQ_INSERT_TAIL(&head, nnp, entries);
+ }
+ }
+ }
+
+ free(np);
+ }
+
+ return sumsi;
+}
+
+int main(int argc, char **argv) {
+ char **lines;
+ size_t nlines = readlines(&lines, "input");
+
+ names = malloc(sizeof(*names));
+ dict_init(names);
+
+ size_t nclists = 0;
+ cond_list_t clists[nlines];
+ stack_u64 froms;
+ stack_u64_init(&froms);
+ clists[0] = parse_line(&froms, lines[0]);
+ nclists++;
+
+ while (clists[nclists - 1].n != SIZE_MAX) {
+ clists[nclists] = parse_line(&froms, lines[nclists]);
+ nclists++;
+ }
+ nclists--;
+
+ size_t i, j;
+ for (i = 0; i < nclists; i++) {
+ cond_t base = {.bounds = {{0, UINT64_MAX},
+ {0, UINT64_MAX},
+ {0, UINT64_MAX},
+ {0, UINT64_MAX}}};
+ cond_list_t excl = exclusive_conditions(clists[i], base);
+ for (j = 0; j < excl.n; j++) {
+ clists[i].condition[j] = excl.condition[j];
+ }
+ }
+
+ size_t n = names->nelts;
+ edge_list_t rgraph[n];
+ for (i = 0; i < n; i++) {
+ rgraph[i].nnbrs = 0;
+ rgraph[i].nbrs = malloc(MAX_NBRS * sizeof(*(rgraph[i].nbrs)));
+ rgraph[i].cond = malloc(MAX_NBRS * sizeof(*(rgraph[i].cond)));
+ }
+ reverse_graph(rgraph, n, clists, nclists, &froms);
+
+ cond_t scond = {.bounds = {{0, 4001}, {0, 4001}, {0, 4001}, {0, 4001}}};
+ size_t start = add_name("A");
+ size_t end = add_name("in");
+ uint64_t sum = allpath_cond(rgraph, start, end, scond);
+
+ printf("%llu\n", sum);
+
+ stack_u64_clear(&froms);
+ free(names);
+}
diff --git a/day2/Makefile b/day2/Makefile
@@ -0,0 +1,30 @@
+CC=clang
+CFLAGS+=-std=c99 -pedantic -Wall -Werror -Wstrict-prototypes
+CFLAGS+=-Wmissing-prototypes -Wmissing-declarations -Wshadow
+CFLAGS+=-Wpointer-arith -Wcast-qual -Wsign-compare
+CFLAGS+=-O2 -g
+CFLAGS+=-fstack-protector-all -Wtype-limits -fno-common
+CFLAGS+=-fno-builtin
+CFLAGS+=-I/usr/local/include
+CFLAGS+=-I../utils
+#LDFLAGS=
+
+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) $(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)
+
+utils:
+ make -C ../utils
+
+clean:
+ rm -rf common.o uppga uppgb
diff --git a/day2/common.c b/day2/common.c
@@ -0,0 +1,3 @@
+#include "common.h"
+
+size_t fn(char **lines, size_t nlines) { return 0; }
diff --git a/day2/common.h b/day2/common.h
@@ -0,0 +1,13 @@
+#ifndef COMMON_H_
+#define COMMON_H_
+
+#include <assert.h>
+#include <limits.h>
+#include <reading.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+size_t fn(char **lines, size_t nlines);
+
+#endif
diff --git a/day2/input b/day2/input
@@ -0,0 +1,100 @@
+Game 1: 4 blue, 16 green, 2 red; 5 red, 11 blue, 16 green; 9 green, 11 blue; 10 blue, 6 green, 4 red
+Game 2: 15 green, 20 red, 8 blue; 12 green, 7 red; 10 green, 2 blue, 15 red; 13 blue, 15 red
+Game 3: 8 red, 2 blue; 3 green, 10 blue, 10 red; 7 green, 4 blue, 7 red; 8 red, 6 green, 13 blue; 4 green, 3 blue, 10 red; 7 blue, 7 green, 5 red
+Game 4: 13 green, 14 blue, 9 red; 6 green, 14 red, 18 blue; 9 red, 11 green, 3 blue; 11 green, 10 red, 14 blue; 17 blue, 3 red, 4 green; 17 blue, 1 red, 9 green
+Game 5: 2 green, 1 red; 8 blue, 2 green, 6 red; 5 blue, 9 red, 2 green; 3 green, 8 red, 6 blue; 6 blue, 5 red
+Game 6: 3 green, 7 blue, 5 red; 3 green, 6 red; 11 blue, 6 red, 1 green
+Game 7: 8 red, 4 green, 11 blue; 12 blue, 1 green, 5 red; 6 red, 1 green, 5 blue; 12 blue, 2 green, 2 red; 4 blue, 4 green, 3 red; 9 blue, 4 green, 8 red
+Game 8: 1 red, 4 green; 6 red, 1 green; 10 red; 1 blue, 2 green; 4 green, 3 red; 1 blue, 8 red
+Game 9: 9 blue, 13 green, 1 red; 10 green, 4 blue, 4 red; 3 red, 4 blue, 14 green; 13 blue, 1 red, 12 green
+Game 10: 2 blue, 16 red, 2 green; 1 green, 16 red, 6 blue; 9 red, 3 green; 1 green, 2 blue, 8 red; 8 red, 6 blue, 3 green
+Game 11: 7 green, 11 red, 12 blue; 3 blue, 6 green, 6 red; 10 blue, 13 green; 1 red, 13 green, 9 blue; 2 blue, 2 red, 13 green; 2 red, 3 blue, 15 green
+Game 12: 3 green, 2 red, 2 blue; 7 green, 5 blue; 1 blue, 1 red, 3 green
+Game 13: 2 green, 2 red, 3 blue; 3 blue, 3 red, 3 green; 3 green, 2 red; 2 blue, 3 red, 3 green; 2 green, 3 red, 1 blue
+Game 14: 4 green, 9 red; 11 green, 10 red, 12 blue; 6 red, 3 green, 12 blue; 5 green, 4 red, 4 blue; 18 blue, 7 red, 11 green; 16 blue, 4 red, 10 green
+Game 15: 5 green, 2 red, 9 blue; 18 green, 6 red, 20 blue; 11 blue, 12 green, 11 red; 9 red, 17 blue, 16 green; 7 green, 1 red, 9 blue
+Game 16: 9 blue, 11 green; 8 green, 2 blue; 1 red, 6 green, 4 blue
+Game 17: 2 red, 2 green, 2 blue; 7 blue, 4 green, 3 red; 2 red, 8 blue, 1 green; 2 red, 6 blue, 2 green; 4 blue, 3 red; 4 green, 5 red, 6 blue
+Game 18: 6 green, 7 red; 3 blue, 6 green, 1 red; 6 red, 3 blue, 5 green
+Game 19: 6 red, 4 green, 5 blue; 2 red, 4 blue, 13 green; 1 green, 1 blue, 2 red; 4 green
+Game 20: 7 red, 17 blue, 6 green; 3 blue, 6 green, 8 red; 7 blue, 6 red, 1 green; 3 green; 8 red, 7 green, 14 blue
+Game 21: 5 red, 3 blue, 7 green; 1 blue, 2 red, 5 green; 2 blue, 8 green, 3 red; 3 blue, 8 red, 4 green; 5 red, 1 blue, 3 green
+Game 22: 2 red, 6 green, 1 blue; 3 red, 3 green, 1 blue; 2 green, 7 red, 2 blue; 5 green, 1 red
+Game 23: 2 red, 16 green, 1 blue; 1 red, 12 green, 3 blue; 12 green, 1 blue, 3 red
+Game 24: 7 red, 1 blue, 12 green; 2 red, 19 green, 3 blue; 19 green, 1 blue, 12 red; 6 green, 16 red, 5 blue; 11 red, 4 blue, 12 green
+Game 25: 2 blue, 3 red, 8 green; 4 blue, 2 red, 9 green; 2 red, 7 blue
+Game 26: 17 red, 8 blue, 3 green; 3 green, 13 red, 4 blue; 20 red, 1 green, 6 blue; 7 blue, 2 red, 2 green; 20 red, 8 blue; 2 green, 16 red, 8 blue
+Game 27: 3 blue, 17 green, 19 red; 16 green, 5 red, 6 blue; 17 green, 16 red, 4 blue
+Game 28: 1 green, 7 red, 1 blue; 8 green, 12 red, 1 blue; 1 blue, 9 red, 1 green
+Game 29: 3 green, 3 blue, 2 red; 3 green, 2 red, 1 blue; 3 green, 2 red, 3 blue; 3 blue, 3 red, 4 green
+Game 30: 3 red, 8 blue, 3 green; 1 green, 1 red; 17 green, 17 blue; 19 green, 15 blue, 1 red; 1 green, 2 red, 16 blue
+Game 31: 11 green, 11 blue, 14 red; 6 blue, 15 green, 2 red; 11 blue, 19 green, 2 red
+Game 32: 9 red, 2 green; 7 green, 4 blue, 2 red; 6 red, 5 green, 1 blue; 4 red, 4 blue, 1 green; 8 red, 6 green
+Game 33: 6 blue, 16 red, 9 green; 5 red, 7 blue, 13 green; 1 green, 9 blue, 1 red; 4 green, 9 blue, 17 red; 2 green, 10 red, 13 blue; 9 red, 1 blue, 14 green
+Game 34: 2 red, 2 green, 4 blue; 3 blue, 2 green; 1 green, 1 red, 2 blue; 1 red, 3 blue, 3 green; 2 green, 8 blue, 2 red; 3 blue, 1 red
+Game 35: 4 red, 14 blue, 2 green; 1 green, 15 blue, 1 red; 1 blue, 2 red, 1 green
+Game 36: 4 blue, 1 red, 2 green; 2 green, 15 blue, 8 red; 7 blue, 1 red; 7 red, 1 green, 1 blue
+Game 37: 2 blue, 1 green, 5 red; 2 blue, 2 green, 4 red; 2 blue, 5 red, 8 green; 3 green, 2 blue, 1 red; 1 red, 1 blue, 5 green; 2 blue, 1 red, 8 green
+Game 38: 2 blue, 4 green, 11 red; 7 green, 6 red, 2 blue; 1 green, 3 red, 1 blue; 4 blue, 4 green, 4 red; 2 red, 5 blue, 2 green
+Game 39: 7 green, 7 blue, 2 red; 11 blue, 4 green, 8 red; 10 red, 4 green, 1 blue; 8 green, 9 blue; 9 green, 4 red; 1 green, 8 blue
+Game 40: 1 green, 13 blue; 6 blue, 7 red; 8 red; 1 green, 13 blue, 3 red; 1 green, 16 red, 13 blue; 14 blue, 14 red, 1 green
+Game 41: 5 green, 2 blue, 10 red; 4 green, 2 blue, 5 red; 6 green, 9 red, 1 blue; 4 red, 1 blue; 1 red, 3 green, 2 blue; 3 red
+Game 42: 17 green, 11 blue, 11 red; 5 blue, 11 green, 9 red; 10 blue, 13 red, 4 green; 8 green, 4 blue, 15 red
+Game 43: 1 red, 3 blue; 1 green, 3 blue, 1 red; 2 blue, 1 green; 2 green, 1 blue; 1 red, 3 blue
+Game 44: 7 green, 5 red, 1 blue; 6 green, 1 blue, 5 red; 2 blue, 6 green; 3 green, 2 red; 4 green; 6 red
+Game 45: 16 red, 14 blue, 19 green; 1 red, 5 green, 6 blue; 16 blue, 2 green, 1 red; 15 green, 6 red, 16 blue
+Game 46: 8 blue, 2 green; 4 red, 3 green, 6 blue; 1 green, 8 blue, 3 red; 3 green, 12 blue, 1 red
+Game 47: 9 green, 3 blue; 1 green, 1 blue; 4 blue, 9 green, 6 red; 8 green, 4 blue, 6 red; 6 red, 12 green, 1 blue; 4 blue, 7 green
+Game 48: 11 green, 4 blue, 1 red; 11 blue, 8 red, 9 green; 4 blue, 3 red, 7 green; 10 blue, 2 green, 9 red; 8 green, 2 blue, 2 red
+Game 49: 8 green, 1 blue, 5 red; 1 green, 1 blue; 3 green, 4 red, 2 blue; 1 blue, 7 green, 1 red; 1 blue, 7 green, 3 red; 5 red, 5 green
+Game 50: 2 green, 2 red, 4 blue; 8 blue, 2 green, 7 red; 4 blue, 5 red; 9 red, 4 blue; 5 blue, 9 red; 2 green, 8 red, 6 blue
+Game 51: 6 green, 1 red, 2 blue; 2 red, 4 blue, 6 green; 9 blue, 4 green
+Game 52: 7 green, 3 red, 12 blue; 8 blue, 9 red, 5 green; 2 blue, 10 green, 8 red; 12 red, 5 green, 3 blue; 8 red, 8 green, 12 blue; 2 green
+Game 53: 2 green, 9 blue, 5 red; 6 red, 3 green; 5 red, 2 green
+Game 54: 9 red, 13 blue; 1 green, 9 red, 16 blue; 12 red, 1 blue, 4 green
+Game 55: 1 red, 2 blue, 3 green; 1 blue; 1 red, 5 blue, 3 green; 1 blue, 3 green; 5 blue
+Game 56: 1 green, 4 red, 1 blue; 1 blue, 2 red, 13 green; 5 blue, 4 red; 13 green, 3 red, 3 blue
+Game 57: 13 blue, 2 red, 7 green; 3 green, 4 red, 14 blue; 3 red, 3 green, 3 blue; 7 blue, 5 green, 1 red
+Game 58: 6 red; 1 blue, 4 red, 2 green; 3 green, 1 blue; 7 green, 1 red; 6 red, 13 green, 1 blue; 3 red, 13 green, 1 blue
+Game 59: 5 green, 10 red, 8 blue; 7 red, 3 green, 2 blue; 6 green, 3 red, 6 blue
+Game 60: 2 green, 5 red, 15 blue; 2 green, 9 blue; 9 blue, 8 green, 3 red; 2 green, 6 red, 2 blue
+Game 61: 8 blue, 3 green, 4 red; 1 red, 10 blue, 1 green; 4 red, 5 green, 3 blue; 3 red, 8 blue, 5 green
+Game 62: 19 blue, 3 red, 14 green; 1 green, 7 blue, 1 red; 15 red, 20 blue, 6 green; 8 red, 4 green, 14 blue
+Game 63: 13 red, 1 blue; 18 red, 4 green; 6 green, 9 red, 1 blue; 7 green, 1 blue, 9 red; 5 red, 1 blue, 4 green; 5 green, 1 blue, 17 red
+Game 64: 2 green, 1 blue, 5 red; 2 red, 5 green; 6 red, 4 green
+Game 65: 1 blue, 7 green, 1 red; 7 red, 1 green; 1 blue, 3 green, 3 red; 7 red, 3 green; 3 green, 7 red; 1 blue, 4 green
+Game 66: 7 green, 6 blue, 8 red; 4 green, 9 red, 3 blue; 6 green, 4 blue; 5 blue, 2 green; 6 red, 4 green, 2 blue
+Game 67: 10 blue, 17 green, 17 red; 11 red, 9 blue, 9 green; 9 blue, 19 red, 5 green; 5 red, 3 blue, 20 green; 11 red, 1 blue, 7 green
+Game 68: 9 green, 4 red, 5 blue; 11 blue, 9 green, 2 red; 11 blue, 2 red, 6 green; 2 green, 6 red, 3 blue; 1 blue, 6 green, 4 red
+Game 69: 3 red, 15 blue, 1 green; 4 red, 14 blue, 2 green; 4 red, 18 blue, 4 green
+Game 70: 3 red, 8 green; 2 red, 6 green; 4 red, 2 blue, 2 green; 8 red, 1 green, 2 blue; 6 red, 3 blue, 4 green; 13 green, 8 red
+Game 71: 3 green, 17 red; 2 red, 3 green; 2 green, 8 red, 1 blue; 11 red, 4 blue; 3 green, 11 red, 3 blue
+Game 72: 1 red, 17 blue, 8 green; 2 red, 11 blue, 16 green; 3 red, 16 blue, 1 green; 2 red, 3 green, 10 blue
+Game 73: 1 blue, 10 green, 8 red; 19 green, 10 red, 5 blue; 3 green, 13 red, 8 blue; 12 green, 4 blue; 2 green, 10 blue, 12 red
+Game 74: 17 blue, 7 red, 10 green; 16 blue, 5 red; 9 blue, 7 green, 2 red; 10 red, 4 green, 14 blue
+Game 75: 10 green, 5 blue, 4 red; 7 red, 10 blue, 7 green; 7 blue, 9 green, 2 red
+Game 76: 13 green, 16 red, 20 blue; 4 red, 14 blue, 5 green; 12 red, 1 blue, 8 green
+Game 77: 4 red, 2 green; 8 blue, 3 green, 2 red; 5 blue, 7 green, 3 red
+Game 78: 12 green, 8 red, 8 blue; 10 green, 9 red, 10 blue; 16 blue, 1 red, 17 green; 4 red, 15 green, 13 blue
+Game 79: 4 green, 2 red; 15 red, 3 blue; 15 red, 5 green
+Game 80: 4 blue, 1 green, 13 red; 13 red, 1 blue, 5 green; 5 blue, 9 red; 3 blue, 3 green; 1 red; 3 red, 7 green, 6 blue
+Game 81: 10 red, 3 green, 4 blue; 2 red, 5 green, 16 blue; 3 green, 1 blue; 9 blue, 2 green, 12 red
+Game 82: 1 green, 9 blue, 1 red; 10 blue, 1 red, 1 green; 1 green, 7 blue; 8 blue
+Game 83: 1 blue, 5 red; 2 blue, 3 red; 1 green, 2 blue, 1 red; 2 red, 1 blue, 1 green; 1 green, 1 blue; 2 red, 1 green
+Game 84: 5 red, 14 blue, 2 green; 6 blue, 5 red, 8 green; 12 green, 3 blue, 5 red; 2 red, 10 green; 9 green, 14 blue
+Game 85: 2 blue, 2 red; 14 red, 6 green, 5 blue; 5 green, 4 blue, 6 red; 8 red, 5 blue, 6 green
+Game 86: 1 blue, 10 red; 4 red; 9 blue, 18 red, 3 green; 1 green, 1 blue, 7 red; 3 green, 8 red, 9 blue; 14 red, 2 green, 4 blue
+Game 87: 1 green, 11 red, 8 blue; 1 green, 11 red, 2 blue; 7 red, 4 blue; 6 blue, 1 red, 2 green; 13 blue, 2 green; 6 blue, 12 red, 3 green
+Game 88: 2 blue, 4 red, 8 green; 4 blue, 7 red; 3 red, 10 green, 4 blue; 9 green, 3 blue, 5 red; 4 red, 6 blue, 3 green
+Game 89: 6 red, 10 green; 15 green, 15 red, 10 blue; 15 red, 1 green, 4 blue; 13 red, 6 blue, 4 green
+Game 90: 17 green, 2 red, 1 blue; 6 green; 1 blue, 1 green; 1 blue, 16 green, 3 red; 14 green, 1 red
+Game 91: 3 blue, 8 green; 3 green, 7 red, 9 blue; 12 blue; 9 red, 7 blue, 4 green; 1 green, 7 red, 1 blue
+Game 92: 11 blue, 9 red, 12 green; 1 blue, 14 red, 6 green; 9 green, 6 red, 6 blue
+Game 93: 1 red, 2 blue; 3 blue, 6 green; 1 red, 4 green, 3 blue
+Game 94: 3 green, 3 blue; 1 red, 3 blue, 9 green; 3 blue, 10 green, 3 red; 10 green, 6 blue, 2 red; 9 blue, 14 green, 2 red; 1 red, 4 blue, 1 green
+Game 95: 7 blue, 10 green; 3 blue, 5 green, 2 red; 4 blue, 10 green, 12 red; 6 green, 2 red, 6 blue
+Game 96: 2 blue, 18 green, 8 red; 13 green, 3 blue, 3 red; 3 blue, 15 red, 8 green; 13 green, 10 red, 2 blue
+Game 97: 14 blue, 2 red; 15 blue, 1 green, 2 red; 3 red, 6 blue, 1 green; 1 green, 14 blue, 4 red
+Game 98: 4 blue, 9 red; 10 red, 1 green, 11 blue; 7 blue, 1 red; 1 red, 6 blue, 1 green
+Game 99: 7 red, 6 green, 2 blue; 8 red; 16 green, 7 red, 4 blue
+Game 100: 1 red, 1 green, 9 blue; 6 blue, 4 green, 3 red; 4 red, 2 green; 3 green, 2 red, 11 blue; 6 green, 5 blue, 1 red
diff --git a/day2/uppga.c b/day2/uppga.c
@@ -0,0 +1,54 @@
+#include "common.h"
+
+#define RED 0
+#define GREEN 1
+#define BLUE 2
+
+static int test_line(char *line) {
+ char *cp = line;
+ long bag[3] = {12, 13, 14};
+
+ while (*cp != '\0') {
+ if (cp[1] == ' ' && '0' <= cp[0] && cp[0] <= '9') {
+ char *pp = cp;
+ while (*pp != ' ')
+ pp--;
+ pp++;
+
+ long v = strtol(pp, NULL, 10);
+
+ if (cp[2] == 'r') {
+ if (bag[RED] < v)
+ return -1;
+ } else if (cp[2] == 'g') {
+ if (bag[GREEN] < v)
+ return -1;
+ } else if (cp[2] == 'b') {
+ if (bag[BLUE] < v)
+ return -1;
+ } else {
+ printf("ERROR\n");
+ exit(1);
+ }
+ }
+
+ cp++;
+ }
+
+ return 0;
+}
+
+int main(int argc, char **argv) {
+ char **lines;
+ size_t nlines = readlines(&lines, "input");
+
+ size_t i;
+ size_t sum = 0;
+ for (i = 0; i < nlines; i++) {
+ if (!test_line(lines[i])) {
+ sum += (i + 1);
+ }
+ }
+
+ printf("%zu\n", sum);
+}
diff --git a/day2/uppgb.c b/day2/uppgb.c
@@ -0,0 +1,55 @@
+#include "common.h"
+
+#define RED 0
+#define GREEN 1
+#define BLUE 2
+
+static long line_min_power(char *line) {
+ char *cp = line;
+ long min[3] = {0, 0, 0};
+
+ while (*cp != '\0') {
+ if (cp[1] == ' ' && '0' <= cp[0] && cp[0] <= '9') {
+ char *pp = cp;
+ while (*pp != ' ')
+ pp--;
+ pp++;
+
+ long v = strtol(pp, NULL, 10);
+
+ if (cp[2] == 'r') {
+ if (min[RED] < v) {
+ min[RED] = v;
+ }
+ } else if (cp[2] == 'g') {
+ if (min[GREEN] < v) {
+ min[GREEN] = v;
+ }
+ } else if (cp[2] == 'b') {
+ if (min[BLUE] < v) {
+ min[BLUE] = v;
+ }
+ } else {
+ printf("ERROR\n");
+ exit(1);
+ }
+ }
+
+ cp++;
+ }
+
+ return min[RED] * min[GREEN] * min[BLUE];
+}
+
+int main(int argc, char **argv) {
+ char **lines;
+ size_t nlines = readlines(&lines, "input");
+
+ size_t i;
+ long sum = 0;
+ for (i = 0; i < nlines; i++) {
+ sum += line_min_power(lines[i]);
+ }
+
+ printf("%ld\n", sum);
+}
diff --git a/day20/Makefile b/day20/Makefile
@@ -0,0 +1,31 @@
+CC=clang
+CFLAGS+=-std=c99 -pedantic -Wall -Werror -Wstrict-prototypes
+CFLAGS+=-Wmissing-prototypes -Wmissing-declarations -Wshadow
+CFLAGS+=-Wpointer-arith -Wcast-qual -Wsign-compare
+CFLAGS+=-O2 -g
+CFLAGS+=-fstack-protector-all -Wtype-limits -fno-common
+CFLAGS+=-fno-builtin
+CFLAGS+=-I/usr/local/include
+CFLAGS+=-I../utils
+GCFLAGS+=-L/usr/local/lib
+LDFLAGS=-lgmp
+
+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) $(CFLAGS) -o uppga uppga.c common.o $(UTILS) $(INCLUDES)
+
+uppgb: $(UTILS) common.o uppgb.c
+ $(CC) $(GCFLAGS) $(CFLAGS) -o uppgb uppgb.c common.o $(UTILS) $(INCLUDES) $(LDFLAGS)
+
+utils:
+ make -C ../utils
+
+clean:
+ rm -rf common.o uppga uppgb
diff --git a/day20/common.c b/day20/common.c
@@ -0,0 +1,3 @@
+#include "common.h"
+
+size_t fn(char **lines, size_t nlines) { return 0; }
diff --git a/day20/common.h b/day20/common.h
@@ -0,0 +1,16 @@
+#ifndef COMMON_H_
+#define COMMON_H_
+
+#include <assert.h>
+#include <gmp.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/queue.h>
+
+#include <reading.h>
+#include <stack_u64.h>
+
+size_t fn(char **lines, size_t nlines);
+
+#endif
diff --git a/day20/exinput b/day20/exinput
@@ -0,0 +1,5 @@
+broadcaster -> a, b, c
+%a -> b
+%b -> c
+%c -> inv
+&inv -> a
diff --git a/day20/exinput2 b/day20/exinput2
@@ -0,0 +1,5 @@
+broadcaster -> a
+%a -> inv, con
+&inv -> b
+%b -> con
+&con -> output
diff --git a/day20/input b/day20/input
@@ -0,0 +1,58 @@
+%cg -> mt, hb
+%sp -> xm
+%nr -> hf, mt
+broadcaster -> tl, gd, zb, gc
+&qz -> qn
+%df -> hd
+%vg -> rm, kx
+%gm -> mt, md
+%ls -> hc
+%lq -> zq, fx
+&zd -> bz, kg, zb, lf, sq, zk, jx
+%lz -> mt
+%sq -> zk
+%zn -> kx, tc
+&zq -> mb, hc, qz, ql, tl, ls
+&mt -> zm, tt, mh, gd, md
+%lm -> mb, zq
+%hf -> mt, sm
+%hb -> mh, mt
+%rm -> kx
+%gc -> kx, sp
+&cq -> qn
+%mh -> jt
+%zm -> nr
+%xm -> kx, ld
+&jx -> qn
+&qn -> rx
+%mp -> qt, kx
+%zk -> vj
+%hd -> mp, kx
+%tl -> zq, hl
+%zb -> zd, ph
+%cl -> zd
+&tt -> qn
+%ld -> zn
+%js -> lq, zq
+%sm -> mt, lz
+%qt -> vg, kx
+%md -> cg
+%vj -> bz, zd
+%qs -> zd, fs
+%mb -> ps
+&kx -> cq, gc, sp, df, ld
+%hc -> lm
+%tc -> df, kx
+%ps -> js, zq
+%fs -> qc, zd
+%hl -> jj, zq
+%bz -> qs
+%jj -> zq, ql
+%ql -> ls
+%ph -> kg, zd
+%qc -> cl, zd
+%lf -> sq
+%kg -> lf
+%fx -> zq
+%jt -> zm, mt
+%gd -> gm, mt
diff --git a/day20/uppga.c b/day20/uppga.c
@@ -0,0 +1,230 @@
+#include "common.h"
+
+#define ALPHSIZE 26
+#define BUTT 676
+#define BRDC 677
+
+typedef SIMPLEQ_HEAD(listhead, entry) head_t;
+
+typedef struct entry {
+ size_t from;
+ size_t to;
+ uint8_t val;
+
+ SIMPLEQ_ENTRY(entry) entries;
+} sig_t;
+
+typedef struct {
+ char *name;
+ uint8_t type;
+
+ uint64_t state;
+ size_t *inshift;
+ size_t nstate;
+
+ stack_u64 nbrs;
+} gate_t;
+
+static inline size_t pure_name_idx(char *s) {
+ return ((s[0] - 'a') * ALPHSIZE + (s[1] - 'a'));
+}
+
+static inline size_t name_idx(char *s) {
+ if (s[0] == 'b') {
+ if (s[1] == 'r') {
+ return BRDC;
+ } else {
+ return BUTT;
+ }
+ }
+
+ return pure_name_idx(&s[1]);
+}
+
+static inline void init_gate(gate_t *gt, char *line) {
+ gt->state = 0;
+ gt->name = line;
+
+ switch (line[0]) {
+ case '&':
+ gt->type = '&';
+ break;
+ case '%':
+ gt->type = '%';
+ break;
+ default:
+ gt->type = 'x';
+ }
+
+ stack_u64_init(>->nbrs);
+
+ char *cp = line;
+ while (*cp != ' ')
+ cp++;
+ cp++;
+
+ while (*cp != '\n' && *cp != EOF) {
+ while (*cp != ' ' && *cp != '\n' && *cp != EOF)
+ cp++;
+ if (*cp != ' ')
+ break;
+ cp++;
+
+ stack_u64_push(>->nbrs, pure_name_idx(cp));
+
+ cp++;
+ }
+}
+
+static inline void init_states(gate_t *gates) {
+ size_t i, j, to;
+ size_t countin[BRDC + 1] = {0};
+
+ for (i = 0; i < BRDC + 1; i++) {
+ if (gates[i].name != NULL) {
+ if (gates[i].type == '&') {
+ gates[i].inshift = malloc((BRDC + 1) * sizeof(*(gates[i].inshift)));
+ } else {
+ gates[i].inshift = NULL;
+ }
+ }
+ }
+
+ for (i = 0; i < BRDC + 1; i++) {
+ if (gates[i].name != NULL) {
+ for (j = 0; j < gates[i].nbrs.nmemb; j++) {
+ to = gates[i].nbrs.data[j];
+ if (gates[to].type == '&')
+ gates[to].inshift[i] = countin[to];
+ countin[to]++;
+ }
+ }
+ }
+
+ for (i = 0; i < BRDC + 1; i++) {
+ if (gates[i].name != NULL) {
+ switch (gates[i].type) {
+ case '%':
+ gates[i].nstate = 1;
+ break;
+ case '&':
+ gates[i].nstate = countin[i];
+ break;
+ default:
+ gates[i].nstate = SIZE_MAX;
+ }
+ }
+ }
+}
+
+static inline void send_pulses(gate_t *gate, size_t from, head_t *head,
+ uint8_t pulse) {
+ size_t i;
+ for (i = 0; i < gate->nbrs.nmemb; i++) {
+ sig_t *n = malloc(sizeof(*n));
+ n->from = from;
+ n->to = gate->nbrs.data[i];
+ n->val = pulse;
+ SIMPLEQ_INSERT_TAIL(head, n, entries);
+ }
+}
+
+static inline void set_bit(uint64_t *out, size_t i, uint8_t val) {
+ assert(i < 63);
+
+ if (val) {
+ *out |= (1ULL << i);
+ } else {
+ *out &= (0xffffffffffffffffULL ^ (1ULL << i));
+ }
+}
+
+static inline void push(uint64_t *ulow, uint64_t *uhig, gate_t *gates) {
+ size_t i;
+ head_t head = SIMPLEQ_HEAD_INITIALIZER(head);
+
+ sig_t *s = malloc(sizeof(*s));
+ s->from = BUTT;
+ s->to = BRDC;
+ s->val = 0;
+
+ SIMPLEQ_INSERT_HEAD(&head, s, entries);
+
+ uint64_t clow = 0;
+ uint64_t chig = 0;
+
+ while (!SIMPLEQ_EMPTY(&head)) {
+ s = SIMPLEQ_FIRST(&head);
+ SIMPLEQ_REMOVE_HEAD(&head, entries);
+
+ if (s->val == 0) {
+ clow++;
+ } else {
+ chig++;
+ }
+
+ switch (gates[s->to].type) {
+ case '%':
+ if (s->val == 0) {
+ gates[s->to].state ^= 1;
+ send_pulses(&gates[s->to], s->to, &head, (uint8_t)gates[s->to].state);
+ }
+ break;
+ case '&':
+ set_bit(&(gates[s->to].state), gates[s->to].inshift[s->from], s->val);
+
+ uint8_t spulse = 0;
+ for (i = 0; i < gates[s->to].nstate; i++) {
+ if ((gates[s->to].nstate & (1ULL << i)) == 0) {
+ spulse = 1;
+ break;
+ }
+ }
+
+ send_pulses(&gates[s->to], s->to, &head, spulse);
+ break;
+ case 'x':
+ assert(s->from == BUTT);
+ assert(s->to == BRDC);
+ send_pulses(&gates[s->to], s->to, &head, 0);
+ break;
+ default:
+ assert(s->to == 465); // rx the only one
+ }
+
+ free(s);
+ }
+
+ *ulow = clow;
+ *uhig = chig;
+}
+
+int main(int argc, char **argv) {
+ char **lines;
+ size_t nlines = readlines(&lines, "input");
+
+ gate_t gates[BRDC + 1];
+ size_t i;
+ for (i = 0; i < BRDC + 1; i++)
+ gates[i].name = NULL;
+
+ size_t g;
+ for (i = 0; i < nlines; i++) {
+ g = name_idx(lines[i]);
+ init_gate(&gates[g], lines[i]);
+ }
+
+ init_states(gates);
+
+ uint64_t slow = 0;
+ uint64_t shig = 0;
+ uint64_t clow, chig;
+
+ for (i = 0; i < 1000; i++) {
+ push(&clow, &chig, gates);
+ slow += clow;
+ shig += chig;
+ }
+
+ printf("%llu\n", slow * shig);
+}
diff --git a/day20/uppgb.c b/day20/uppgb.c
@@ -0,0 +1,254 @@
+#include "common.h"
+
+#define ALPHSIZE 26
+#define BUTT 676
+#define BRDC 677
+
+#define QZ 441
+#define CQ 68
+#define JX 257
+#define TT 513
+
+typedef SIMPLEQ_HEAD(listhead, entry) head_t;
+
+typedef struct entry {
+ size_t from;
+ size_t to;
+ uint8_t val;
+
+ SIMPLEQ_ENTRY(entry) entries;
+} sig_t;
+
+typedef struct {
+ char *name;
+ uint8_t type;
+
+ uint64_t state;
+ size_t *inshift;
+ size_t nstate;
+
+ stack_u64 nbrs;
+} gate_t;
+
+static inline size_t pure_name_idx(char *s) {
+ return ((s[0] - 'a') * ALPHSIZE + (s[1] - 'a'));
+}
+
+static inline size_t name_idx(char *s) {
+ if (s[0] == 'b') {
+ if (s[1] == 'r') {
+ return BRDC;
+ } else {
+ return BUTT;
+ }
+ }
+
+ return pure_name_idx(&s[1]);
+}
+
+static inline void init_gate(gate_t *gt, char *line) {
+ gt->state = 0;
+ gt->name = line;
+
+ switch (line[0]) {
+ case '&':
+ gt->type = '&';
+ break;
+ case '%':
+ gt->type = '%';
+ break;
+ default:
+ gt->type = 'x';
+ }
+
+ stack_u64_init(>->nbrs);
+
+ char *cp = line;
+ while (*cp != ' ')
+ cp++;
+ cp++;
+
+ while (*cp != '\n' && *cp != EOF) {
+ while (*cp != ' ' && *cp != '\n' && *cp != EOF)
+ cp++;
+ if (*cp != ' ')
+ break;
+ cp++;
+
+ stack_u64_push(>->nbrs, pure_name_idx(cp));
+
+ cp++;
+ }
+}
+
+static inline void init_states(gate_t *gates) {
+ size_t i, j, to;
+ size_t countin[BRDC + 1] = {0};
+
+ for (i = 0; i < BRDC + 1; i++) {
+ if (gates[i].name != NULL) {
+ if (gates[i].type == '&') {
+ gates[i].inshift = malloc((BRDC + 1) * sizeof(*(gates[i].inshift)));
+ } else {
+ gates[i].inshift = NULL;
+ }
+ }
+ }
+
+ for (i = 0; i < BRDC + 1; i++) {
+ if (gates[i].name != NULL) {
+ for (j = 0; j < gates[i].nbrs.nmemb; j++) {
+ to = gates[i].nbrs.data[j];
+ if (gates[to].type == '&')
+ gates[to].inshift[i] = countin[to];
+ countin[to]++;
+ }
+ }
+ }
+
+ for (i = 0; i < BRDC + 1; i++) {
+ if (gates[i].name != NULL) {
+ switch (gates[i].type) {
+ case '%':
+ gates[i].nstate = 1;
+ break;
+ case '&':
+ gates[i].nstate = countin[i];
+ break;
+ default:
+ gates[i].nstate = SIZE_MAX;
+ }
+ }
+ }
+}
+
+static inline void send_pulses(gate_t *gate, size_t from, head_t *head,
+ uint8_t pulse) {
+ size_t i;
+ for (i = 0; i < gate->nbrs.nmemb; i++) {
+ sig_t *n = malloc(sizeof(*n));
+ n->from = from;
+ n->to = gate->nbrs.data[i];
+ n->val = pulse;
+ SIMPLEQ_INSERT_TAIL(head, n, entries);
+ }
+}
+
+static inline void set_bit(uint64_t *out, size_t i, uint8_t val) {
+ assert(i < 63);
+
+ if (val) {
+ *out |= (1ULL << i);
+ } else {
+ *out &= (0xffffffffffffffffULL ^ (1ULL << i));
+ }
+}
+
+static inline void push(gate_t *gates, size_t idx, size_t *cycla,
+ size_t *cyclb) {
+ size_t i;
+ head_t head = SIMPLEQ_HEAD_INITIALIZER(head);
+
+ sig_t *s = malloc(sizeof(*s));
+ s->from = BUTT;
+ s->to = BRDC;
+ s->val = 0;
+
+ SIMPLEQ_INSERT_HEAD(&head, s, entries);
+
+ uint64_t clow = 0;
+ uint64_t chig = 0;
+
+ while (!SIMPLEQ_EMPTY(&head)) {
+ s = SIMPLEQ_FIRST(&head);
+ SIMPLEQ_REMOVE_HEAD(&head, entries);
+
+ if (s->val == 0) {
+ clow++;
+ } else {
+ chig++;
+ }
+
+ if (s->val == 1 && s->to == 429) {
+ if (cycla[s->from] == SIZE_MAX) {
+ cycla[s->from] = idx + 1;
+ } else if (cyclb[s->from] == SIZE_MAX && idx + 1 != cycla[s->from]) {
+ cyclb[s->from] = idx + 1;
+ }
+ }
+
+ switch (gates[s->to].type) {
+ case '%':
+ if (s->val == 0) {
+ gates[s->to].state ^= 1;
+ send_pulses(&gates[s->to], s->to, &head, (uint8_t)gates[s->to].state);
+ }
+ break;
+ case '&':
+ set_bit(&(gates[s->to].state), gates[s->to].inshift[s->from], s->val);
+
+ uint8_t spulse = 0;
+ for (i = 0; i < gates[s->to].nstate; i++) {
+ if ((gates[s->to].state & (1ULL << i)) == 0) {
+ spulse = 1;
+ break;
+ }
+ }
+
+ send_pulses(&gates[s->to], s->to, &head, spulse);
+ break;
+ case 'x':
+ assert(s->from == BUTT);
+ assert(s->to == BRDC);
+ send_pulses(&gates[s->to], s->to, &head, 0);
+ break;
+ default:
+ assert(s->to == 465); // rx the only one
+ }
+
+ free(s);
+ }
+}
+
+int main(int argc, char **argv) {
+ char **lines;
+ size_t nlines = readlines(&lines, "input");
+
+ gate_t gates[BRDC + 1];
+ size_t i;
+ for (i = 0; i < BRDC + 1; i++)
+ gates[i].name = NULL;
+
+ size_t g;
+ for (i = 0; i < nlines; i++) {
+ g = name_idx(lines[i]);
+ init_gate(&gates[g], lines[i]);
+ }
+
+ init_states(gates);
+
+ size_t cycla[BRDC + 1];
+ size_t cyclb[BRDC + 1];
+ for (i = 0; i < BRDC + 1; i++) {
+ cycla[i] = SIZE_MAX;
+ cyclb[i] = SIZE_MAX;
+ }
+
+ for (i = 0; i < 10000; i++) {
+ push(gates, i, cycla, cyclb);
+ }
+
+ mpz_t p;
+ mpz_init_set_ui(p, 1);
+
+ for (i = 0; i < BRDC + 1; i++) {
+ if (cycla[i] != SIZE_MAX) {
+ assert(cyclb[i] == cycla[i] * 2); // this makes the cycle possible
+ mpz_lcm_ui(p, p, cycla[i]);
+ }
+ }
+
+ gmp_printf("%Zd\n", p);
+
+ mpz_clear(p);
+}
diff --git a/day21/Makefile b/day21/Makefile
@@ -0,0 +1,30 @@
+CC=clang
+CFLAGS+=-std=c99 -pedantic -Wall -Werror -Wstrict-prototypes
+CFLAGS+=-Wmissing-prototypes -Wmissing-declarations -Wshadow
+CFLAGS+=-Wpointer-arith -Wcast-qual -Wsign-compare
+CFLAGS+=-O2 -g
+CFLAGS+=-fstack-protector-all -Wtype-limits -fno-common
+CFLAGS+=-fno-builtin
+CFLAGS+=-I/usr/local/include
+CFLAGS+=-I../utils
+#LDFLAGS=
+
+UTILS=../utils/reading.o ../utils/graph.o ../utils/stack_u64.o ../utils/set_u64p.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) $(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)
+
+utils:
+ make -C ../utils
+
+clean:
+ rm -rf common.o uppga uppgb
diff --git a/day21/common.c b/day21/common.c
@@ -0,0 +1,47 @@
+#include "common.h"
+
+static inline size_t idx(size_t row, size_t col, size_t ncols) {
+ return row * ncols + col;
+}
+
+static inline int walkable(char **lines, size_t r, size_t c) {
+ return lines[r][c] == '.' || lines[r][c] == 'S';
+}
+
+static inline void edge_adder(graph_t *g, char **lines, size_t nlines,
+ size_t ncols, size_t row, size_t col) {
+ // north
+ if (row > 0 && walkable(lines, row - 1, col)) {
+ graph_add_edge(g, idx(row, col, ncols), idx(row - 1, col, ncols));
+ }
+
+ // east
+ if (col < ncols - 1 && walkable(lines, row, col + 1)) {
+ graph_add_edge(g, idx(row, col, ncols), idx(row, col + 1, ncols));
+ }
+
+ // south
+ if (row < nlines - 1 && walkable(lines, row + 1, col)) {
+ graph_add_edge(g, idx(row, col, ncols), idx(row + 1, col, ncols));
+ }
+
+ // west
+ if (col > 0 && walkable(lines, row, col - 1)) {
+ graph_add_edge(g, idx(row, col, ncols), idx(row, col - 1, ncols));
+ }
+}
+
+void read_grid(graph_t *g, size_t *start, char **lines, size_t nlines) {
+ size_t i, j;
+ size_t ncols = strlen(lines[0]) - 1;
+
+ graph_init(g, nlines * ncols);
+ for (i = 0; i < nlines; i++) {
+ for (j = 0; j < ncols; j++) {
+ if (lines[i][j] == '.' || lines[i][j] == 'S')
+ edge_adder(g, lines, nlines, ncols, i, j);
+ if (lines[i][j] == 'S')
+ *start = idx(i, j, ncols);
+ }
+ }
+}
diff --git a/day21/common.h b/day21/common.h
@@ -0,0 +1,23 @@
+#ifndef COMMON_H_
+#define COMMON_H_
+
+#include <assert.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/queue.h>
+
+#include <graph.h>
+#include <reading.h>
+#include <set_u64p.h>
+
+typedef struct entry {
+ size_t node;
+ size_t dist;
+
+ SIMPLEQ_ENTRY(entry) entries;
+} entry_t;
+
+void read_grid(graph_t *g, size_t *start, char **lines, size_t nlines);
+
+#endif
diff --git a/day21/exinput b/day21/exinput
@@ -0,0 +1,11 @@
+...........
+.....###.#.
+.###.##..#.
+..#.#...#..
+....#.#....
+.##..S####.
+.##..#...#.
+.......##..
+.##.#.####.
+.##..##.##.
+...........
diff --git a/day21/input b/day21/input
@@ -0,0 +1,131 @@
+...................................................................................................................................
+...............#.....#...#......#...............#.....#...#...........#..#....##.#..#.........#..............#...........#..#......
+........#.#..........#.##..#.......#.#.#.......#..#........................#............#...#....#.............#....#.........#....
+.....#......#...................#...#......#.............#..............#.#....#.......#...#...#......##.#.#...........#..###......
+.........#............#...##.........#.#....#........#..........................#....#.#......#......#....#....#............#.#....
+...#.....#................#.#..........#..........#.#.#...........#.......#..............#......#.......##.....#.........##.#......
+..........#....................#............#........#............#............#....#..........#.........................#.........
+...#.#...................#.#......##..#........#.##.....................................#........##............#.##....#...........
+.........................................#...#.......................#...........................#..#........#....##.#...##........
+...#.......#...#.......#..#.#.......#.......#........................#........#....#....#...#.#.....#...#...........#........##.#..
+..#....#.............#........................#..##.............................#..#.................#....##.......#.......#....#..
+.........................#.......#...#...........#..................#..............#.#....#.....#...#........#...........#......#..
+............#..................#...#.......#...#.#.........#.......................#............#.......#....#.....#..........#....
+..........#........#......##.#.....#...#................#....##...........#................#.......#........#......#...#....#..#...
+.................#.......................##...............#.....#.....#............#.................#..........#......#.....#.....
+.....#.###................#..........#...................#.##........#...............#....#...............#..#................#.#..
+.#..#..........#..................#...................................#......#.................#.#..................#..............
+..........#..#...#.#...........#.#..#....................#....................#..........#.#.#.....#....#...........#........#.....
+.#.............#.......##.##.........#.#..............#.......#.............#.........................................#....#.#.....
+.............#.....#.#........#..........#..............#.....................#..................#..#........#.#.....#...#.........
+....#.......#..............#.....#.......#...........#.............#.##..................#.................#..#......#.#...#....#..
+..#....#.....#......................#.....................#..........#..##........#.........#.............#......#.................
+...##.......#.......#...#..##..................#.........##....................#.#...................................#..#..........
+........#.........#..##........................#......#........#...#...#........#......................................#.......#...
+....#..#....#.#.#.................#.............#.........#.............#....#................#..#.....#...##.....#.........##.....
+...................#................#...............................#.................#...........#.....##.#.......................
+.....#........#........#........................#..............#.............................................#........#...#........
+.......#............#.................................#.......#........#...#..............................#.....#.#.#......#.#.#...
+.....................###....#.#................#.#....#........##.#..#.......#...#............................#..........###....#..
+.#.....##.#......#.#........#.#..............#...............#.........#.........#.....#...........#.............................#.
+...#.....#...........#.#......#................#..#....#...#..#......#................#....#.............#.#....#..................
+..#....##......#.............#...............#.................................#.......#................#...........#.#............
+..........#....#....##.......................#.#.#..................#.....#..............#................#..................#.....
+.....#......................................#....#......................#..........#........#........................#.............
+..#.#..#........#...#..#...................#............#..#...#......#.#...#............#.....#...............#..............#....
+..#....#..##..........#...........#......................##................#...#...............................#..#....#........#..
+......#........#...................#.#.......#..#.#....#..##...#.........##......#....#..........#....................#....#.......
+.#.##.....#.....#..................#.....#..#..#....#....#......#...........#......#....#.........#........##..#.#..##.............
+........#..#.....#.....#.......#.#......................#..................#.#.......##...................................#..#.....
+..#........#.........................#.......#..............................#.....##.........#..#.##...............................
+..............................#....................#......................#.....#..#.............................#..........#......
+........#.#.....................#......#.....#.............##...............#....#.#...#..........................#...#....#.......
+........#...................#.#.##.##........................#.#........................#...............................#..#...#.#.
+.............##.................#......#.#.##.......#.........................#.......................#.................#..........
+..##.....#..........................##..........#....#.............................##.....###......#...........................#...
+...#.......#...#..............#................#.#.....#..#..................#..#...##....#....#.......#...........#.........#.....
+.....#.......#.........#..#.......##.............#.##...#.......#................#..........#............#.................#.......
+..............#..........##....................#......#...##..................................#.#.......#.#..............#.........
+..#.....#..#.#.............#................#......................#.#.................##.......###.#....#..............##.........
+....................#.........#...#............#.#......#..........#........#..........................#..#.#............##........
+.......#...#..........#.........#........#....#......###.......#..#.........##....#..............#.......#..#..........#...........
+.....##.#.................................#.....#.............#.#.......#..##.............#........................................
+.......#..................##.##..#............#......#...#....##........##.#................#....#..#..##..........................
+..##.#..............###..#........#...#...#.........#.....................#....#.......##............#...#..................#......
+....#..............#...........#.....##................##...##.......#...#....#...#............#..#..............................#.
+.........................#.........#..................##................#....#...#...........#......#..#....####.............#.....
+.....................#...#....#........#...........#..........#....................#..#..#..........#..............................
+.#..................#..................#........#............#.#..............#....#...............#........#....##............##..
+...............#....#.#.........#...#.......#...#.......#.......#................#.##................#.................#...........
+..............#.#.......#...#....#......#.............#...................##...#.......##......##..................................
+..........##.#..#.......##........#.##......#............#.#..##...............#...#.....#...#............#......#.................
+........#.#.#........................................##....#..#...............#.......##......#......#...........#..##.............
+......................................#........................#.........#.....#...................#...............................
+.........................#....#.......#...................#..#..#.#.....#..................#......##.......................#.......
+......#....#.......#.............#.........................#........#.#...#.....#..#....#......#....#.#.......#...........#........
+.................................................................S.................................................................
+...........#...#.....#......................#.......#.............#.#............#.##.#...#........#.......#........#.......##.....
+................#..#........#...#.....................#...............#...........................##.....#.........#...............
+.............##.##.#...#........#..#...#....................#...#.......................#............#.............................
+................#....#.#.#...#...............#...........#..............................##........................#................
+.......................................#.....#...........#.........#...................#..#..#.................#.........#.......#.
+..#...............#....#.#.#............................#.#..#............#.........#......#........#....#......................#..
+...#......................#....#.#....................##..........#......#...#........#....#.....................#.#...........#.#.
+...............#...#.................................##...#.#.......#...#...........#...................#...........#..............
+................#......#.............#.#...##...##......#......#..#..........#..#......#...........................................
+..................#.#.....#.##.....#....#..........................##.#.#....#.........#...#.....#........#...##.#...............#.
+........................#...#..............#....#.......#......#......#......#..#...............##.............##..................
+..#...##.............#..................#....#.......................#..........#...##......................#..#..#..........#...#.
+....##.#..........#...#..........#.......#...#............#.#.........#..#...#.#.......##......#..###..#.........#.................
+.........#.............#...#..........#........#..##..................#..#.........................#.....#...#..............#......
+.......#...#.............#.#....###................#...#.................#.#.............#..................##...............#.....
+....#....##..............#......#.....#.....#...#..#............#...##.......#.#....#...#........##.#..#...............#...#.......
+.#..#....#............#.........#...........#......#...#............#...........#......##....#........#..........................#.
+....###...#.................#.......#............#.#.........#...................#.##............#....................#............
+........#...............................#..........#................#......#....#.............#..........##..........#.....#..##...
+....#.....###...................##..##.##...#..##...##...#....#.......#..................#........#..#...................#.........
+..#.#............#................#...#.#.......#.........#.....#.#.....#.............#.....#..#.....................#..##.........
+............#.#..#....................#.....#..........#.#...................#....................#..#.......................#..#..
+....#....#.....#..................##................#..#...#.......##...............#.....##..#................#..##..##...#.......
+..................#..............................##................#....#....#........................................#...#...##...
+.............##........................#....#........##......#.............#.#...#................#..........#..#.#.....#.......#..
+....#.#..#...#..#..................#..#..#..#.#......#..#..#.#.....####......#...........##.#....#..#..............#............#..
+.#...#.................................#............##...#....................#.#..#....#.......#................#..#..........#...
+..#.................#.................#...................#.#.......#....#...............#......#.#...............#................
+......###.....#.........#.................#.#.............#..#..#.......#.....#.............................#....##..##..#.........
+..........###....#.#.#....#........#............###..#.........#....#...........#.......#......#........#......#....#............#.
+.....##...#.#.##....................##...#.#..#......#.......#......#...#........#.....................#.......#......#.....##.....
+.#.....#..#...............................#....#.................................##...................#.......#...............#....
+.....................##.....#...................#......................#.#..#................................##....................
+....#....#..........#........#.........#...##..........#.....#..#..#.............#..##....................................#........
+..........#.#.............#.................#............#.....#......#...............................#.................#....#.#...
+......#...#.#.....#.#.##..#.#............###....#.....#................##......#.......#..#....................#.....#.............
+.....#....#....................#.....................#..........#.....#.............#..#.......................#.#.................
+......#....#...............................#...#........#.......................#....................##...#..#......#...##....#....
+....#..............#...........#................#.#......#........##...#..#....###..................#.........#.............#......
+......#....#....#.....#..##.#.#.............##.......#.......#....#...##..........................#....###...#...#.............#...
+.#....##......#........#.#..........#..........................................#................#..................#...............
+..#......#...#....#.......##.....#.....................#.....#.#..#...#...#......#.......................................#..#......
+......#..............#.......#.#..........................#.............#.......#.#.............#......#....................#..#...
+..#...#.........................#.#....#............................#.....................#.....#.................#................
+...................##......#.....#.............................#......##....#............#...#......................#..............
+......#...#..#.##.............#........#..#.........##...#....#......#..#......#..........#...........#..........#.#..#.#..........
+.#..#..#.........#.......#.......#.........#..........##...##...#.#...#........................................#....#..............
+.#..#.#.#....#......#................#........................#.#.....#........................#...#......................#......#.
+...............##...............##....................#..#.#.........................#.......#.......#...........#............#....
+..........#.........#.#.............#....#..#.#.............##....#......#.#.........................#..#.....#.......#........#...
+....##......#...#.............................#...............#......#................#.....................................#......
+....###.#..#.......#...................#....#..........................#..#..................#.....#....#.....#................#.#.
+............#.#..#.#.###........##..#.##...........................#.................#.#.............#.............#.....##........
+..#......#................................#.#.....................#......................#........#.....#.....#.#...#.....#........
+.............#..........#.#.##......#..#....................##................................#..............#......#...........##.
+.....#...#..............#..#....#..#..............................#..........................#.###..............#...##.....##......
+.#...#..#.......#.#...............#....#.....#..#....#..............#...................................................#.#.#......
+.......##.........#.#....#...........#.....#....#...............#....................#..................##......#........#.........
+...#.#.....#....#.................#..#................#........#..................#......#............#....#...........#..#........
+.....#...#..................#.......#.........#...#....#...................#...##..#.#....#....#.##..#..##.##..................#...
+.....................#..#...#.....#............#..........................#.##.....................#..#...#......##.....#.....#....
+..#........#.......##.#..............#..##................................#..#.#....#.....#...............#.................#.#....
+...#.................................#.........#...........................#....##.#...................#......##.................#.
+.........#..........#.#......#....##....#.#...#.........#................................#....#..#..............#....##...#........
+...................................................................................................................................
diff --git a/day21/uppga.c b/day21/uppga.c
@@ -0,0 +1,57 @@
+#include "common.h"
+
+static inline uint64_t nsize(graph_t *g, size_t start, size_t nsteps) {
+ size_t i;
+ SIMPLEQ_HEAD(listead, entry) head = SIMPLEQ_HEAD_INITIALIZER(head);
+ uint64_t count = 0;
+ entry_t *e = malloc(sizeof(*e));
+
+ e->node = start;
+ e->dist = 0;
+ SIMPLEQ_INSERT_TAIL(&head, e, entries);
+
+ set_u64p_t added;
+ set_u64p_init(&added);
+ uint64_t pp[2] = {e->node, e->dist};
+ le_t tt;
+ set_u64p_insert(&added, pp);
+
+ while (!SIMPLEQ_EMPTY(&head)) {
+ e = SIMPLEQ_FIRST(&head);
+ SIMPLEQ_REMOVE_HEAD(&head, entries);
+
+ if (e->dist < nsteps) {
+ for (i = 0; i < g->nbrs[e->node].nmemb; i++) {
+ pp[0] = g->nbrs[e->node].data[i];
+ pp[1] = e->dist + 1;
+ if (set_u64p_lookup(&tt, &added, pp) == SIZE_MAX) {
+ set_u64p_insert(&added, pp);
+ entry_t *ne = malloc(sizeof(*e));
+ ne->node = g->nbrs[e->node].data[i];
+ ne->dist = e->dist + 1;
+ SIMPLEQ_INSERT_TAIL(&head, ne, entries);
+ }
+ }
+ } else if (e->dist == nsteps) {
+ count++;
+ }
+
+ free(e);
+ }
+
+ set_u64p_clear(&added);
+
+ return count;
+}
+
+int main(int argc, char **argv) {
+ char **lines;
+ size_t nlines = readlines(&lines, "input");
+
+ graph_t g;
+ size_t start;
+ read_grid(&g, &start, lines, nlines);
+
+ uint64_t count = nsize(&g, start, 64);
+ printf("%llu\n", count);
+}
diff --git a/day21/uppgb.c b/day21/uppgb.c
@@ -0,0 +1,129 @@
+#include "common.h"
+
+static inline void bfsl(uint8_t *hitv, uint64_t *hitd, graph_t *g, size_t start,
+ size_t lmt, size_t nr, size_t nc) {
+ size_t i;
+ SIMPLEQ_HEAD(listead, entry) head = SIMPLEQ_HEAD_INITIALIZER(head);
+
+ entry_t *e = malloc(sizeof(*e));
+ e->node = start;
+ e->dist = 0;
+ SIMPLEQ_INSERT_TAIL(&head, e, entries);
+
+ while (!SIMPLEQ_EMPTY(&head)) {
+ e = SIMPLEQ_FIRST(&head);
+ SIMPLEQ_REMOVE_HEAD(&head, entries);
+
+ if (e->dist < lmt) {
+ for (i = 0; i < g->nbrs[e->node].nmemb; i++) {
+ if (hitv[g->nbrs[e->node].data[i]] == 0) {
+ entry_t *ne = malloc(sizeof(*e));
+ ne->node = g->nbrs[e->node].data[i];
+ ne->dist = e->dist + 1;
+ hitv[ne->node] = 1;
+ hitd[ne->node] = ne->dist;
+ SIMPLEQ_INSERT_TAIL(&head, ne, entries);
+ }
+ }
+ }
+
+ free(e);
+ }
+}
+
+typedef struct u64p {
+ uint64_t x;
+ uint64_t y;
+} u64p_t;
+
+static inline u64p_t hitt(uint8_t *hitv, uint64_t *hitd, size_t nr, size_t nc) {
+ uint64_t ho = 0;
+ uint64_t he = 0;
+ size_t i;
+
+ for (i = 0; i < nr * nc; i++) {
+ if (hitv[i] == 1) {
+ if (hitd[i] % 2 == 0) {
+ he++;
+ } else {
+ ho++;
+ }
+ }
+ }
+
+ return (u64p_t){ho, he};
+}
+
+static inline u64p_t hlong(uint8_t *hitv, uint64_t *hitd, size_t nr, size_t nc,
+ size_t v) {
+ uint64_t ho = 0;
+ uint64_t he = 0;
+ size_t i;
+
+ for (i = 0; i < nr * nc; i++) {
+ if (hitv[i] == 1 && hitd[i] > v) {
+ if (hitd[i] % 2 == 0) {
+ he++;
+ } else {
+ ho++;
+ }
+ }
+ }
+
+ return (u64p_t){ho, he};
+}
+
+/**
+ * This function asserts the magic properties we need
+ * to hold (magic in the sense as not in the specification,
+ * but perhaps observable) for this solution to be
+ * correct. I detest this non-general heuristic shit...
+ */
+static inline void assert_magic(char **lines, uint64_t nr, uint64_t nc,
+ u64p_t start, uint64_t steps) {
+ assert(start.x == nr / 2);
+ assert(start.y == nc / 2);
+ assert(nr == nc);
+ assert(nr == 131);
+ assert(steps % nr == nr / 2);
+
+ assert(lines[start.x][start.y] == 'S');
+
+ size_t i;
+ // S is on clear row/col!!!
+ for (i = 0; i < nr; i++) {
+ assert(lines[i][start.y] == '.' || lines[i][start.y] == 'S');
+ assert(lines[start.x][i] == '.' || lines[start.x][i] == 'S');
+ }
+}
+
+int main(int argc, char **argv) {
+ char **lines;
+ size_t i;
+ size_t nr = readlines(&lines, "input");
+ size_t nc = strlen(lines[0]) - 1;
+ uint64_t steps = 26501365;
+
+ uint8_t hitv[nr * nc];
+ memset(hitv, 0, nr * nc);
+ uint64_t hitd[nr * nc];
+ for (i = 0; i < nr * nc; i++)
+ hitd[i] = UINT64_MAX;
+
+ u64p_t sstart = {65, 65};
+ assert_magic(lines, nr, nc, sstart, steps);
+
+ graph_t g;
+ size_t start;
+ read_grid(&g, &start, lines, nc);
+
+ bfsl(hitv, hitd, &g, start, 131, nr, nc);
+
+ u64p_t c = hitt(hitv, hitd, nr, nc);
+ u64p_t uh = hlong(hitv, hitd, nr, nc, 65);
+
+ uint64_t x = steps / nr;
+ uint64_t v =
+ c.x * (x + 1) * (x + 1) + c.y * x * x - (x + 1) * uh.x + x * uh.y;
+ printf("%llu\n", v);
+}
diff --git a/day22/Makefile b/day22/Makefile
@@ -0,0 +1,30 @@
+CC=clang
+CFLAGS+=-std=c99 -pedantic -Wall -Werror -Wstrict-prototypes
+CFLAGS+=-Wmissing-prototypes -Wmissing-declarations -Wshadow
+CFLAGS+=-Wpointer-arith -Wcast-qual -Wsign-compare
+CFLAGS+=-O2 -g
+CFLAGS+=-fstack-protector-all -Wtype-limits -fno-common
+CFLAGS+=-fno-builtin
+CFLAGS+=-I/usr/local/include
+CFLAGS+=-I../utils
+#LDFLAGS=
+
+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) $(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)
+
+utils:
+ make -C ../utils
+
+clean:
+ rm -rf common.o uppga uppgb
diff --git a/day22/common.c b/day22/common.c
@@ -0,0 +1,92 @@
+#include "common.h"
+
+static inline void order_interval(iv_t *iv) {
+ if (iv->lb > iv->ub) {
+ uint64_t tmp = iv->ub;
+ iv->ub = iv->lb;
+ iv->lb = tmp;
+ }
+}
+
+static inline void order_brick(brick_t *b) {
+ size_t i;
+ for (i = 0; i < 3; i++)
+ order_interval(&(b->ivs[i]));
+}
+
+static int brick_cmp_z(const void *a, const void *b) {
+ const brick_t *aa = (const brick_t *)a;
+ const brick_t *bb = (const brick_t *)b;
+
+ return aa->ivs[2].lb < bb->ivs[2].lb ? -1 : 1;
+}
+
+void sort_bricks(brick_t *bricks, const size_t n) {
+ qsort(bricks, n, sizeof(bricks[0]), brick_cmp_z);
+}
+
+void read_bricks(brick_t *bricks, char **lines, const size_t nlines) {
+ size_t i;
+ char *cp;
+
+ for (i = 0; i < nlines; i++) {
+ cp = lines[i];
+ cp = sread_next_u64(&bricks[i].ivs[0].lb, cp);
+ assert(cp != NULL);
+ cp = sread_next_u64(&bricks[i].ivs[1].lb, cp);
+ assert(cp != NULL);
+ cp = sread_next_u64(&bricks[i].ivs[2].lb, cp);
+ assert(cp != NULL);
+ cp = sread_next_u64(&bricks[i].ivs[0].ub, cp);
+ assert(cp != NULL);
+ cp = sread_next_u64(&bricks[i].ivs[1].ub, cp);
+ assert(cp != NULL);
+ cp = sread_next_u64(&bricks[i].ivs[2].ub, cp);
+
+ order_brick(&bricks[i]);
+ }
+}
+
+static inline int iv_nei(const iv_t *a, const iv_t *b) {
+ return (a->lb <= b->ub) && (b->lb <= a->ub);
+}
+
+int brick_nei(const brick_t *a, const brick_t *b) {
+ return iv_nei(&(a->ivs[0]), &(b->ivs[0])) &&
+ iv_nei(&(a->ivs[1]), &(b->ivs[1])) &&
+ iv_nei(&(a->ivs[2]), &(b->ivs[2]));
+}
+
+void gravitize(brick_t *a) {
+ a->ivs[2].lb--;
+ a->ivs[2].ub--;
+}
+
+int may_gravitize(const brick_t *a, const brick_t *landed,
+ const size_t nlanded) {
+ size_t i;
+
+ if (a->ivs[2].lb <= 1)
+ return 0;
+
+ brick_t b = *a;
+ gravitize(&b);
+
+ for (i = 0; i < nlanded; i++) {
+ if (brick_nei(&b, &landed[i]))
+ return 0;
+ }
+
+ return 1;
+}
+
+void gravitize_all(brick_t *bricks, const size_t n) {
+ // assume sorted by l.b. on z, increasingly
+ size_t i;
+
+ for (i = 0; i < n; i++) {
+ while (may_gravitize(&bricks[i], bricks, i)) {
+ gravitize(&bricks[i]);
+ }
+ }
+}
diff --git a/day22/common.h b/day22/common.h
@@ -0,0 +1,29 @@
+#ifndef COMMON_H_
+#define COMMON_H_
+
+#include <assert.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <reading.h>
+#include <stack_u64.h>
+
+typedef struct interval {
+ uint64_t lb;
+ uint64_t ub;
+} iv_t;
+
+typedef struct brick {
+ iv_t ivs[3];
+} brick_t;
+
+void read_bricks(brick_t *bricks, char **lines, const size_t nlines);
+void sort_bricks(brick_t *bricks, const size_t n);
+void gravitize(brick_t *a);
+int may_gravitize(const brick_t *a, const brick_t *landed,
+ const size_t nlanded);
+void gravitize_all(brick_t *bricks, const size_t n);
+int brick_nei(const brick_t *a, const brick_t *b);
+
+#endif
diff --git a/day22/exinput b/day22/exinput
@@ -0,0 +1,7 @@
+1,0,1~1,2,1
+0,0,2~2,0,2
+0,2,3~2,2,3
+0,0,4~0,2,4
+2,0,5~2,2,5
+0,1,6~2,1,6
+1,1,8~1,1,9
diff --git a/day22/input b/day22/input
@@ -0,0 +1,1203 @@
+7,3,85~9,3,85
+2,8,123~4,8,123
+8,2,69~8,2,72
+3,1,280~3,4,280
+4,1,6~4,2,6
+7,1,156~7,3,156
+1,5,105~4,5,105
+5,8,69~5,8,69
+5,0,255~5,3,255
+2,8,120~3,8,120
+3,3,202~5,3,202
+0,5,80~2,5,80
+5,9,123~6,9,123
+6,1,249~9,1,249
+9,4,100~9,6,100
+4,4,124~6,4,124
+3,4,222~3,4,223
+4,5,284~4,8,284
+3,5,44~5,5,44
+3,2,132~3,5,132
+5,2,127~7,2,127
+0,2,11~0,3,11
+4,7,151~5,7,151
+0,3,232~0,5,232
+0,9,34~3,9,34
+2,1,195~4,1,195
+0,0,50~0,3,50
+6,4,234~6,7,234
+3,5,234~3,6,234
+5,2,213~8,2,213
+4,2,223~4,5,223
+8,3,9~8,4,9
+2,2,292~2,4,292
+5,7,261~6,7,261
+4,5,263~4,7,263
+7,0,137~9,0,137
+6,0,4~6,0,4
+2,7,282~4,7,282
+9,3,291~9,4,291
+0,8,163~2,8,163
+4,9,111~7,9,111
+3,7,104~4,7,104
+9,0,34~9,3,34
+1,5,57~3,5,57
+8,5,214~9,5,214
+9,5,279~9,8,279
+2,4,206~4,4,206
+5,1,136~5,2,136
+1,2,219~1,3,219
+4,2,143~6,2,143
+4,8,195~6,8,195
+5,1,85~8,1,85
+4,4,10~4,4,11
+5,6,91~8,6,91
+1,6,51~1,6,51
+3,9,237~5,9,237
+3,5,264~3,6,264
+7,3,232~9,3,232
+4,1,192~6,1,192
+2,2,232~5,2,232
+7,4,287~7,7,287
+4,8,63~4,9,63
+3,5,295~6,5,295
+4,6,39~4,9,39
+8,7,217~8,9,217
+6,7,229~8,7,229
+4,4,184~4,5,184
+6,3,236~8,3,236
+8,6,13~9,6,13
+0,3,12~0,4,12
+5,7,9~5,7,12
+1,3,151~1,5,151
+3,9,71~4,9,71
+2,8,60~4,8,60
+3,2,102~3,5,102
+3,6,26~6,6,26
+4,7,113~4,9,113
+7,1,268~7,1,270
+3,4,69~5,4,69
+7,6,165~9,6,165
+7,7,131~7,9,131
+8,5,74~8,7,74
+1,8,222~4,8,222
+3,3,189~3,5,189
+5,6,215~5,8,215
+5,5,111~6,5,111
+2,8,57~5,8,57
+3,3,101~3,4,101
+7,1,252~8,1,252
+0,0,2~3,0,2
+0,5,86~0,7,86
+7,1,229~9,1,229
+0,6,124~2,6,124
+8,3,32~9,3,32
+8,5,229~8,6,229
+7,4,285~7,6,285
+6,3,187~6,6,187
+2,5,237~4,5,237
+2,1,294~4,1,294
+1,5,241~3,5,241
+3,2,4~3,5,4
+0,4,44~3,4,44
+5,4,74~5,6,74
+4,7,154~6,7,154
+5,0,80~6,0,80
+2,2,234~2,4,234
+5,3,57~5,6,57
+8,3,148~8,5,148
+1,7,60~2,7,60
+0,0,3~0,0,4
+4,6,84~4,8,84
+6,0,140~7,0,140
+1,6,252~1,7,252
+3,7,276~3,9,276
+7,8,1~8,8,1
+3,5,187~4,5,187
+3,6,29~3,9,29
+2,1,233~4,1,233
+3,3,133~5,3,133
+5,6,128~5,6,131
+2,2,235~4,2,235
+2,4,7~4,4,7
+1,1,260~1,3,260
+8,7,176~9,7,176
+7,7,64~8,7,64
+4,8,10~6,8,10
+0,1,234~3,1,234
+3,7,33~3,9,33
+7,7,71~7,9,71
+0,5,179~1,5,179
+3,2,32~5,2,32
+5,7,3~7,7,3
+6,1,258~9,1,258
+5,4,258~5,7,258
+2,6,217~2,8,217
+0,4,131~0,4,133
+8,0,242~8,0,244
+9,4,262~9,7,262
+2,5,6~5,5,6
+8,3,159~8,5,159
+4,2,78~7,2,78
+6,0,235~8,0,235
+5,4,64~5,4,66
+6,4,273~6,6,273
+7,2,138~7,3,138
+1,0,6~4,0,6
+7,3,154~7,4,154
+9,1,39~9,4,39
+5,5,168~5,7,168
+1,5,41~3,5,41
+1,2,50~1,5,50
+4,2,259~6,2,259
+0,0,218~0,3,218
+5,6,40~8,6,40
+7,9,236~9,9,236
+8,4,6~8,7,6
+2,4,30~2,6,30
+0,7,221~0,7,222
+7,1,202~7,1,202
+4,2,181~4,5,181
+5,0,283~7,0,283
+4,6,238~5,6,238
+4,2,67~6,2,67
+2,7,228~2,9,228
+0,6,164~0,9,164
+1,2,193~3,2,193
+3,9,129~6,9,129
+7,3,266~9,3,266
+3,5,75~4,5,75
+0,9,37~1,9,37
+2,1,50~2,4,50
+0,4,2~0,6,2
+4,2,207~4,2,207
+3,1,108~3,2,108
+6,9,201~8,9,201
+7,6,176~8,6,176
+8,6,73~8,8,73
+6,9,69~8,9,69
+2,2,181~2,5,181
+9,4,232~9,7,232
+3,4,114~4,4,114
+3,3,225~3,5,225
+0,7,179~0,9,179
+0,5,109~2,5,109
+9,6,92~9,9,92
+9,1,96~9,2,96
+7,6,99~8,6,99
+6,3,116~6,5,116
+1,2,46~1,4,46
+4,8,87~5,8,87
+1,4,59~3,4,59
+0,1,163~0,3,163
+9,8,176~9,9,176
+3,5,28~3,5,29
+6,4,90~6,6,90
+5,9,133~7,9,133
+3,8,85~5,8,85
+8,3,244~8,4,244
+6,3,204~9,3,204
+2,2,295~4,2,295
+1,3,182~3,3,182
+3,0,122~4,0,122
+3,2,225~6,2,225
+0,6,166~2,6,166
+1,4,53~1,5,53
+1,2,88~1,2,90
+6,8,236~8,8,236
+3,2,141~3,3,141
+7,6,102~7,7,102
+9,3,215~9,5,215
+6,2,110~6,4,110
+5,0,287~7,0,287
+1,8,194~4,8,194
+2,2,8~2,4,8
+2,5,216~5,5,216
+5,8,186~7,8,186
+0,1,240~0,3,240
+1,3,295~3,3,295
+9,4,274~9,5,274
+3,4,249~3,6,249
+2,4,244~2,6,244
+4,9,68~4,9,68
+1,2,237~4,2,237
+8,1,141~9,1,141
+4,0,142~6,0,142
+8,1,124~8,3,124
+4,2,285~4,4,285
+1,2,192~1,4,192
+1,8,225~3,8,225
+6,3,203~6,6,203
+4,2,116~6,2,116
+4,6,177~4,8,177
+1,0,108~1,1,108
+9,1,40~9,3,40
+9,4,293~9,6,293
+5,1,231~5,2,231
+5,2,13~5,2,16
+6,0,219~7,0,219
+2,0,119~3,0,119
+7,3,238~7,3,241
+7,5,257~7,6,257
+2,8,146~5,8,146
+3,1,224~5,1,224
+3,1,158~3,3,158
+2,1,78~2,3,78
+4,4,9~7,4,9
+3,3,277~3,5,277
+5,6,134~7,6,134
+6,5,43~6,7,43
+7,2,198~7,5,198
+4,4,62~7,4,62
+6,2,136~8,2,136
+7,1,203~9,1,203
+2,9,231~5,9,231
+3,0,5~5,0,5
+4,3,127~4,5,127
+6,7,200~6,9,200
+3,6,118~6,6,118
+6,0,271~6,2,271
+3,0,200~3,1,200
+7,5,259~9,5,259
+5,4,39~5,7,39
+3,8,117~5,8,117
+0,3,299~0,4,299
+7,0,130~7,3,130
+8,0,121~8,1,121
+2,5,161~2,8,161
+8,0,28~8,1,28
+0,1,257~1,1,257
+7,2,263~7,4,263
+8,5,285~8,7,285
+3,0,221~3,2,221
+9,3,256~9,6,256
+1,7,164~1,9,164
+0,9,247~1,9,247
+5,7,282~6,7,282
+2,3,46~2,5,46
+6,2,83~7,2,83
+1,7,196~1,9,196
+9,0,35~9,1,35
+0,2,263~3,2,263
+4,7,82~5,7,82
+0,2,265~0,2,266
+6,4,13~7,4,13
+6,1,266~9,1,266
+5,3,226~5,5,226
+8,3,52~8,5,52
+2,1,150~2,3,150
+0,2,152~3,2,152
+7,2,2~7,2,2
+9,0,140~9,1,140
+4,3,252~4,5,252
+7,8,133~9,8,133
+4,9,131~4,9,131
+0,3,248~0,6,248
+1,7,51~3,7,51
+0,5,175~0,8,175
+9,2,102~9,3,102
+2,4,127~2,4,129
+1,5,1~1,5,3
+4,6,226~7,6,226
+1,7,134~3,7,134
+6,4,61~6,7,61
+3,6,2~5,6,2
+2,6,61~4,6,61
+4,3,89~4,4,89
+6,6,230~7,6,230
+8,0,15~8,0,17
+3,3,220~3,6,220
+8,4,145~8,7,145
+3,7,279~3,7,280
+0,1,132~0,1,133
+8,5,95~8,7,95
+6,6,210~6,8,210
+8,1,44~9,1,44
+7,4,3~9,4,3
+2,1,101~2,4,101
+2,1,12~2,3,12
+0,3,225~0,6,225
+1,1,227~3,1,227
+3,9,170~5,9,170
+5,0,241~6,0,241
+3,5,26~5,5,26
+2,7,213~4,7,213
+2,9,183~4,9,183
+7,0,218~7,2,218
+3,6,267~3,6,269
+9,4,11~9,6,11
+8,0,234~8,2,234
+2,5,108~3,5,108
+4,9,234~4,9,236
+9,4,91~9,7,91
+1,0,226~4,0,226
+1,0,199~1,2,199
+0,5,178~0,6,178
+5,8,100~7,8,100
+4,5,212~6,5,212
+3,3,201~7,3,201
+3,6,285~3,9,285
+7,2,245~7,4,245
+0,1,201~0,3,201
+5,5,217~7,5,217
+3,6,31~3,6,33
+4,2,242~6,2,242
+1,3,242~1,5,242
+8,4,274~8,5,274
+0,0,124~0,0,127
+4,3,258~4,3,261
+4,7,198~4,9,198
+4,1,244~4,3,244
+0,0,159~1,0,159
+7,3,253~7,6,253
+6,9,70~8,9,70
+0,8,240~2,8,240
+8,6,260~8,7,260
+5,5,249~7,5,249
+6,8,269~6,9,269
+7,9,186~7,9,186
+4,4,190~4,6,190
+1,3,51~1,5,51
+3,5,195~4,5,195
+7,0,84~7,2,84
+8,3,221~8,6,221
+1,0,205~4,0,205
+4,2,111~4,4,111
+3,2,268~6,2,268
+5,5,147~7,5,147
+4,9,204~7,9,204
+3,7,167~3,9,167
+7,0,215~7,3,215
+8,5,257~8,8,257
+0,4,227~0,5,227
+5,6,151~5,6,151
+4,4,260~6,4,260
+3,2,52~3,4,52
+7,3,17~8,3,17
+5,7,46~5,9,46
+5,2,203~5,3,203
+0,5,81~0,5,83
+5,2,62~5,3,62
+6,2,280~9,2,280
+2,4,230~2,5,230
+3,3,154~3,4,154
+4,8,270~6,8,270
+6,9,160~8,9,160
+9,0,1~9,2,1
+9,5,173~9,8,173
+3,7,249~5,7,249
+2,0,268~2,3,268
+0,9,200~0,9,202
+3,5,63~3,6,63
+6,9,230~9,9,230
+3,2,228~6,2,228
+3,1,207~5,1,207
+8,5,208~9,5,208
+3,4,128~4,4,128
+2,7,30~4,7,30
+0,1,291~3,1,291
+7,0,141~9,0,141
+6,2,125~6,4,125
+0,4,119~3,4,119
+4,4,231~5,4,231
+0,9,186~2,9,186
+9,3,101~9,5,101
+3,5,109~4,5,109
+6,8,214~6,9,214
+0,2,38~2,2,38
+2,5,137~3,5,137
+1,7,143~1,7,143
+1,7,166~1,9,166
+5,5,264~5,8,264
+2,2,238~2,3,238
+0,3,122~0,5,122
+3,3,144~3,3,147
+9,0,36~9,2,36
+7,1,267~9,1,267
+4,3,33~6,3,33
+2,2,18~5,2,18
+4,1,177~6,1,177
+1,0,254~1,2,254
+4,6,64~6,6,64
+5,8,212~8,8,212
+0,4,249~0,5,249
+5,3,256~5,3,257
+2,2,266~2,4,266
+6,6,50~6,6,52
+1,3,11~1,4,11
+7,5,207~8,5,207
+3,6,65~3,6,67
+1,2,2~4,2,2
+9,0,281~9,2,281
+7,2,157~8,2,157
+3,1,203~5,1,203
+5,5,169~6,5,169
+1,0,203~3,0,203
+4,8,97~7,8,97
+3,6,55~6,6,55
+0,8,246~1,8,246
+3,1,82~5,1,82
+2,6,53~2,8,53
+4,1,271~4,3,271
+8,1,100~8,4,100
+1,1,93~1,4,93
+0,5,139~1,5,139
+5,6,149~5,8,149
+9,9,130~9,9,133
+7,6,70~9,6,70
+0,6,251~0,8,251
+3,2,34~5,2,34
+0,9,240~1,9,240
+6,8,238~8,8,238
+9,0,88~9,0,90
+5,8,228~7,8,228
+4,6,286~4,9,286
+0,1,51~3,1,51
+4,1,112~4,2,112
+4,5,108~6,5,108
+8,4,92~8,4,94
+4,6,210~4,6,211
+2,4,249~2,5,249
+6,6,123~6,8,123
+6,2,254~6,2,256
+5,5,50~6,5,50
+4,5,128~6,5,128
+0,3,47~0,5,47
+4,5,8~4,7,8
+1,4,208~4,4,208
+5,3,13~6,3,13
+1,4,43~1,6,43
+2,8,61~3,8,61
+3,8,234~5,8,234
+1,0,27~1,3,27
+2,2,140~5,2,140
+7,0,105~9,0,105
+2,5,256~2,5,258
+0,2,63~0,4,63
+7,4,120~9,4,120
+5,7,236~7,7,236
+2,8,231~3,8,231
+5,1,270~5,2,270
+3,1,248~3,3,248
+7,6,95~7,8,95
+2,2,155~2,3,155
+2,4,140~2,5,140
+2,5,75~2,6,75
+1,7,195~4,7,195
+5,4,281~5,7,281
+9,0,93~9,2,93
+5,5,93~6,5,93
+6,5,144~8,5,144
+1,9,1~2,9,1
+1,5,204~1,5,204
+5,9,283~8,9,283
+1,3,75~1,6,75
+5,1,257~5,1,259
+0,6,281~2,6,281
+2,4,282~4,4,282
+4,6,209~4,7,209
+0,0,296~0,3,296
+5,7,269~5,9,269
+7,0,285~7,0,286
+6,4,138~6,5,138
+6,2,204~9,2,204
+1,1,109~1,2,109
+6,7,96~8,7,96
+7,1,200~7,3,200
+9,0,44~9,0,47
+6,8,241~8,8,241
+2,2,9~4,2,9
+2,0,118~2,2,118
+7,7,184~7,7,187
+6,4,118~7,4,118
+3,4,268~6,4,268
+3,2,240~6,2,240
+2,1,107~2,4,107
+7,3,65~7,5,65
+6,8,136~7,8,136
+6,0,273~8,0,273
+8,4,43~8,6,43
+2,7,104~2,9,104
+8,2,190~8,4,190
+1,6,194~3,6,194
+8,2,66~8,5,66
+6,2,144~6,2,147
+7,4,94~7,7,94
+3,3,205~3,3,207
+4,1,102~4,4,102
+2,3,38~2,6,38
+8,4,118~8,7,118
+8,2,60~8,5,60
+6,6,141~6,9,141
+3,6,197~3,6,198
+1,9,235~1,9,238
+9,6,109~9,6,110
+4,4,265~4,7,265
+3,2,135~3,2,137
+1,1,115~1,1,117
+3,4,134~5,4,134
+3,2,206~5,2,206
+2,2,289~3,2,289
+5,1,21~5,5,21
+4,9,271~5,9,271
+0,8,292~2,8,292
+1,5,111~1,6,111
+3,5,176~6,5,176
+8,1,253~8,1,256
+4,0,7~5,0,7
+0,0,94~3,0,94
+5,4,96~5,5,96
+6,6,72~6,9,72
+5,8,202~6,8,202
+2,7,215~4,7,215
+8,2,231~9,2,231
+0,8,40~0,9,40
+7,1,283~7,2,283
+7,3,3~7,3,5
+3,0,292~3,0,294
+7,0,134~7,4,134
+6,4,271~9,4,271
+4,8,161~7,8,161
+2,2,33~2,4,33
+6,0,276~6,1,276
+2,6,85~2,6,86
+1,1,58~3,1,58
+1,8,199~1,9,199
+0,9,43~0,9,45
+2,3,236~5,3,236
+2,4,220~2,5,220
+5,4,266~7,4,266
+1,4,250~1,5,250
+2,0,117~4,0,117
+0,0,206~2,0,206
+7,4,98~9,4,98
+7,3,155~8,3,155
+3,4,194~4,4,194
+5,1,174~6,1,174
+1,3,212~3,3,212
+0,3,9~2,3,9
+4,4,203~4,6,203
+0,8,219~2,8,219
+7,3,296~7,5,296
+3,5,274~3,8,274
+7,4,246~8,4,246
+6,3,186~6,5,186
+9,8,174~9,9,174
+1,5,199~1,7,199
+7,0,158~7,1,158
+1,5,202~1,5,202
+6,3,118~8,3,118
+6,0,239~8,0,239
+4,1,105~4,3,105
+1,2,86~3,2,86
+0,7,219~1,7,219
+5,1,246~5,2,246
+9,2,27~9,5,27
+0,0,227~1,0,227
+3,4,204~5,4,204
+0,4,197~2,4,197
+2,7,171~2,9,171
+8,0,34~8,1,34
+8,7,159~8,9,159
+6,2,150~8,2,150
+4,2,191~4,4,191
+6,0,249~8,0,249
+0,7,176~0,9,176
+7,6,162~7,8,162
+7,0,159~9,0,159
+4,7,214~4,8,214
+6,2,118~8,2,118
+1,3,96~1,3,98
+3,6,121~4,6,121
+7,5,250~7,6,250
+9,8,189~9,8,191
+0,9,46~0,9,47
+9,1,224~9,4,224
+7,7,265~7,8,265
+1,9,234~2,9,234
+3,4,120~5,4,120
+3,2,245~5,2,245
+4,0,225~4,1,225
+7,4,205~7,6,205
+4,7,223~4,9,223
+3,1,104~3,2,104
+0,1,251~2,1,251
+5,4,262~7,4,262
+9,0,232~9,1,232
+3,5,280~5,5,280
+7,3,16~7,5,16
+1,1,192~3,1,192
+1,7,245~1,9,245
+0,1,106~3,1,106
+8,6,79~8,7,79
+6,4,188~8,4,188
+6,2,155~6,3,155
+0,3,14~1,3,14
+4,4,275~4,6,275
+2,5,131~2,6,131
+7,0,63~7,2,63
+4,3,139~4,5,139
+4,6,205~4,6,206
+4,3,226~4,3,229
+0,1,86~2,1,86
+1,5,77~2,5,77
+5,5,23~5,6,23
+8,0,162~8,0,166
+3,8,248~5,8,248
+5,1,7~7,1,7
+4,7,103~4,9,103
+6,7,223~6,9,223
+0,9,244~2,9,244
+6,0,216~6,3,216
+3,9,226~4,9,226
+2,3,152~4,3,152
+4,6,136~6,6,136
+8,7,56~9,7,56
+2,0,59~5,0,59
+9,4,8~9,6,8
+0,4,229~0,7,229
+3,1,265~3,2,265
+5,1,27~5,1,29
+5,6,282~8,6,282
+6,2,62~8,2,62
+2,8,195~3,8,195
+2,6,247~2,7,247
+8,5,50~8,7,50
+0,0,89~0,2,89
+3,4,284~5,4,284
+6,6,128~6,7,128
+9,6,15~9,6,17
+2,1,119~3,1,119
+8,1,120~8,3,120
+9,6,160~9,7,160
+5,5,43~5,7,43
+8,7,183~8,8,183
+2,7,211~4,7,211
+4,4,143~4,5,143
+3,0,290~3,3,290
+2,2,219~3,2,219
+7,4,254~9,4,254
+9,0,207~9,1,207
+6,8,260~8,8,260
+8,2,276~8,4,276
+4,4,267~6,4,267
+1,2,125~1,5,125
+4,4,77~7,4,77
+4,7,178~7,7,178
+2,2,194~3,2,194
+7,5,252~7,7,252
+5,7,263~7,7,263
+7,3,218~9,3,218
+5,2,262~6,2,262
+4,7,51~5,7,51
+2,9,256~2,9,259
+2,4,123~2,4,124
+6,5,265~6,7,265
+3,7,179~3,9,179
+4,7,167~4,8,167
+2,1,19~2,3,19
+5,6,107~9,6,107
+3,7,247~3,8,247
+9,0,30~9,2,30
+6,5,173~6,8,173
+4,8,66~7,8,66
+9,0,86~9,3,86
+9,8,3~9,8,4
+6,3,242~9,3,242
+6,1,136~8,1,136
+0,7,133~2,7,133
+4,1,32~6,1,32
+0,2,183~2,2,183
+7,3,255~9,3,255
+8,2,230~8,4,230
+2,9,3~5,9,3
+9,1,29~9,4,29
+0,9,255~2,9,255
+0,7,75~3,7,75
+8,2,3~8,2,6
+9,5,184~9,7,184
+4,1,204~5,1,204
+9,4,230~9,6,230
+1,7,141~3,7,141
+2,6,231~4,6,231
+4,0,35~7,0,35
+4,9,110~6,9,110
+5,6,62~7,6,62
+0,5,247~3,5,247
+3,2,129~5,2,129
+2,0,271~5,0,271
+0,9,242~1,9,242
+3,0,120~5,0,120
+6,4,113~8,4,113
+5,6,256~8,6,256
+2,0,166~2,4,166
+1,2,186~4,2,186
+8,5,270~8,7,270
+5,0,195~7,0,195
+4,0,273~4,0,275
+3,7,114~5,7,114
+4,2,217~4,5,217
+0,4,201~0,6,201
+0,9,204~2,9,204
+4,3,32~4,5,32
+6,6,274~6,8,274
+3,7,228~3,8,228
+8,0,161~9,0,161
+4,5,224~4,7,224
+1,0,55~1,2,55
+5,8,101~7,8,101
+9,6,19~9,6,20
+6,0,264~7,0,264
+7,7,233~7,9,233
+2,3,136~4,3,136
+6,4,156~8,4,156
+5,1,269~5,2,269
+5,8,99~5,8,99
+5,8,28~7,8,28
+7,6,190~8,6,190
+0,3,217~1,3,217
+0,1,130~0,5,130
+1,2,63~3,2,63
+2,1,232~3,1,232
+0,5,137~0,7,137
+2,1,235~2,1,237
+4,4,65~4,5,65
+5,2,24~9,2,24
+4,7,234~5,7,234
+8,6,121~8,9,121
+1,6,282~1,6,285
+0,6,131~0,6,131
+1,6,44~1,6,47
+3,7,6~6,7,6
+4,9,106~4,9,108
+0,8,147~2,8,147
+2,2,217~2,4,217
+2,3,218~4,3,218
+8,4,55~9,4,55
+7,6,180~7,7,180
+2,1,87~2,3,87
+6,5,293~8,5,293
+5,4,228~7,4,228
+3,2,249~6,2,249
+5,4,126~7,4,126
+3,8,12~5,8,12
+1,8,287~3,8,287
+7,6,227~7,9,227
+9,2,126~9,4,126
+1,3,139~1,4,139
+3,0,201~6,0,201
+3,7,13~5,7,13
+4,6,274~4,8,274
+2,6,278~2,8,278
+0,3,159~2,3,159
+6,2,81~6,3,81
+0,6,172~0,8,172
+9,0,3~9,2,3
+0,3,250~0,3,252
+5,6,80~5,8,80
+6,4,96~7,4,96
+2,1,229~2,2,229
+1,6,82~3,6,82
+2,8,105~3,8,105
+6,7,157~9,7,157
+5,7,220~8,7,220
+4,0,278~4,0,281
+2,3,157~5,3,157
+2,4,99~5,4,99
+9,2,129~9,4,129
+0,1,197~3,1,197
+1,5,56~2,5,56
+6,5,8~6,8,8
+1,5,9~1,7,9
+4,7,232~6,7,232
+5,4,25~5,6,25
+7,1,3~8,1,3
+2,2,250~2,4,250
+3,2,29~5,2,29
+3,7,284~3,8,284
+1,7,228~1,8,228
+8,5,265~8,7,265
+8,7,51~8,7,53
+4,4,12~7,4,12
+0,3,49~2,3,49
+1,4,81~1,6,81
+1,3,265~1,3,268
+9,7,186~9,9,186
+6,8,217~6,9,217
+2,1,20~2,3,20
+4,6,96~7,6,96
+5,9,135~5,9,135
+8,2,31~9,2,31
+7,2,202~7,5,202
+7,1,234~7,3,234
+3,1,143~3,3,143
+4,8,102~4,9,102
+6,3,63~6,5,63
+2,5,135~5,5,135
+3,1,268~5,1,268
+1,6,138~1,7,138
+2,7,288~3,7,288
+7,2,151~7,4,151
+9,5,168~9,7,168
+0,4,190~2,4,190
+7,2,27~7,2,29
+8,1,206~9,1,206
+6,0,135~6,3,135
+2,8,165~2,8,166
+5,0,265~6,0,265
+3,2,113~5,2,113
+7,5,212~7,7,212
+0,1,185~0,2,185
+0,1,56~0,3,56
+7,5,7~8,5,7
+5,3,59~8,3,59
+0,3,141~0,6,141
+4,5,177~7,5,177
+0,9,198~3,9,198
+7,5,227~9,5,227
+4,8,267~6,8,267
+8,7,59~8,7,61
+0,2,243~0,4,243
+1,7,80~2,7,80
+6,1,64~6,3,64
+1,6,286~1,7,286
+4,5,240~4,5,242
+6,1,277~6,3,277
+9,3,6~9,7,6
+6,9,238~8,9,238
+5,1,30~6,1,30
+6,4,272~6,6,272
+5,4,85~5,7,85
+1,4,14~1,6,14
+5,5,200~6,5,200
+6,5,183~6,9,183
+0,0,58~2,0,58
+4,1,85~4,1,87
+3,5,141~4,5,141
+5,3,277~5,3,279
+7,6,51~7,8,51
+3,9,130~5,9,130
+5,1,84~5,3,84
+9,4,277~9,6,277
+9,0,87~9,2,87
+1,3,149~3,3,149
+2,4,40~4,4,40
+8,5,213~8,8,213
+6,4,289~9,4,289
+0,3,193~2,3,193
+9,7,171~9,9,171
+7,9,134~9,9,134
+1,7,218~2,7,218
+2,6,36~6,6,36
+0,8,148~3,8,148
+3,8,176~6,8,176
+8,6,69~8,7,69
+6,5,6~6,6,6
+0,1,54~0,3,54
+2,1,60~2,3,60
+1,1,205~5,1,205
+2,6,58~2,8,58
+2,7,170~3,7,170
+6,7,98~6,7,100
+5,0,33~7,0,33
+2,5,179~4,5,179
+1,0,83~1,2,83
+4,2,211~6,2,211
+0,0,239~0,2,239
+3,7,115~3,8,115
+3,7,165~6,7,165
+7,0,32~9,0,32
+0,7,106~3,7,106
+0,6,6~0,8,6
+0,0,157~0,1,157
+6,8,138~8,8,138
+8,8,3~8,9,3
+8,2,63~8,3,63
+1,1,111~1,1,114
+4,2,12~6,2,12
+0,7,169~1,7,169
+6,0,2~7,0,2
+7,7,70~8,7,70
+1,0,111~2,0,111
+0,5,253~2,5,253
+2,3,122~2,6,122
+6,5,53~6,7,53
+6,4,261~6,5,261
+2,2,283~4,2,283
+2,5,228~2,6,228
+4,5,225~6,5,225
+1,6,136~1,8,136
+7,5,110~7,6,110
+8,0,281~8,0,283
+2,1,24~5,1,24
+0,1,200~0,4,200
+5,7,284~7,7,284
+3,3,49~3,3,50
+5,3,293~5,5,293
+5,5,180~8,5,180
+1,1,81~3,1,81
+2,2,285~2,2,287
+1,6,288~3,6,288
+9,1,47~9,1,50
+2,1,189~4,1,189
+1,3,140~3,3,140
+4,4,121~4,4,123
+2,7,31~2,7,32
+8,7,268~8,7,268
+2,5,215~5,5,215
+9,0,42~9,2,42
+6,4,206~9,4,206
+4,6,169~4,7,169
+3,9,239~7,9,239
+5,5,210~8,5,210
+5,7,180~5,7,182
+4,0,251~4,3,251
+8,1,205~9,1,205
+3,7,53~3,9,53
+1,8,1~4,8,1
+2,5,207~5,5,207
+5,6,207~7,6,207
+0,6,224~0,7,224
+0,3,62~0,4,62
+9,5,1~9,5,3
+4,9,126~7,9,126
+0,6,8~0,8,8
+7,4,257~7,4,260
+2,4,142~2,4,144
+2,1,270~2,3,270
+0,4,56~1,4,56
+4,4,224~6,4,224
+8,3,231~8,4,231
+4,2,214~4,3,214
+5,1,133~7,1,133
+5,6,126~7,6,126
+4,1,5~7,1,5
+1,2,202~1,2,204
+5,7,292~7,7,292
+7,0,47~7,1,47
+3,5,285~5,5,285
+6,6,121~6,9,121
+3,4,106~3,6,106
+0,4,121~1,4,121
+1,7,244~3,7,244
+1,1,249~4,1,249
+1,2,76~1,4,76
+5,5,171~7,5,171
+8,2,78~8,2,80
+8,3,12~8,4,12
+0,0,97~0,0,100
+1,0,114~2,0,114
+0,0,122~2,0,122
+2,5,129~4,5,129
+1,4,137~3,4,137
+9,2,123~9,4,123
+3,4,290~5,4,290
+9,5,72~9,6,72
+0,7,170~0,8,170
+7,1,226~7,3,226
+2,4,81~2,6,81
+0,6,72~3,6,72
+6,3,145~6,5,145
+5,6,77~5,8,77
+0,0,237~0,3,237
+3,4,271~4,4,271
+4,4,60~6,4,60
+8,4,116~8,7,116
+5,5,223~8,5,223
+6,1,251~6,4,251
+2,9,182~5,9,182
+2,0,163~2,1,163
+8,0,12~8,1,12
+1,6,289~1,8,289
+4,7,116~5,7,116
+3,9,73~3,9,74
+4,4,67~6,4,67
+1,0,3~3,0,3
+3,1,46~3,4,46
+0,5,8~3,5,8
+1,2,53~4,2,53
+1,9,65~3,9,65
+8,2,162~8,3,162
+7,7,77~9,7,77
+6,4,197~6,7,197
+6,0,145~8,0,145
+6,4,269~9,4,269
+0,4,127~0,7,127
+8,5,267~8,8,267
+6,0,236~8,0,236
+4,0,56~4,3,56
+0,6,202~0,7,202
+6,3,3~6,5,3
+2,7,63~2,9,63
+3,5,73~3,8,73
+3,3,210~4,3,210
+4,1,114~4,1,115
+6,0,79~6,2,79
+0,2,221~1,2,221
+7,9,277~7,9,278
+2,4,72~5,4,72
+7,9,129~9,9,129
+0,4,196~0,6,196
+0,3,194~0,5,194
+4,7,67~4,9,67
+3,6,261~5,6,261
+3,0,256~3,1,256
+3,0,228~5,0,228
+1,1,252~3,1,252
+2,6,242~2,7,242
+2,1,167~3,1,167
+5,3,11~5,5,11
+7,3,223~9,3,223
+7,6,235~7,8,235
+1,9,66~2,9,66
+2,6,248~5,6,248
+5,2,76~5,5,76
+9,6,21~9,6,23
+2,7,2~2,9,2
+4,4,198~4,6,198
+5,8,199~5,9,199
+0,1,184~0,3,184
+0,1,293~3,1,293
+1,3,74~1,6,74
+4,4,201~5,4,201
+0,1,160~2,1,160
+9,0,41~9,3,41
+4,2,284~4,3,284
+2,0,61~5,0,61
+0,6,276~3,6,276
+6,7,237~8,7,237
+2,6,71~5,6,71
+5,4,287~6,4,287
+3,5,68~3,6,68
+3,7,201~5,7,201
+3,8,48~5,8,48
+4,4,86~7,4,86
+3,5,235~3,7,235
+4,2,152~8,2,152
+6,4,135~8,4,135
+6,2,85~8,2,85
+7,0,248~7,3,248
+0,3,59~0,4,59
+7,9,280~9,9,280
+8,2,164~8,3,164
+2,7,280~2,7,281
+0,6,130~0,8,130
+4,1,175~6,1,175
+1,2,124~1,4,124
+0,8,10~0,9,10
+3,3,117~3,6,117
+0,5,142~0,5,143
+6,6,27~6,8,27
+0,6,250~2,6,250
+1,8,227~1,9,227
+1,8,4~1,8,6
+0,8,107~2,8,107
+6,3,265~8,3,265
+3,6,237~6,6,237
+3,5,192~3,8,192
+6,0,8~6,1,8
+6,0,263~6,3,263
+5,7,196~5,9,196
+6,6,159~6,8,159
+5,3,248~5,5,248
+1,8,99~4,8,99
+5,5,129~6,5,129
+8,4,224~8,4,227
+0,1,154~0,4,154
+7,5,224~9,5,224
+2,7,158~5,7,158
+5,3,205~7,3,205
+2,6,144~2,8,144
+6,4,47~6,7,47
+5,3,275~5,6,275
+2,5,27~6,5,27
+8,0,139~9,0,139
+6,5,139~8,5,139
+8,3,219~9,3,219
+6,2,29~6,4,29
+2,1,187~2,4,187
+5,6,93~8,6,93
+6,5,142~8,5,142
+2,7,49~5,7,49
+6,2,250~8,2,250
+4,0,83~6,0,83
+6,0,280~9,0,280
+4,7,44~6,7,44
+1,0,264~1,3,264
+0,3,255~0,4,255
+6,6,1~8,6,1
+2,5,239~2,8,239
+7,3,221~7,6,221
+8,0,102~8,2,102
+7,7,182~9,7,182
+1,3,123~3,3,123
+0,7,135~2,7,135
+1,7,78~3,7,78
+4,5,196~7,5,196
+1,2,296~4,2,296
+0,1,21~3,1,21
+8,7,67~8,9,67
+5,9,185~7,9,185
+2,5,227~2,8,227
+9,4,275~9,7,275
+4,3,231~4,3,233
+9,3,131~9,4,131
+4,2,108~6,2,108
+7,6,209~7,6,210
+4,5,204~6,5,204
+7,4,52~7,6,52
+6,0,193~6,2,193
+8,7,215~8,8,215
+4,4,28~6,4,28
+2,3,45~2,5,45
+1,4,188~2,4,188
+0,2,269~0,4,269
+9,2,130~9,4,130
+9,4,263~9,6,263
+8,5,263~8,8,263
+7,3,42~7,6,42
+5,1,173~5,5,173
+3,3,227~3,6,227
+2,2,208~4,2,208
+3,2,220~4,2,220
+1,0,229~2,0,229
+5,0,279~7,0,279
+6,6,104~7,6,104
+1,2,26~5,2,26
+8,1,259~8,4,259
+6,7,49~8,7,49
+1,5,48~1,7,48
+6,3,82~9,3,82
+6,6,175~8,6,175
+2,0,36~2,2,36
+4,9,288~4,9,289
+0,6,5~2,6,5
+3,7,160~3,7,162
+8,3,125~8,4,125
+8,2,75~8,3,75
+0,5,279~0,7,279
+6,5,120~6,6,120
+8,7,158~9,7,158
+5,6,189~8,6,189
+8,1,25~8,2,25
+0,0,91~2,0,91
+2,3,77~5,3,77
+1,3,214~3,3,214
+2,7,155~5,7,155
+5,1,252~5,4,252
+2,8,102~2,9,102
+7,1,44~7,3,44
+5,6,174~8,6,174
+7,4,291~7,7,291
+2,7,55~2,8,55
+3,1,253~3,1,253
+4,9,274~7,9,274
+3,6,272~5,6,272
+6,4,89~9,4,89
+6,5,75~8,5,75
+4,5,245~5,5,245
+4,1,255~4,4,255
+1,8,248~1,8,249
+0,7,253~0,9,253
+3,4,29~4,4,29
+8,0,9~8,2,9
diff --git a/day22/uppga.c b/day22/uppga.c
@@ -0,0 +1,54 @@
+#include "common.h"
+
+static void supporting(stack_u64 *s, stack_u64 *t, brick_t *bricks, size_t n) {
+ size_t i, j;
+ brick_t b;
+
+ for (i = 0; i < n; i++) {
+ if (bricks[i].ivs[2].lb > 1) {
+ b = bricks[i];
+ gravitize(&b);
+
+ for (j = 0; j < n; j++) {
+ if (i != j && brick_nei(&b, &bricks[j])) {
+ stack_u64_push(s, i);
+ stack_u64_push(t, j);
+ }
+ }
+ }
+ }
+}
+
+int main(int argc, char **argv) {
+ size_t i;
+ char **lines;
+ size_t nlines = readlines(&lines, "input");
+
+ brick_t bricks[nlines];
+ read_bricks(bricks, lines, nlines);
+ sort_bricks(bricks, nlines);
+ gravitize_all(bricks, nlines);
+
+ stack_u64 s, t;
+ stack_u64_init(&s);
+ stack_u64_init(&t);
+ supporting(&s, &t, bricks, nlines);
+
+ uint64_t deg[nlines];
+ memset(deg, 0, nlines * sizeof(*deg));
+ for (i = 0; i < s.nmemb; i++)
+ deg[s.data[i]]++;
+
+ uint8_t unsafe[nlines];
+ memset(unsafe, 0, nlines);
+ for (i = 0; i < s.nmemb; i++)
+ if (deg[s.data[i]] == 1)
+ unsafe[t.data[i]] = 1;
+
+ uint64_t count = 0;
+ for (i = 0; i < nlines; i++)
+ if (!unsafe[i])
+ count++;
+
+ printf("%lld\n", count);
+}
diff --git a/day22/uppgb.c b/day22/uppgb.c
@@ -0,0 +1,61 @@
+#include "common.h"
+
+static inline void gravitize_all_ind(uint8_t *ind, brick_t *bricks,
+ const size_t n) {
+ // assume sorted by l.b. on z, increasingly
+ size_t i;
+ memset(ind, 0, n);
+
+ for (i = 0; i < n; i++) {
+ while (may_gravitize(&bricks[i], bricks, i)) {
+ gravitize(&bricks[i]);
+ ind[i] = 1;
+ }
+ }
+}
+
+static uint64_t remcnt(brick_t *bricks, size_t n) {
+ size_t i, j;
+ brick_t b[n - 1];
+ uint8_t ind[n - 1];
+ uint64_t fallen;
+ uint64_t tot = 0;
+
+ for (i = 0; i < n; i++) {
+ // copy all but brick i
+ size_t jc = 0;
+ for (j = 0; j < n; j++) {
+ if (j != i) {
+ b[jc] = bricks[j];
+ jc++;
+ }
+ }
+
+ // gravitize all
+ gravitize_all_ind(ind, b, n - 1);
+
+ // count number of fallen
+ fallen = 0;
+ for (j = 0; j < n - 1; j++) {
+ if (ind[j])
+ fallen++;
+ }
+
+ tot += fallen;
+ }
+
+ return tot;
+}
+
+int main(int argc, char **argv) {
+ char **lines;
+ size_t nlines = readlines(&lines, "input");
+
+ brick_t bricks[nlines];
+ read_bricks(bricks, lines, nlines);
+ sort_bricks(bricks, nlines);
+ gravitize_all(bricks, nlines);
+
+ uint64_t count = remcnt(bricks, nlines);
+ printf("%lld\n", count);
+}
diff --git a/day23/Makefile b/day23/Makefile
@@ -0,0 +1,30 @@
+CC=clang
+CFLAGS+=-std=c99 -pedantic -Wall -Werror -Wstrict-prototypes
+CFLAGS+=-Wmissing-prototypes -Wmissing-declarations -Wshadow
+CFLAGS+=-Wpointer-arith -Wcast-qual -Wsign-compare
+CFLAGS+=-O2 -g
+CFLAGS+=-fstack-protector-all -Wtype-limits -fno-common
+CFLAGS+=-fno-builtin
+CFLAGS+=-I/usr/local/include
+CFLAGS+=-I../utils
+#LDFLAGS=
+
+UTILS=../utils/reading.o ../utils/dg.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) $(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)
+
+utils:
+ make -C ../utils
+
+clean:
+ rm -rf common.o uppga uppgb
diff --git a/day23/common.c b/day23/common.c
@@ -0,0 +1,34 @@
+#include "common.h"
+
+size_t idx(size_t row, size_t col, size_t ncols) { return row * ncols + col; }
+
+int walkable(char **lines, size_t r, size_t c) {
+ return lines[r][c] == '.' || lines[r][c] == '<' || lines[r][c] == '>' ||
+ lines[r][c] == '^' || lines[r][c] == 'v';
+}
+
+/**
+ * This is a terrible solution, essentially
+ * brute force, recursively. Could replace with
+ * dyn.prog.
+ */
+void recursive_longest_path(uint8_t *visited, size_t node, size_t end,
+ size_t steps, const dg_t *g, size_t *l) {
+ size_t i;
+ visited[node] = 1;
+
+ if (node == end) {
+ if (*l < steps) {
+ *l = steps;
+ }
+ } else {
+ for (i = 0; i < g->nbrs[node].nmemb; i++) {
+ size_t nbr = g->nbrs[node].data[i];
+ if (visited[nbr] == 0) {
+ recursive_longest_path(visited, nbr, end, steps + 1, g, l);
+ }
+ }
+ }
+
+ visited[node] = 0;
+}
diff --git a/day23/common.h b/day23/common.h
@@ -0,0 +1,17 @@
+#ifndef COMMON_H_
+#define COMMON_H_
+
+#include <assert.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <dg.h>
+#include <reading.h>
+
+size_t idx(size_t row, size_t col, size_t ncols);
+int walkable(char **lines, size_t r, size_t c);
+void recursive_longest_path(uint8_t *visited, size_t node, size_t end,
+ size_t steps, const dg_t *g, size_t *l);
+
+#endif
diff --git a/day23/exinput b/day23/exinput
@@ -0,0 +1,23 @@
+#.#####################
+#.......#########...###
+#######.#########.#.###
+###.....#.>.>.###.#.###
+###v#####.#v#.###.#.###
+###.>...#.#.#.....#...#
+###v###.#.#.#########.#
+###...#.#.#.......#...#
+#####.#.#.#######.#.###
+#.....#.#.#.......#...#
+#.#####.#.#.#########v#
+#.#...#...#...###...>.#
+#.#.#v#######v###.###v#
+#...#.>.#...>.>.#.###.#
+#####v#.#.###v#.#.###.#
+#.....#...#...#.#.#...#
+#.#########.###.#.#.###
+#...###...#...#...#.###
+###.###.#.###v#####v###
+#...#...#.#.>.>.#.>.###
+#.###.###.#.###.#.#v###
+#.....###...###...#...#
+#####################.#
diff --git a/day23/input b/day23/input
@@ -0,0 +1,141 @@
+#.###########################################################################################################################################
+#.............#...#...###...#...#.......#...###...#...#...#.....#...#...#...###...#...#...#.....###...#.....#...#####...#...#...............#
+#############.#.#.#.#.###.#.#.#.#.#####.#.#.###.#.#.#.#.#.#.###.#.#.#.#.#.#.###.#.#.#.#.#.#.###.###.#.#.###.#.#.#####.#.#.#.#.#############.#
+#.............#.#...#.#...#.#.#...#.....#.#...#.#.#.#.#.#.#.#...#.#.#.#.#.#.#...#.#.#.#.#.#.#...#...#.#...#...#...#...#.#.#.#.......#.......#
+#.#############.#####.#.###.#.#####.#####.###.#.#.#.#.#.#.#.#.###.#.#.#.#.#.#.###.#.#.#.#.#.#.###.###.###.#######.#.###.#.#.#######.#.#######
+#.............#.....#.#...#.#.#.....#...#.#...#.#.#.#.#.#...#...#.#...#.#.#.#...#.#.#.#.#.#.#...#...#.###.....#...#...#...#...#...#.#.......#
+#############.#####.#.###.#.#.#.#####.#.#.#.###.#.#.#.#.#######.#.#####.#.#.###.#.#.#.#.#.#.###.###.#.#######.#.#####.#######.#.#.#.#######.#
+#.............#...#.#.#...#.#.#...>.>.#.#.#.###.#.#.#...#.......#.....#.#.#.###.#.#.#.#.#...#...#...#.#...#...#.#...#.....#...#.#.#.#.....#.#
+#.#############.#.#.#.#.###.#.#####v###.#.#.###.#.#.#####.###########.#.#.#.###.#.#.#.#.#####.###.###.#.#.#.###.#.#.#####.#.###.#.#.#.###.#.#
+#.........#...#.#.#.#.#...#...#...#.#...#.#.###.#.#.#.....#...#####...#.#.#...#.#.#.#.#.....#...#...#...#.#...#.#.#.#...#.#...#.#.#.#...#.#.#
+#########.#.#.#.#.#.#.###.#####.#.#.#.###.#.###.#.#.#.#####.#.#####.###.#.###.#.#.#.#.#####.###.###.#####.###.#.#.#.#.#.#.###.#.#.#.###.#.#.#
+#.........#.#.#.#...#...#.#...#.#.#.#.#...#.#...#.#.#.....#.#.#.>.>.#...#.#...#.#.#.#.###...#...###.....#.....#.#.#...#.#.#...#.#...#...#...#
+#.#########.#.#.#######.#.#.#.#.#.#.#.#.###.#.###.#.#####.#.#.#.#v###.###.#.###.#.#.#.###.###.#########.#######.#.#####.#.#.###.#####.#######
+#.#.......#.#.#...#.....#...#...#.#.#...###.#.###.#.....#...#.#.#.###.....#...#.#...#...#.#...#...#...#.......#...#...#.#.#...#.#...#...#...#
+#.#.#####.#.#.###.#.#############.#.#######.#.###.#####.#####.#.#.###########.#.#######.#.#.###.#.#.#.#######.#####.#.#.#.###.#.#.#.###.#.#.#
+#.#.#.....#.#.###.#...#...#.....#.#.....###.#.###.#...#.#.....#.#.#.....#.....#.....#...#.#.###.#.#.#.###...#.......#.#.#...#...#.#...#...#.#
+#.#.#.#####.#.###.###.#.#.#.###.#.#####.###.#.###.#.#.#.#.#####.#.#.###.#.#########.#.###.#.###.#.#.#.###.#.#########.#.###.#####.###.#####.#
+#...#.#.....#.#...#...#.#.#...#.#.#...#...#...###.#.#...#.......#...#...#.>.>...#...#.#...#...#.#...#.>.>.#.#.....#...#...#.#.....###...#...#
+#####.#.#####.#.###v###.#.###.#.#.#.#.###.#######.#.#################.#####v###.#.###.#.#####.#.#######v###.#.###.#.#####.#.#.#########.#.###
+###...#.....#...###.>.#.#.....#...#.#...#.......#.#.###...###.........#.....#...#.#...#.....#.#.....###...#.#...#.#.....#...#.....#...#.#...#
+###.#######.#######v#.#.###########.###.#######.#.#.###.#.###.#########.#####.###.#.#######.#.#####.#####.#.###.#.#####.#########.#.#.#.###.#
+#...#...#...#.......#...#...........###.........#...#...#.....#...#...#.....#.....#.....#...#...#...#.....#.#...#.......#.......#...#.#.#...#
+#.###.#.#.###.###########.###########################.#########.#.#.#.#####.###########.#.#####.#.###.#####.#.###########.#####.#####.#.#.###
+#.#...#.#.###...###...###.#.................#.....#...#.....#...#...#.###...###...#...#...#####.#.###.....#.#.....#...#...#...#.......#...###
+#.#.###.#.#####.###.#.###.#.###############.#.###.#.###.###.#.#######.###.#####.#.#.#.#########.#.#######.#.#####.#.#.#.###.#.###############
+#.#.###...#...#.....#...#...#...............#.#...#.#...#...#.#.......#...#...#.#.#.#.#...###...#.....#...#.......#.#.#.....#.......#.......#
+#.#.#######.#.#########.#####.###############.#.###.#.###.###.#.#######.###.#.#.#.#.#.#.#.###.#######.#.###########.#.#############.#.#####.#
+#.#...#.....#.....#...#.....#.................#...#...#...#...#.....#...#...#...#.#.#...#...#.........#.....#...#...#.#...###.......#.#.....#
+#.###.#.#########.#.#.#####.#####################.#####.###.#######.#.###.#######.#.#######.###############.#.#.#.###.#.#.###.#######.#.#####
+#.#...#.....#...#.#.#.......###.....#...#.......#.#...#...#.#...#...#...#.#.......#.....#...###...#...###...#.#.#...#.#.#...#.........#.....#
+#.#.#######.#.#.#.#.###########.###.#.#.#.#####.#.#.#.###.#.#.#.#.#####.#.#.###########.#.#####.#.#.#.###v###.#.###.#.#.###.###############.#
+#...#...###...#.#...###.....#...###...#...#####...#.#.###...#.#.#.#...#...#.......#...#.#.#...#.#.#.#.#.>.>.#.#...#.#.#...#.#...#...#...#...#
+#####.#.#######v#######.###.#.#####################.#.#######.#.#.#.#.###########.#.#.#.#.#.#.#.#.#.#.#.#v#.#.###.#.#.###.#.#.#.#v#.#.#.#.###
+#...#.#.#...###.>.#...#...#.#.###...#####...###...#.#.#.......#...#.#.#...#.......#.#...#...#.#.#.#.#...#.#...#...#.#...#.#...#.>.#...#...###
+#.#.#.#.#.#.###v#.#.#.###.#.#v###.#.#####.#.###.#.#.#.#.###########.#.#.#.#.#######.#########.#.#.#.#####.#####.###.###.#.#######v###########
+#.#...#...#...#.#.#.#.#...#.>.>.#.#...#...#...#.#.#.#.#...........#.#.#.#.#.......#.........#.#.#.#.#.....#...#...#...#.#.#.....#...#...#####
+#.###########.#.#.#.#.#.#####v#.#.###.#.#####.#.#.#.#.###########.#.#.#.#.#######v#########.#.#.#.#.#.#####.#.###.###.#.#.#.###.###.#.#.#####
+#.......#...#.#.#...#.#.#.....#.#.#...#.....#.#.#.#.#.#...###...#.#.#.#.#.#.....>.>.#...#...#...#.#.#.......#...#.#...#.#.#...#.###...#.....#
+#######.#.#.#.#.#####.#.#.#####.#.#.#######.#.#.#.#.#.#.#.###.#.#.#.#.#.#.#.#####v#.#.#.#.#######.#.###########.#.#.###.#.###.#.###########.#
+#.....#...#.#.#...###.#.#.....#...#...#...#.#.#.#.#.#.#.#.###.#.#.#.#.#.#...#.....#.#.#.#.......#...#...........#...#...#...#.#.............#
+#.###.#####.#.###.###.#.#####.#######.#.#.#.#.#.#.#.#.#.#.###.#.#v#.#.#.#####.#####.#.#.#######.#####.###############.#####.#.###############
+#...#.....#.#.#...#...#.#.....#...###.#.#.#.#...#.#.#.#.#.#...#.>.>.#...#...#.....#...#...#...#.#.....#.........#...#...#...#...#...........#
+###.#####.#.#.#.###.###.#.#####.#.###.#.#.#.#####.#.#.#.#.#.#####v#######.#.#####.#######.#.#.#.#.#####.#######.#.#.###.#.#####.#.#########.#
+#...#...#.#.#...###.....#.#.....#...#.#.#.#.#.....#.#...#.#.#.....#.....#.#.....#.......#...#...#.......#####...#.#.###.#.#.....#.#.........#
+#.###.#.#.#.#############.#.#######.#.#.#.#.#.#####.#####.#.#.#####.###.#.#####.#######.#####################.###.#.###.#.#.#####.#.#########
+#.....#.#.#.###.......###...#...#...#.#.#...#.....#.....#...#.......#...#.....#...#...#.#...#...#...#...#.....#...#...#...#.......#.........#
+#######.#.#.###.#####.#######.#.#.###.#.#########.#####.#############.#######.###.#.#.#.#.#.#.#.#.#.#.#.#.#####.#####.#####################.#
+#.......#.#.....#.....#.......#...###...###...#...#.....###...#...#...#...#...###.#.#...#.#...#.#.#...#.#...#...#...#.....#...###...........#
+#.#######.#######.#####.###################.#.#.###.#######.#.#.#.#.###.#.#.#####.#.#####.#####.#.#####.###.#.###.#.#####.#.#.###.###########
+#.......#.......#.....#...............#...#.#.#.....#...#...#...#...###.#.#.....#.#...###.#.....#...#...###...#...#.......#.#.#...#.........#
+#######.#######.#####.###############.#.#.#.#.#######.#.#.#############.#.#####.#.###.###.#.#######.#.#########.###########.#.#.###.#######.#
+#.......#.....#.#...#.#...#...#.......#.#.#.#...#.....#.#...........#...#.......#.#...#...#...#...#.#...#.....#.............#.#...#.#.......#
+#.#######.###.#.#.#.#.#.#.#.#.#.#######.#.#.###.#.#####.###########.#.###########.#.###.#####.#.#.#.###.#.###.###############.###.#.#.#######
+#.......#.#...#...#...#.#...#.#...#####.#.#.#...#.....#.......#.....#...#.......#.#...#.....#.#.#...#...#...#...#.............###...#...#...#
+#######.#.#.###########.#####.###.#####.#.#.#.#######v#######.#.#######.#.#####.#.###.#####.#.#.#####.#####.###.#.#####################.#.#.#
+#.......#.#.###.........#...#.....#.....#.#.#.#.....>.>.#...#.#...#.....#.#.....#.....#...#.#.#.....#.#...#.#...#.#...#.......#.....###...#.#
+#.#######.#v###.#########.#.#######.#####.#.#.#.#####v#.#.#.#.###.#.#####.#.###########.#.#.#.#####.#.#.#.#.#.###v#.#.#.#####.#.###.#######.#
+#.#.......#.>.#...........#.......#.....#.#.#.#.#...#.#.#.#.#.....#.......#...#...###...#.#.#.#.....#...#...#...>.>.#.#.#.....#...#.........#
+#.#.#######v#.###################.#####.#.#.#.#.#.#.#.#.#.#.#################.#.#.###.###.#.#.#.#################v###.#.#.#######.###########
+#...#...#...#...###.....#.........#.....#.#.#...#.#.#.#...#...#...#...........#.#.#...###.#.#.#.#...............#.#...#.#.#.....#...........#
+#####.#.#.#####.###.###.#.#########.#####.#.#####.#.#.#######.#.#.#.###########.#.#.#####.#.#.#.#.#############.#.#.###.#.#.###.###########.#
+#...#.#.#...#...#...#...#.........#.....#.#...#...#...#.....#...#.#.........#...#.#.....#.#.#.#.#...#.........#...#.....#.#.#...###...#...#.#
+#.#.#.#.###.#.###.###.###########.#####.#.###.#.#######.###.#####.#########.#.###.#####.#.#.#.#.###.#.#######.###########.#.#.#####.#.#.#.#.#
+#.#...#.....#...#...#.#...###...#.#...#.#.....#.........#...#.....#...#####.#...#.......#...#...###...#.......#...#.......#.#.#...#.#.#.#.#.#
+#.#############.###.#.#.#.###.#.#v#.#.#.#################.###.#####.#.#####v###.#######################.#######.#.#.#######.#.#.#.#.#.#v#.#.#
+#.............#...#.#.#.#...#.#.>.>.#...###...............###...#...#...#.>.>.#.#...###...###...###...#.....###.#.#.....#...#.#.#.#.#.>.#...#
+#############.###.#.#.#.###.#.###v#########.###################.#.#####.#.#v#.#.#.#.###.#.###.#.###.#.#####.###.#.#####.#.###.#.#.#.###v#####
+#.............###.#.#.#...#.#...#...###...#...#...#.......###...#.#.....#.#.#...#.#...#.#.#...#.#...#.......#...#...###...#...#.#.#.#...#...#
+#.###############.#.#.###.#.###.###.###.#.###.#.#.#.#####.###.###.#.#####.#.#####.###.#.#.#.###.#.###########.#####.#######.###.#.#.#.###.#.#
+#...............#.#.#.#...#.#...###...#.#.###...#...#...#...#.#...#.#...#.#...###.#...#.#.#...#.#.......###...#.....#...###.....#...#.....#.#
+###############.#.#.#.#.###.#.#######.#.#.###########.#.###.#.#.###.#.#.#.###.###.#.###.#.###.#.#######.###.###.#####.#.###################.#
+###.............#...#...###.#.#.......#.#.....#.......#.....#...###...#...###.#...#.....#...#.#.#.....#...#...#...#...#.#...#...#...###...#.#
+###.#######################.#.#.#######.#####.#.#############################.#.###########.#.#.#.###.###.###.###.#.###.#.#.#.#.#.#.###.#.#.#
+#...#...#.....#.......#...#...#.......#.#.....#.........###...#...###...#...#...###...#.....#.#.#...#.#...###.#...#.#...#.#.#.#.#.#.#...#.#.#
+#.###.#.#.###.#.#####.#.#.###########.#.#.#############.###.#.#.#.###.#.#.#.#######.#.#v#####.#.###.#.#v#####.#.###.#.###.#.#.#.#.#.#v###.#.#
+#...#.#.#.#...#.#.....#.#.....#.......#.#...#...........#...#.#.#.#...#.#.#...#...#.#.>.>.#...#.#...#.>.>.....#.....#.#...#.#.#...#.>.###...#
+###.#.#.#.#.###.#v#####.#####.#.#######.###.#.###########.###.#.#.#.###.#.###.#.#.#.###v#.#.###.#.#####v#############.#.###.#.#######v#######
+###...#...#.....#.>.#...#.....#.......#.#...#...........#.#...#.#.#...#.#.###.#.#.#.#...#...###...#.....#.....#...###.#...#...#.......###...#
+#################v#.#.###.###########.#.#.#############.#.#.###.#.###.#.#.###.#.#.#.#.#############.#####.###.#.#.###.###.#####.#########.#.#
+#.................#.#.#...###.......#...#.....#...###...#.#.###.#.#...#...###.#.#...#.....#.........#...#.###...#...#.#...#...#.......#...#.#
+#.#################.#.#.#####.#####.#########.#.#.###.###.#.###.#.#.#########.#.#########.#.#########.#.#.#########.#.#.###.#.#######.#.###.#
+#.#.........#.....#...#.#...#.#.....#...#.....#.#.#...#...#.#...#.#.....###...#...#.......#...#...#...#.#.#.........#...###.#.........#.#...#
+#.#.#######.#.###.#####.#.#.#.#.#####.#.#.#####.#.#.###.###.#.###.#####.###.#####.#.#########.#.#.#.###.#.#.###############.###########.#.###
+#.#.#.......#.#...###...#.#...#...#...#...###...#.#...#.#...#.#...#...#...#...#...#.........#.#.#.#.#...#.#...............#.........#...#...#
+#.#.#.#######.#.#####.###.#######.#.#########.###.###.#.#.###.#.###.#.###.###.#.###########.#.#.#.#.#.###.###############.#########.#.#####.#
+#...#.........#.....#.#...#.......#.........#...#.###.#.#.#...#...#.#...#...#.#.#...........#...#.#.#...#.#...............#.........#.#.....#
+###################.#.#.###.###############.###.#.###v#.#.#.#####.#.###.###.#.#.#.###############.#.###.#.#.###############.#########.#.#####
+#...#...#...........#...#...#...#...#...#...###.#...>.>.#...#...#.#...#.#...#...#.........###...#...#...#.#...............#.....#.....#.....#
+#.#.#.#.#.###############.###.#.#.#.#.#.#v#####.#####v#######.#.#.###.#.#.###############.###.#.#####.###.###############.#####.#.#########.#
+#.#...#.#...#...........#...#.#.#.#.#.#.>.>...#.#...#.........#.#.....#.#.#...#.........#.....#.....#.#...#.....#...#.....#####...#.........#
+#.#####.###.#.#########.###.#.#.#.#.#.###v###.#.#.#.###########.#######.#.#.#.#.#######.###########.#.#.###.###.#.#.#.#############.#########
+#.....#...#...#.....#...###...#.#.#.#.#...###...#.#.#.......#...###...#...#.#.#.......#.............#.#...#...#...#...#####.........#...#...#
+#####.###.#####.###.#.#########.#.#.#.#.#########.#.#.#####.#.#####.#.#####.#.#######.###############.###.###.#############.#########.#.#.#.#
+#####...#.#...#.###...###...###...#...#.......#...#...#...#...#...#.#.#...#.#.#.....#...........#...#.....###.............#...........#...#.#
+#######.#.#.#.#.#########.#.#################.#.#######.#.#####.#.#.#.#.#.#.#.#.###.###########.#.#.#####################.#################.#
+###...#.#.#.#.#.....#...#.#.#...###...###.....#.......#.#.#...#.#.#.#.#.#.#.#.#.#...#.......#...#.#.#.....#...............#.................#
+###.#.#.#.#.#.#####.#.#.#.#.#.#.###.#.###.###########.#.#.#.#.#.#.#.#.#.#.#.#.#.#.###.#####.#.###.#.#.###.#.###############.#################
+#...#...#...#.......#.#.#.#.#.#...#.#.#...#.......###...#.#.#.#.#.#.#.#.#...#.#.#...#.....#.#.#...#.#.#...#...............#.#...............#
+#.###################.#.#.#.#.###.#.#.#.###.#####.#######.#.#.#.#.#.#.#.#####.#.###.#####.#.#.#.###.#.#.#################.#.#.#############.#
+#.......#...#.....###.#.#.#.#.#...#.#.#...#.....#...#.....#.#.#.#.#.#.#...#...#.#...#...#.#...#.#...#.#.#...#...........#.#...#.......#.....#
+#######.#.#.#.###.###.#.#.#.#.#.###.#.###v#####.###.#.#####.#.#.#.#.#.###.#.###.#.###.#.#v#####.#.###.#.#.#.#.#########.#.#####.#####.#.#####
+#.......#.#...#...#...#...#...#.#...#...>.>.#...#...#...###.#.#.#.#.#.#...#.#...#.#...#.>.>.###.#.#...#...#.#.........#.#.#...#.....#.#.....#
+#.#######.#####v###.###########.#.#######v#.#.###.#####v###.#.#.#.#.#.#.###.#.###.#.#####v#.###.#.#.#######.#########.#.#.#.#.#####v#.#####.#
+#.........#...#.>...#...#...###...#...#...#...#...#...>.>...#...#...#.#...#.#.###.#...#...#...#.#.#.......#.#...#.....#...#.#.#...>.#.#.....#
+###########.#.#v#####.#.#.#.#######.#.#.#######.###.###v#############.###.#.#.###.###.#.#####.#.#.#######.#.#.#.#.#########.#.#.###v#.#.#####
+#...........#.#.......#...#.....#...#.#.......#...#.#...###...#...###...#.#.#.#...#...#.....#.#.#.#...###.#.#.#.#.###.....#.#.#.#...#...#...#
+#.###########.#################.#.###.#######.###.#.#.#####.#.#.#.#####.#.#.#.#.###.#######.#.#.#.#.#.###.#.#.#.#v###.###.#.#.#.#.#######.#.#
+#.#.........#.#.....#.....#.....#...#...#.....###...#.....#.#.#.#.#####.#.#.#.#...#.#.......#.#.#.#.#...#.#.#.#.>.>.#...#.#.#.#.#.#...###.#.#
+#.#.#######.#.#.###.#.###.#.#######.###.#.###############.#.#.#.#.#####.#.#.#.###.#.#.#######.#.#.#.###.#.#.#.###v#.###.#.#.#.#.#.#.#.###.#.#
+#.#.#.....#.#...###.#.#...#.#...###.#...#.........#...###...#...#.....#.#.#...#...#.#.......#...#.#.#...#.#.#.###.#.#...#.#.#.#.#.#.#.....#.#
+#.#.#.###.#.#######.#.#.###.#.#.###.#.###########.#.#.###############.#.#.#####.###.#######.#####.#.#.###.#.#.###.#.#.###.#.#.#.#.#.#######.#
+#...#...#.#.#...###...#...#.#.#.....#...#...#...#.#.#.................#.#...###...#.#.......#...#.#.#...#.#.#.#...#...#...#.#.#.#.#.#.......#
+#######.#.#.#.#.#########.#.#.#########.#.#.#.#.#.#.###################.###.#####.#.#.#######.#.#.#.###.#.#.#.#.#######.###.#.#.#.#.#.#######
+###...#.#.#...#.........#...#...#.....#.#.#.#.#...#...................#...#.....#...#.........#.#...###...#...#.......#...#.#...#...#...#...#
+###.#.#.#.#############.#######.#.###.#.#.#.#.#######################.###.#####.###############.#####################.###.#.###########.#.#.#
+#...#...#...#...#.....#.###...#...###.#.#.#.#.#.....#.................###...#...#.............#.#...#...#####...#...#...#.#...#...#...#...#.#
+#.#########.#.#.#.###.#.###.#.#######.#.#.#.#.#.###.#.#####################.#.###.###########.#.#.#.#.#.#####.#.#.#.###.#.###.#.#.#.#.#####.#
+#.........#.#.#.#.###...#...#...###...#...#...#.#...#.........###...#...###...###.........###...#.#...#...#...#.#.#.#...#.#...#.#...#.......#
+#########.#.#.#.#.#######.#####.###.###########.#.###########.###.#.#.#.#################.#######.#######.#.###.#.#.#.###.#.###.#############
+#.........#...#.#.....#...#...#.....#...#...#...#...#...#...#.....#...#.......#.....#...#.......#.......#.#.###...#...###.#.###.............#
+#.#############.#####.#.###.#.#######.#.#.#.#.#####.#.#.#.#.#################.#.###.#.#.#######.#######.#.#.#############.#.###############.#
+#.............#.......#.....#.......#.#.#.#.#...#...#.#.#.#.#.................#...#...#.#.......###.....#.#.......#...###...#...#...........#
+#############.#####################.#.#.#.#.###.#.###.#.#.#.#v###################.#####.#.#########v#####.#######.#.#.#######.#.#.###########
+#.......#.....#...#...#...###.......#.#.#.#.#...#...#.#.#.#.>.>.....#...###...###.....#...###...#.>.>...#.........#.#.#...###.#.#...........#
+#.#####.#.#####.#.#.#.#.#.###.#######.#.#.#.#.#####.#.#.#.#########.#.#.###.#.#######.#######.#.#.#####.###########.#.#.#.###.#.###########.#
+#.....#.#...###.#.#.#...#...#.....#...#...#.#.....#.#.#.#.#...#.....#.#.#...#.#.....#.......#.#...#.....#...#.....#.#...#.#...#...#...#.....#
+#####.#.###.###.#.#.#######.#####.#.#######.#####.#.#.#.#.#.#.#.#####.#.#.###.#.###.#######.#.#####.#####.#.#.###.#.#####.#.#####.#.#.#.#####
+#.....#.....#...#.#.#.......#...#.#.......#.#...#.#.#.#.#.#.#.#.....#.#.#...#.#...#...#.....#.#.....#...#.#.#.#...#.#.....#.....#...#.#.....#
+#.###########.###.#.#.#######.#.#v#######.#.#.#.#.#.#.#.#.#.#.#####.#.#.###.#.###.###.#.#####.#.#####.#.#.#.#.#.###.#.#########.#####.#####.#
+#.#...#.....#...#.#.#.#.....#.#.>.>...#...#.#.#.#.#...#...#.#.......#.#.###.#.###...#.#...#...#.#...#.#...#.#.#.###.#.#.......#.....#.###...#
+#.#.#.#.###.###.#.#.#.#.###.#.#######.#.###.#.#.#.#########.#########.#.###.#.#####.#.###v#.###.#.#.#.#####.#.#.###.#.#.#####.#####.#.###.###
+#...#...#...###.#...#...###.#.#.......#.###...#.#.#.........#...#...#.#.#...#...#...#.#.>.>.#...#.#.#.#...#...#...#.#.#.#.....#...#.#.#...###
+#########.#####.###########.#.#.#######.#######.#.#.#########.#.#.#.#.#.#.#####.#.###.#.#####.###.#.#.#.#.#######.#.#.#.#.#####.#.#.#.#.#####
+#.........#.....#...###...#.#.#...#...#.......#.#.#...#.....#.#.#.#.#.#.#...###.#.###...#.....#...#.#.#.#.........#.#.#.#.#...#.#.#.#.#...###
+#.#########.#####.#.###.#.#.#.###.#.#.#######.#.#.###.#.###.#.#.#.#.#.#.###.###.#.#######.#####.###.#.#.###########.#.#.#.#.#.#.#.#.#.###v###
+#.........#.......#.....#.#.#.#...#.#.....#...#.#.###...###...#.#.#.#.#.#...#...#.......#.....#...#...#.#...#.....#.#.#.#.#.#.#.#.#.#.#.>.###
+#########.###############.#.#.#.###.#####.#.###.#.#############.#.#.#.#.#.###.#########.#####.###.#####.#.#.#.###.#.#.#.#.#.#.#.#.#.#.#.#v###
+#.........#...#...#...#...#.#.#...#.....#.#...#.#.#.............#.#.#.#.#.###...#.....#.....#.#...#.....#.#.#.#...#.#.#.#.#.#.#.#.#.#.#.#.###
+#.#########.#.#.#.#.#.#.###.#.###.#####.#.###.#.#.#.#############.#.#.#.#.#####.#.###.#####.#.#.###.#####.#.#.#.###.#.#.#.#.#.#.#.#.#.#.#.###
+#...........#...#...#...###...###.......#.....#...#...............#...#...#####...###.......#...###.......#...#.....#...#...#...#...#...#...#
+###########################################################################################################################################.#
diff --git a/day23/uppga.c b/day23/uppga.c
@@ -0,0 +1,58 @@
+#include "common.h"
+
+static inline void edge_adder(dg_t *g, char **lines, size_t nlines,
+ size_t ncols, size_t row, size_t col) {
+ char c = lines[row][col];
+ // north
+ if (c != '<' && c != '>' && c != 'v' && row > 0 &&
+ walkable(lines, row - 1, col)) {
+ dg_add_edge(g, idx(row, col, ncols), idx(row - 1, col, ncols));
+ }
+
+ // east
+ if (c != '^' && c != '<' && c != 'v' && col < ncols - 1 &&
+ walkable(lines, row, col + 1)) {
+ dg_add_edge(g, idx(row, col, ncols), idx(row, col + 1, ncols));
+ }
+
+ // south
+ if (c != '^' && c != '<' && c != '>' && row < nlines - 1 &&
+ walkable(lines, row + 1, col)) {
+ dg_add_edge(g, idx(row, col, ncols), idx(row + 1, col, ncols));
+ }
+
+ // west
+ if (c != 'v' && c != '>' && c != '^' && col > 0 &&
+ walkable(lines, row, col - 1)) {
+ dg_add_edge(g, idx(row, col, ncols), idx(row, col - 1, ncols));
+ }
+}
+
+static inline void read_grid(dg_t *g, char **lines, size_t nlines) {
+ size_t i, j;
+ size_t ncols = strlen(lines[0]) - 1;
+
+ dg_init(g, nlines * ncols);
+ for (i = 0; i < nlines; i++) {
+ for (j = 0; j < ncols; j++) {
+ if (lines[i][j] == '.' || lines[i][j] == '>' || lines[i][j] == '<' ||
+ lines[i][j] == 'v' || lines[i][j] == '^')
+ edge_adder(g, lines, nlines, ncols, i, j);
+ }
+ }
+}
+
+int main(int argc, char **argv) {
+ char **lines;
+ size_t nlines = readlines(&lines, "input");
+
+ dg_t g;
+ read_grid(&g, lines, nlines);
+
+ size_t l = 0;
+ uint8_t visited[g.n];
+ memset(visited, 0, g.n);
+ recursive_longest_path(visited, 1, g.n - 2, 0, &g, &l);
+
+ printf("%zu\n", l);
+}
diff --git a/day23/uppgb.c b/day23/uppgb.c
@@ -0,0 +1,54 @@
+#include "common.h"
+
+static inline void edge_adder(dg_t *g, char **lines, size_t nlines,
+ size_t ncols, size_t row, size_t col) {
+ // char c = lines[row][col];
+ // north
+ if (row > 0 && walkable(lines, row - 1, col)) {
+ dg_add_edge(g, idx(row, col, ncols), idx(row - 1, col, ncols));
+ }
+
+ // east
+ if (col < ncols - 1 && walkable(lines, row, col + 1)) {
+ dg_add_edge(g, idx(row, col, ncols), idx(row, col + 1, ncols));
+ }
+
+ // south
+ if (row < nlines - 1 && walkable(lines, row + 1, col)) {
+ dg_add_edge(g, idx(row, col, ncols), idx(row + 1, col, ncols));
+ }
+
+ // west
+ if (col > 0 && walkable(lines, row, col - 1)) {
+ dg_add_edge(g, idx(row, col, ncols), idx(row, col - 1, ncols));
+ }
+}
+
+static void read_grid(dg_t *g, char **lines, size_t nlines) {
+ size_t i, j;
+ size_t ncols = strlen(lines[0]) - 1;
+
+ dg_init(g, nlines * ncols);
+ for (i = 0; i < nlines; i++) {
+ for (j = 0; j < ncols; j++) {
+ if (lines[i][j] == '.' || lines[i][j] == '>' || lines[i][j] == '<' ||
+ lines[i][j] == 'v' || lines[i][j] == '^')
+ edge_adder(g, lines, nlines, ncols, i, j);
+ }
+ }
+}
+
+int main(int argc, char **argv) {
+ char **lines;
+ size_t nlines = readlines(&lines, "input");
+
+ dg_t g;
+ read_grid(&g, lines, nlines);
+
+ size_t l = 0;
+ uint8_t visited[g.n];
+ memset(visited, 0, g.n);
+ recursive_longest_path(visited, 1, g.n - 2, 0, &g, &l);
+
+ printf("%zu\n", l);
+}
diff --git a/day24/Makefile b/day24/Makefile
@@ -0,0 +1,30 @@
+CC=clang
+CFLAGS+=-std=c99 -pedantic -Wall -Werror -Wstrict-prototypes
+CFLAGS+=-Wmissing-prototypes -Wmissing-declarations -Wshadow
+CFLAGS+=-Wpointer-arith -Wcast-qual -Wsign-compare
+CFLAGS+=-O2 -g
+CFLAGS+=-fstack-protector-all -Wtype-limits -fno-common
+CFLAGS+=-fno-builtin
+CFLAGS+=-I/usr/local/include -I/usr/local/include/flint
+CFLAGS+=-I../utils
+LDFLAGS=-L/usr/local/lib -lflint
+
+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) $(CFLAGS) -o uppga uppga.c common.o $(UTILS) $(INCLUDES) $(LDFLAGS)
+
+uppgb: $(UTILS) common.o uppgb.c
+ $(CC) $(CFLAGS) -o uppgb uppgb.c common.o $(UTILS) $(INCLUDES) $(LDFLAGS)
+
+utils:
+ make -C ../utils
+
+clean:
+ rm -rf common.o uppga uppgb
diff --git a/day24/common.c b/day24/common.c
@@ -0,0 +1,57 @@
+#include "common.h"
+
+static inline dline_t decode_line(char *line) {
+ char *cp = line;
+ dline_t res;
+
+ cp = sread_next_u64(&res.pt[0], cp);
+ cp = sread_next_u64(&res.pt[1], cp);
+ cp = sread_next_u64(&res.pt[2], cp);
+
+ cp = sread_next_i64(&res.dir[0], cp);
+ cp = sread_next_i64(&res.dir[1], cp);
+ cp = sread_next_i64(&res.dir[2], cp);
+
+ return res;
+}
+
+void read_pts(pt_t *pts, pt_t *dir, char **lines, size_t nlines) {
+ size_t i;
+ dline_t t;
+
+ for (i = 0; i < nlines; i++) {
+ t = decode_line(lines[i]);
+
+ fmpq_init(pts[i].c[0]);
+ fmpq_set_si(pts[i].c[0], t.pt[0], 1);
+ fmpq_init(pts[i].c[1]);
+ fmpq_set_si(pts[i].c[1], t.pt[1], 1);
+ fmpq_init(pts[i].c[2]);
+ fmpq_set_si(pts[i].c[2], t.pt[2], 1);
+
+ fmpq_init(dir[i].c[0]);
+ fmpq_set_si(dir[i].c[0], t.dir[0], 1);
+ fmpq_init(dir[i].c[1]);
+ fmpq_set_si(dir[i].c[1], t.dir[1], 1);
+ fmpq_init(dir[i].c[2]);
+ fmpq_set_si(dir[i].c[2], t.dir[2], 1);
+ }
+}
+
+/* DEBUG */
+void print_point(pt_t p) {
+ printf("(");
+ fmpq_print(p.c[0]);
+ printf(", ");
+ fmpq_print(p.c[1]);
+ printf(", ");
+ fmpq_print(p.c[2]);
+ printf(")");
+}
+
+void print_pp(pt_t p, pt_t q) {
+ print_point(p);
+ printf(" :: ");
+ print_point(q);
+ printf("\n");
+}
diff --git a/day24/common.h b/day24/common.h
@@ -0,0 +1,29 @@
+#ifndef COMMON_H_
+#define COMMON_H_
+
+#include <assert.h>
+#include <flint.h>
+#include <fmpq.h>
+#include <fmpq_mat.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <reading.h>
+
+typedef struct point3d {
+ fmpq_t c[3];
+} pt_t;
+
+typedef struct fromline {
+ uint64_t pt[3];
+ int64_t dir[3];
+} dline_t;
+
+void read_pts(pt_t *pts, pt_t *dir, char **lines, size_t nlines);
+
+/* DEBUG */
+void print_point(pt_t p);
+void print_pp(pt_t p, pt_t q);
+
+#endif
diff --git a/day24/exinput b/day24/exinput
@@ -0,0 +1,5 @@
+19, 13, 30 @ -2, 1, -2
+18, 19, 22 @ -1, -1, -2
+20, 25, 34 @ -2, -2, -4
+12, 31, 28 @ -1, -2, -1
+20, 19, 15 @ 1, -5, -3
diff --git a/day24/input b/day24/input
@@ -0,0 +1,300 @@
+257520024329236, 69140711609471, 263886787577054 @ 21, 351, 72
+227164924449606, 333280170830371, 330954002548352 @ 70, -28, -35
+269125649340143, 131766988959682, 261281801543906 @ 35, -337, -281
+220308068691946, 434660701646971, 160719186877066 @ 76, -149, 208
+255647674798651, 348515966374702, 193326101738764 @ 21, 73, 145
+425777063250656, 398815171620631, 423901841874772 @ -319, -319, -289
+188415254345592, 292913991854159, 346612358767416 @ 164, -60, -107
+300514501328886, 270309297308981, 326340712226252 @ -46, 12, -54
+289039137171838, 468769919737628, 381716316128222 @ -18, -173, -89
+281089998594418, 335433658881985, 343173481921168 @ -7, 15, -33
+177436721430566, 295404741895041, 368333466431252 @ 110, 99, -44
+390583517924614, 305563157479015, 455916814052890 @ -122, 97, -132
+316390218564578, 94210142972305, 113609203918400 @ -43, 323, 235
+217494185851307, 317231908134724, 209087996553667 @ 89, -25, 146
+398859584212576, 374365789797151, 272084558613922 @ -212, -156, 43
+284738314046726, 308838943112765, 298969128743400 @ -14, 12, 13
+258500719548744, 119196481669942, 231355675952968 @ 184, -73, 197
+276070022244263, 119143180340299, 246997268866856 @ -31, 128, 37
+287612959884088, 163732460667415, 224494638235387 @ -136, -288, 216
+138744850943906, 246978450581189, 262201404313448 @ 181, 120, 69
+214925199043846, 362854956964477, 170180041615288 @ 86, -62, 198
+524375133288654, 551676836247773, 453456562046416 @ -287, -206, -148
+243404783957458, 138088198721926, 240293943201394 @ 274, -129, 79
+432639860874625, 475961227591519, 182086551911797 @ -153, -52, 156
+298997468032671, 332994524020531, 306406567370602 @ -31, 8, 11
+248796935768422, 164250560458909, 274859873413192 @ 33, 237, 56
+215666495234376, 294963434751463, 388719648776211 @ 76, 68, -90
+266116411115626, 374672557744101, 517705416256347 @ 18, -386, -602
+53314403481341, 240185595220618, 107492161632073 @ 221, 179, 230
+433246080325834, 242548091401837, 364654794010360 @ -153, 178, -23
+261708563977444, 410743273979455, 353318916752986 @ 15, 13, -12
+231661835992448, 392732082129575, 396620647404212 @ 53, -35, -89
+252399647265481, 64551413022322, 189715549086796 @ 231, 653, 689
+248596888518654, 214895389050109, 339215263757088 @ 32, 182, -17
+289501795347174, 172849915843281, 261966795196168 @ -50, 81, 29
+246580000555160, 226773420464369, 247236148126364 @ 43, 120, 87
+262865107008690, 231291312503157, 389369053126168 @ 20, 82, -163
+224402368673112, 335266556685665, 284525560388246 @ 59, 48, 48
+259028656858350, 313306108079245, 388052014550672 @ 23, 8, -114
+343563015903846, 279465197359087, 225319940120420 @ -154, -88, 129
+243487299857086, 327698807944029, 329989814664768 @ 51, -62, -50
+254092291315150, 229307724010014, 217040217320482 @ 30, 129, 131
+250962442693274, 113870594257751, 267929392995850 @ 188, 121, -172
+193552378635286, 320860133672197, 131483264369480 @ 96, 59, 225
+336320370136175, 435967817075997, 296841952951833 @ -73, -90, 30
+297247644478025, 324140885794379, 314538386160773 @ -35, -36, -18
+261620994273099, 377928882770001, 299551864233153 @ 17, -14, 28
+251723504786366, 276931201154751, 313677887521467 @ 62, -216, -120
+219547969365044, 309418729749099, 41926971899166 @ 67, 67, 334
+298463183030206, 420767726669921, 241714063390072 @ -84, -749, 89
+328152267891238, 290973866532381, 189017920464864 @ -126, -134, 214
+235654135839526, 342481786754041, 281348737413542 @ 54, -16, 42
+151542147481500, 250311176603675, 76954336530912 @ 169, 109, 321
+302030981863750, 461220551215381, 304211715681808 @ -26, -54, 33
+285467835069001, 215958606887944, 288850948902946 @ -29, 27, -21
+356652661313106, 198259884514949, 306157526516196 @ -169, 108, -38
+322027461989845, 340373823259042, 272945705978890 @ -161, -487, -13
+330083518690557, 217086106069641, 388170305988278 @ -173, -54, -353
+274770090540966, 194725026991681, 323394034140072 @ -10, -100, -251
+300840503687206, 222456764830921, 368134061726227 @ -26, 186, -38
+163740425872818, 27054570370070, 110497390298223 @ 274, 487, 420
+248324142635734, 174166846456685, 213322406150616 @ 48, 172, 147
+275064285526458, 150430030914047, 254733791423160 @ -16, 15, 13
+191428283313343, 237008045073970, 255438105076522 @ 143, 75, 71
+232773431948008, 405327687452581, 376304583703682 @ 57, -94, -84
+239381202417290, 377786123364787, 373341255924356 @ 40, 17, -45
+273973064431901, 151118813420806, 280356225925947 @ -5, 113, -50
+261269375126440, 156865471816663, 214414124162584 @ 107, -361, 349
+242730954353485, 175902335761384, 446961523658482 @ 37, 233, -129
+313212438103774, 233688151713205, 182967845730184 @ -77, 47, 209
+286038044385622, 431302934026480, 321350509515040 @ -10, -33, 13
+279731765289830, 282069476141251, 306006776171674 @ -10, -19, -22
+327457003963726, 326490694948533, 381340101417016 @ -84, -48, -127
+261007151698463, 230308053861820, 266646659100387 @ 25, 59, 46
+296277119862156, 381850154144145, 476674193898042 @ -44, -246, -369
+316070147101994, 43164092698152, 94283473988772 @ -38, 373, 241
+370523048805954, 519355442919237, 259270891262436 @ -116, -198, 75
+256341031788436, 455155034984671, 421357897533214 @ 21, -49, -88
+254617994156168, 116446099862593, 227489322503254 @ 205, 20, 230
+292646139243686, 221959730744701, 340558547817192 @ -67, -112, -243
+257434946624214, 495083710713181, 455845492804385 @ 22, -154, -158
+216499937415046, 312941364640189, 147057503928808 @ 116, -122, 285
+262560883032124, 484374847397713, 13634567474884 @ 23, -476, 559
+265773177829978, 248085745690309, 272676355763080 @ 19, -72, 13
+202051178577044, 169545181700679, 56271569939922 @ 95, 225, 336
+293064317512360, 480122686618897, 69775676542054 @ -28, -270, 359
+175030840990763, 144191081411041, 92929384414597 @ 115, 266, 266
+251143580576981, 399472566775891, 478157245633944 @ 31, -64, -203
+357913330510190, 197692993180188, 186158532508650 @ -98, 199, 163
+314808296558798, 358340108820631, 373577832926148 @ -110, -379, -257
+253137554186230, 362000092322269, 62959304005768 @ 64, -558, 673
+292187970454544, 110870170306747, 546391539652150 @ -17, 305, -232
+333809786044606, 307148534161021, 275789391170032 @ -64, 86, 59
+236864010943558, 331025906220709, 290494800828976 @ 54, -12, 27
+142907510933503, 289447484208054, 322086042973348 @ 207, 15, -31
+237096816078931, 437083044501571, 72932581176877 @ 41, -32, 272
+345060694904842, 223969752443152, 375390337845952 @ -102, 133, -99
+247219682952196, 249228250952821, 301159201103512 @ 51, 26, -19
+146909000208550, 87475983340381, 192235680546088 @ 320, 336, 217
+258406044978185, 426577479340554, 321585854223631 @ 19, -23, 14
+546759680707426, 454811052554017, 341726525866654 @ -284, -56, -8
+253931690756986, 188215153396761, 188777078983932 @ 153, -513, 528
+269607846094273, 172358741794837, 201560237250280 @ 15, -242, 357
+252873978896386, 404006837834908, 455133811594213 @ 26, -21, -140
+306824079898999, 453526810781212, 347681905165705 @ -33, -67, -18
+258519904763366, 279453768994109, 283189454939408 @ 26, 22, 28
+284128764038614, 122865887688715, 290164298716171 @ -10, 288, 38
+238957705524646, 223356284043661, 498540058151752 @ 44, 169, -209
+230317645914892, 334860091178905, 409022243969761 @ 48, 74, -76
+276518065232281, 211484362356221, 266551906815492 @ -9, 6, 25
+256474359357190, 179121135241085, 250651582630216 @ 30, 180, 80
+318464679361946, 216581760262297, 330624820216586 @ -124, -16, -152
+285993883828197, 286309951999821, 334018792217069 @ -25, -74, -96
+212554047435046, 331203405675361, 159541157244772 @ 142, -233, 284
+281481291872240, 68400439837521, 322305480677266 @ -17, 376, -82
+295061889577639, 201580654459492, 311475155435266 @ -125, -271, -297
+193696069539493, 262483848746293, 217017659911894 @ 219, -146, 159
+124140624854344, 301348791150907, 242644163774710 @ 229, 7, 94
+358654955560126, 270769686702901, 259406469539656 @ -109, 91, 73
+280247025025944, 352745624486918, 352992264631676 @ -8, -65, -71
+269594179813050, 272875089981261, 295713061153694 @ 8, 46, 12
+294331022433350, 135771827027261, 271614987266088 @ -68, 186, -5
+245459217800646, 349474671008221, 320314561238952 @ 40, -19, -9
+279077631906406, 275913302553341, 330827933965352 @ -9, -12, -69
+262774782528894, 451548563984016, 346582130103875 @ 14, -29, -6
+286764059756174, 354563255628329, 307638197498704 @ -20, -105, -13
+260258023390560, 353958788759803, 329638445922056 @ 19, 5, -11
+242965071520527, 252306836786103, 295972010956295 @ 73, -60, -38
+281073826546636, 185404239635395, 265242354566755 @ -64, -320, -86
+238145744413556, 246502437606365, 334437515072328 @ 131, -266, -267
+280483472864552, 201098235174355, 295596974607028 @ -31, -97, -121
+221859606504631, 215635409567331, 358512983175382 @ 111, 60, -157
+380706113066008, 351782555796337, 304945347647536 @ -145, -32, 9
+275895660358372, 109095025330404, 244408187815636 @ -60, 93, 17
+189313782642534, 401283454582309, 371586254412336 @ 130, -145, -102
+256170150479389, 259944259108057, 308592661396999 @ 35, -6, -38
+363993920484490, 144872830986647, 144934008576868 @ -102, 264, 209
+259912764983308, 121256391156469, 279852695950594 @ 137, -30, -398
+167225870087526, 245625204944075, 346237375855263 @ 166, 88, -66
+251743163000641, 454307430659691, 377537921734897 @ 27, -72, -52
+348991776765342, 399409673440629, 460553326759664 @ -100, -92, -201
+183633486202216, 317322512652704, 181805532609194 @ 96, 93, 159
+235850807324405, 84375074447435, 284480492591048 @ 175, 360, -123
+257098435914275, 81467769453166, 259278551026696 @ 193, 461, -187
+356282499350896, 380851238258611, 452651806972672 @ -107, -57, -183
+291132244387838, 511148014784761, 439266852300576 @ -28, -379, -237
+265857627675806, 123733904488081, 256557745157192 @ 56, 5, -83
+281977969883677, 166620806684095, 220447390103095 @ -127, -576, 312
+295436866101583, 246444014012328, 170589780350417 @ -105, -375, 406
+223435029924358, 157484262657181, 251519271414952 @ 182, 81, 51
+235547646989746, 169903147279385, 251449740102144 @ 201, -107, 27
+82022698764860, 201215952106573, 169417972405582 @ 295, 158, 206
+333611460262698, 283040587273825, 423036454643894 @ -212, -340, -542
+349033656530035, 220698698603627, 286274340138002 @ -75, 192, 51
+329460643117362, 390305671379670, 313834644742448 @ -62, -21, 13
+293356676406166, 228469595765317, 299820329370292 @ -54, -40, -64
+254349802005622, 352589493236221, 248484275602984 @ 25, 26, 89
+272282404665232, 133510157556607, 292866914867176 @ -7, -67, -411
+300018590222990, 173171691680389, 160048907152640 @ -25, 239, 184
+310051252951074, 301556610011981, 325911129800568 @ -35, 106, 9
+184942875250902, 165747780677297, 234867482840908 @ 250, 115, 110
+254203358416722, 125973359668609, 243913341257652 @ 148, 32, 51
+302227910093702, 237974048888317, 291035176445832 @ -62, 8, -14
+208092841428385, 132315770663137, 344160435635434 @ 135, 242, -117
+415024258727179, 277950787512139, 397244512782781 @ -147, 128, -68
+251394657981431, 151367327630296, 215872553431802 @ 247, -415, 375
+222258171656587, 283029528104874, 257968855199527 @ 189, -395, 26
+255806743893285, 135514696983867, 245330799820716 @ 97, 60, 57
+285657595375835, 196169512957836, 145312518570742 @ -37, 21, 371
+299284133251720, 276330900240739, 313523834722738 @ -35, 59, -8
+295650382196858, 289029284685836, 312794208130709 @ -46, -89, -56
+394004465346012, 561184235546883, 231847573198726 @ -173, -357, 110
+264591480264645, 157646694249438, 206714031872400 @ 43, -63, 285
+232624248456049, 4456232128246, 168463114034812 @ 193, 751, 441
+259422877084431, 262124556356546, 292098173473177 @ 41, -195, -64
+237525829601851, 98097316244812, 322965303813892 @ 61, 315, -39
+334177054670029, 416077489350526, 336666450340432 @ -71, -69, -19
+224924462746416, 244321174680213, 307228288143518 @ 196, -306, -185
+216889279699866, 450145201771951, 426269647466000 @ 76, -139, -143
+152070098046106, 259752988004246, 226388638024052 @ 210, 37, 121
+291773349844668, 477761668048868, 414594739686658 @ -16, -81, -85
+210722928303316, 214227489451857, 299130651952588 @ 201, -72, -97
+286352502542572, 133393386015643, 192755379516523 @ -36, 212, 224
+267153377828600, 199114464075903, 284239075326008 @ 17, 9, -35
+231917580926707, 406018292236282, 261340922094838 @ 103, -457, 43
+281244456639170, 171796792071935, 230653939833358 @ -116, -621, 188
+270054487893421, 132377065689286, 440293542515722 @ 7, 277, -141
+259964809775270, 234138071617235, 238379093305475 @ 38, -92, 100
+314418505290576, 377931266195131, 352380537055112 @ -61, -115, -75
+325841024734986, 501327463002061, 545464947132532 @ -68, -226, -313
+387307094796694, 230477877377065, 335860155755569 @ -138, 154, -20
+296313695592616, 321213212371396, 252705042137827 @ -20, 91, 86
+191222826724738, 265934037847189, 291781573779582 @ 132, 50, 16
+117589582944086, 230638015109437, 49933604074328 @ 191, 158, 328
+261704797104278, 303264075577348, 197851290667742 @ 22, -43, 171
+317939429656722, 367792018267589, 268415879758608 @ -121, -420, 19
+267037309903546, 195750354662461, 261748110314152 @ 19, -26, 21
+267820758996778, 366144408181927, 300962360629126 @ 10, -32, 19
+250996761695374, 195036380212046, 261246749741556 @ 30, 201, 73
+100404741968938, 314819242397317, 172390952212258 @ 180, 98, 168
+253844966114641, 162130818435661, 234249830927182 @ 87, -10, 119
+287965734111631, 342092450405692, 266724476426098 @ -19, -41, 59
+278287816706516, 124085359603801, 228895404628967 @ -100, -142, 232
+256286821324454, 216894757033629, 283338123375848 @ 55, -95, -51
+488002360011426, 528153778762922, 387511006294125 @ -254, -197, -78
+267053940851244, 173957047668917, 232335042562122 @ 43, -470, 156
+270890255948806, 76384688043031, 16543277199172 @ 6, 348, 425
+264322616492155, 131840673785581, 208230694040059 @ 19, 246, 160
+357318776370511, 296458323577561, 519023901842857 @ -225, -222, -650
+343722530646527, 241818348857728, 136829187493641 @ -71, 167, 208
+238899850182998, 257252248618589, 266763751759400 @ 55, 72, 57
+410472170186554, 300797302332043, 347830764189805 @ -158, 80, -28
+259075057458591, 298537910392131, 122665734913982 @ 23, 28, 267
+401947050870196, 421734995551051, 484732816493992 @ -215, -231, -315
+295436356959682, 188639909979022, 258708073963816 @ -70, 25, 37
+301164576258637, 394943898697060, 332741957158690 @ -33, -65, -21
+230611624290492, 340792774745365, 73587973157270 @ 163, -646, 742
+294130899118290, 292545381480571, 240719285785954 @ -20, 101, 98
+419986775512327, 223673886181482, 417458908519501 @ -171, 169, -112
+210046656705894, 221284650255069, 421476584262824 @ 73, 183, -101
+256536196115606, 377070221656101, 436123698810712 @ 26, -72, -175
+294024076848118, 412084892885329, 201409123355308 @ -30, -173, 158
+287752386936064, 407837359501027, 381861731533282 @ -11, 7, -44
+253669210007785, 353792130900388, 253232713648747 @ 23, 67, 86
+329285404921043, 278743934821428, 390471763286833 @ -71, 79, -100
+435565227003866, 384626208707601, 386646793332972 @ -199, -39, -84
+301956582455098, 151950205030783, 220362004583110 @ -52, 213, 134
+145508229355056, 220818682420171, 215970436432052 @ 131, 197, 123
+283903107110011, 227047257522202, 89980344345064 @ -39, -143, 613
+202965406588408, 199152376776307, 221164621360606 @ 163, 77, 140
+324688003280358, 217684450222941, 359357082911256 @ -92, 96, -120
+263712828427606, 297974845196621, 264354907356952 @ 15, 67, 68
+293032563157288, 214477580871739, 297204821882758 @ -55, -13, -62
+192383446392359, 320982317146804, 233068887697587 @ 85, 95, 106
+216537650227484, 147484448394795, 141853480788956 @ 197, 129, 439
+277541994961116, 127533871327961, 245354586026093 @ -64, -54, 24
+252934485764848, 222996884909596, 233084357199736 @ 64, -99, 117
+226444500597445, 276533675790430, 324975524239390 @ 97, -53, -77
+268175373242422, 262462041477613, 282833237767888 @ 14, -178, -31
+256948593850391, 182455283500366, 106165951616956 @ 91, -229, 905
+291936273362624, 293158207649335, 434894933556435 @ -76, -460, -666
+252167416942606, 139345983193671, 240266582518052 @ 90, 111, 91
+256859489489286, 326878230624241, 429206866123512 @ 38, -211, -335
+296921570931256, 195549690905221, 159943728165202 @ -69, 26, 326
+244824499353906, 229419612948421, 337394204133112 @ 91, -124, -223
+219021053836747, 343194041227213, 238037673112552 @ 95, -106, 101
+281424002930362, 221340643747945, 255593918081812 @ -30, -118, 41
+236339921002766, 294407648783406, 430655790436725 @ 46, 91, -122
+268403596036630, 145509284065249, 264147602190400 @ 22, -22, -67
+235549117079609, 234725487212165, 260307431852046 @ 79, 30, 55
+272577516136076, 107332884169681, 200556393238197 @ -8, 194, 412
+269412247273325, 129056805712668, 251226058216844 @ 19, -5, -15
+274219329563866, 111953718268291, 244695820342672 @ -30, 104, 29
+257917446274690, 304034367301211, 323802359291430 @ 24, 31, -18
+279673396168814, 81386556438269, 187220933268220 @ -22, 358, 263
+303630226135526, 361529185015861, 376159422337777 @ -26, 62, -34
+379438076362510, 262553392750087, 384798756835162 @ -190, 17, -164
+334524546266722, 344578238109739, 212445621571651 @ -86, -40, 138
+306331523497257, 208098338303065, 264069754586193 @ -107, -46, 18
+204233089532542, 393342184743205, 312536859107200 @ 74, 18, 25
+235803542978134, 216354393825541, 339044877119032 @ 138, -144, -279
+283705160444800, 233773775512003, 283063013233612 @ -31, -85, -29
+151320036399894, 205840761750673, 40128344204008 @ 122, 215, 293
+222465813210841, 171752035987810, 305831892945703 @ 91, 185, -18
+202209798540041, 311201894683469, 142832349394195 @ 151, -138, 302
+299695907842732, 175754020577929, 334891459190680 @ -63, 124, -131
+398117670468102, 376692149467905, 242013529816280 @ -122, 39, 97
+252123774712927, 114561188663491, 259374905202661 @ 225, 56, -148
+260297779253622, 349616050420531, 262532775470165 @ 22, -64, 64
+111949386121450, 273297068091301, 268086195766480 @ 207, 96, 63
+203785056305625, 195883756528353, 293573010748288 @ 209, 10, -67
+288054983055728, 280828316293181, 293675064424644 @ -23, 6, 7
+220757552414794, 370867834007599, 206472637554100 @ 60, 25, 135
+242329415358062, 487196079161445, 302299564441726 @ 34, -62, 38
+259423970886769, 384255711021289, 319183690474660 @ 19, -6, 9
+288046962752004, 124457493327847, 308969132582490 @ -61, 197, -176
+172266022790246, 209773510765693, 278103767833217 @ 166, 134, 36
+270764300111361, 133493680682051, 256427225379522 @ 7, -8, -45
+274899413255917, 226642372878892, 266466243108430 @ -5, -45, 23
+287423131908296, 193992467267791, 220220690282422 @ -97, -313, 212
+264226198390534, 85385128813237, 273232227092176 @ 38, 355, -68
+217997361030196, 407047607211061, 371570555366092 @ 67, -38, -53
+218331548913406, 359473836855961, 404473578724652 @ 66, 20, -89
+262288707957077, 95892767594501, 247756305259051 @ 83, 286, 14
+373778295055641, 327619581620677, 197777136070747 @ -109, 62, 146
+142930240619630, 52699689494223, 51148703355466 @ 158, 372, 323
+343810011749478, 263780217413373, 311786062501868 @ -82, 118, 12
+267313687303465, 133151065171066, 250356965113171 @ 33, 11, 8
+245950696744438, 184947777991801, 136201139694716 @ 54, 146, 297
+261775574212646, 91424430975421, 169677560091352 @ 26, 326, 251
+267107776690654, 139110687337123, 272620340615656 @ 34, -27, -155
+393210959788167, 458386542493504, 195614307619132 @ -167, -193, 161
+277753944254149, 64099181306980, 242829304570999 @ -47, 537, 64
+287539496022912, 367946592206225, 358201753647404 @ -17, -56, -65
+158001159792996, 292019671067668, 3575704173562 @ 136, 95, 371
+308916843050680, 374813044377482, 320428611833279 @ -36, 13, 10
+463476116425270, 311966303456533, 270653020451308 @ -242, 42, 59
+355839126742670, 342409731048201, 383802212770205 @ -82, 66, -50
+290420569743818, 221768046955175, 407441916682330 @ -40, 19, -298
+398305966619496, 307051018264281, 264500936098003 @ -124, 106, 74
diff --git a/day24/uppga.c b/day24/uppga.c
@@ -0,0 +1,152 @@
+#include "common.h"
+
+static int inint(fmpq_t x, fmpq_t min, fmpq_t max) {
+ return (fmpq_cmp(min, x) <= 0) && (fmpq_cmp(x, max) <= 0);
+}
+
+static int online_segm(pt_t *a, pt_t *adir, fmpq_t min, fmpq_t max, pt_t bt) {
+ int ret = 0;
+
+ fmpq_t t;
+ fmpq_init(t);
+
+ fmpq_sub(t, bt.c[0], a->c[0]);
+ fmpq_div(t, t, adir->c[0]);
+
+ if (inint(t, min, max)) {
+ fmpq_mul(t, t, adir->c[1]);
+ fmpq_add(t, t, a->c[1]);
+ if (fmpq_cmp(bt.c[1], t) == 0) {
+ ret = 1;
+ }
+ }
+
+ fmpq_clear(t);
+ return ret;
+}
+
+static int para(pt_t *a, pt_t *adir, pt_t *b, pt_t *bdir, fmpq_t min,
+ fmpq_t max) {
+ int r = 0;
+ pt_t bt;
+ fmpq_init(bt.c[0]);
+ fmpq_init(bt.c[1]);
+ fmpq_init(bt.c[2]);
+
+ fmpq_mul(bt.c[0], bdir->c[0], min);
+ fmpq_add(bt.c[0], bt.c[0], b->c[0]);
+ fmpq_mul(bt.c[1], bdir->c[1], min);
+ fmpq_add(bt.c[1], bt.c[1], b->c[1]);
+ fmpq_mul(bt.c[2], bdir->c[2], min);
+ fmpq_add(bt.c[2], bt.c[2], b->c[2]);
+
+ if (online_segm(a, adir, min, max, bt)) {
+ r = 1;
+ }
+
+ fmpq_mul(bt.c[0], bdir->c[0], max);
+ fmpq_add(bt.c[0], bt.c[0], b->c[0]);
+ fmpq_mul(bt.c[1], bdir->c[1], max);
+ fmpq_add(bt.c[1], bt.c[1], b->c[1]);
+ fmpq_mul(bt.c[2], bdir->c[2], max);
+ fmpq_add(bt.c[2], bt.c[2], b->c[2]);
+
+ if (r == 0 && online_segm(a, adir, min, max, bt)) {
+ r = 2;
+ }
+
+ fmpq_mul(bt.c[0], adir->c[0], max);
+ fmpq_add(bt.c[0], bt.c[0], a->c[0]);
+ fmpq_mul(bt.c[1], adir->c[1], max);
+ fmpq_add(bt.c[1], bt.c[1], a->c[1]);
+ fmpq_mul(bt.c[2], adir->c[2], max);
+ fmpq_add(bt.c[2], bt.c[2], a->c[2]);
+
+ if (r == 0 && online_segm(b, bdir, min, max, bt)) {
+ r = 3;
+ }
+
+ fmpq_clear(bt.c[0]);
+ fmpq_clear(bt.c[1]);
+ fmpq_clear(bt.c[2]);
+
+ return r;
+}
+
+static int has_solution_in(pt_t *a, pt_t *adir, pt_t *b, pt_t *bdir, fmpq_t min,
+ fmpq_t max) {
+ int r = 0;
+ fmpq_mat_t A, Ainv, B, x;
+ fmpq_t is[2];
+
+ fmpq_mat_init(A, 2, 2);
+ fmpq_mat_init(B, 2, 1);
+ fmpq_mat_init(x, 2, 1);
+ fmpq_mat_init(Ainv, 2, 2);
+ fmpq_init(is[0]);
+ fmpq_init(is[1]);
+
+ fmpq_set(fmpq_mat_entry(A, 0, 0), bdir->c[0]);
+ fmpq_set(fmpq_mat_entry(A, 0, 1), adir->c[0]);
+ fmpq_set(fmpq_mat_entry(A, 1, 0), bdir->c[1]);
+ fmpq_set(fmpq_mat_entry(A, 1, 1), adir->c[1]);
+ fmpq_sub(fmpq_mat_entry(B, 0, 0), a->c[0], b->c[0]);
+ fmpq_sub(fmpq_mat_entry(B, 1, 0), a->c[1], b->c[1]);
+
+ if (fmpq_mat_inv(Ainv, A) != 0) {
+ fmpq_mat_mul(x, Ainv, B);
+ if (!(fmpq_cmp_ui(fmpq_mat_entry(x, 0, 0), 0) < 0) &&
+ !(fmpq_cmp_ui(fmpq_mat_entry(x, 1, 0), 0) > 0)) {
+ fmpq_mul(is[0], bdir->c[0], fmpq_mat_entry(x, 0, 0));
+ fmpq_add(is[0], is[0], b->c[0]);
+
+ fmpq_mul(is[1], bdir->c[1], fmpq_mat_entry(x, 0, 0));
+ fmpq_add(is[1], is[1], b->c[1]);
+
+ if (inint(is[0], min, max) && inint(is[1], min, max)) {
+ r = 1;
+ }
+ }
+ } else {
+ r = para(a, adir, b, bdir, min, max);
+ }
+
+ fmpq_mat_clear(A);
+ fmpq_mat_clear(Ainv);
+ fmpq_mat_clear(B);
+ fmpq_mat_clear(x);
+ fmpq_clear(is[0]);
+ fmpq_clear(is[1]);
+
+ return r;
+}
+
+int main(int argc, char **argv) {
+ char **lines;
+ size_t nlines = readlines(&lines, "input");
+
+ pt_t pts[nlines], dir[nlines];
+ read_pts(pts, dir, lines, nlines);
+
+ size_t i, j;
+
+ fmpq_t min, max;
+ fmpq_init(min);
+ fmpq_init(max);
+ fmpq_set_ui(min, 200000000000000ULL, 1);
+ fmpq_set_ui(max, 400000000000000ULL, 1);
+
+ size_t count = 0;
+ for (i = 0; i < nlines; i++) {
+ for (j = i + 1; j < nlines; j++) {
+ if (has_solution_in(&pts[i], &dir[i], &pts[j], &dir[j], min, max)) {
+ count++;
+ }
+ }
+ }
+
+ fmpq_clear(min);
+ fmpq_clear(max);
+
+ printf("%lld\n", count);
+}
diff --git a/day24/uppgb.c b/day24/uppgb.c
@@ -0,0 +1,100 @@
+#include "common.h"
+
+static void systemsolver(fmpq_t res, pt_t *p, pt_t *d, size_t n) {
+ fmpq_mat_t A, x, b;
+ fmpq_mat_init(A, 6, 6); // should be enough unless linear dep
+ fmpq_mat_init(x, 6, 1);
+ fmpq_mat_init(b, 6, 1);
+
+ fmpq_t t;
+ fmpq_init(t);
+
+ size_t i, j;
+ size_t ii = 0;
+ for (i = 0; i < n; i++) {
+ for (j = i + 1; j < n; j++) {
+ // A[ii,0] = d[j,1] - d[i,1]
+ fmpq_sub(fmpq_mat_entry(A, ii, 0), d[j].c[1], d[i].c[1]);
+ // A[ii,1] = d[i,0] - d[j,0]
+ fmpq_sub(fmpq_mat_entry(A, ii, 1), d[i].c[0], d[j].c[0]);
+ // A[ii,2] = 0
+ fmpq_set_ui(fmpq_mat_entry(A, ii, 2), 0, 1);
+ // A[ii,3] = p[i,1] - p[j,1]
+ fmpq_sub(fmpq_mat_entry(A, ii, 3), p[i].c[1], p[j].c[1]);
+ // A[ii,4] = p[j,0] - p[i,0]
+ fmpq_sub(fmpq_mat_entry(A, ii, 4), p[j].c[0], p[i].c[0]);
+ // A[ii,5] = 0
+ fmpq_set_ui(fmpq_mat_entry(A, ii, 5), 0, 1);
+ // b[ii] = -d[i,1]p[i,0]+d[i,0]p[i,1]+d[j,1]p[j,0]-d[j,0]p[j,1]
+ fmpq_set_ui(fmpq_mat_entry(b, ii, 0), 0, 1);
+ fmpq_mul(t, d[i].c[1], p[i].c[0]);
+ fmpq_sub(fmpq_mat_entry(b, ii, 0), fmpq_mat_entry(b, ii, 0), t);
+ fmpq_mul(t, d[i].c[0], p[i].c[1]);
+ fmpq_add(fmpq_mat_entry(b, ii, 0), fmpq_mat_entry(b, ii, 0), t);
+ fmpq_mul(t, d[j].c[1], p[j].c[0]);
+ fmpq_add(fmpq_mat_entry(b, ii, 0), fmpq_mat_entry(b, ii, 0), t);
+ fmpq_mul(t, d[j].c[0], p[j].c[1]);
+ fmpq_sub(fmpq_mat_entry(b, ii, 0), fmpq_mat_entry(b, ii, 0), t);
+
+ ii++;
+ if (ii == 6)
+ break;
+
+ // A[ii,0] = d[j,2] - d[i,2]
+ fmpq_sub(fmpq_mat_entry(A, ii, 0), d[j].c[2], d[i].c[2]);
+ // A[ii,2] = d[i,0] - d[j,0]
+ fmpq_sub(fmpq_mat_entry(A, ii, 2), d[i].c[0], d[j].c[0]);
+ // A[ii,1] = 0
+ fmpq_set_ui(fmpq_mat_entry(A, ii, 1), 0, 1);
+ // A[ii,3] = p[i,2] - p[j,2]
+ fmpq_sub(fmpq_mat_entry(A, ii, 3), p[i].c[2], p[j].c[2]);
+ // A[ii,5] = p[j,0] - p[i,0]
+ fmpq_sub(fmpq_mat_entry(A, ii, 5), p[j].c[0], p[i].c[0]);
+ // A[ii,4] = 0
+ fmpq_set_ui(fmpq_mat_entry(A, ii, 4), 0, 1);
+ // b[ii] = -d[i,2]p[i,0]+d[i,0]p[i,2]+d[j,2]p[j,0]-d[j,0]p[j,2]
+ fmpq_set_ui(fmpq_mat_entry(b, ii, 0), 0, 1);
+ fmpq_mul(t, d[i].c[2], p[i].c[0]);
+ fmpq_sub(fmpq_mat_entry(b, ii, 0), fmpq_mat_entry(b, ii, 0), t);
+ fmpq_mul(t, d[i].c[0], p[i].c[2]);
+ fmpq_add(fmpq_mat_entry(b, ii, 0), fmpq_mat_entry(b, ii, 0), t);
+ fmpq_mul(t, d[j].c[2], p[j].c[0]);
+ fmpq_add(fmpq_mat_entry(b, ii, 0), fmpq_mat_entry(b, ii, 0), t);
+ fmpq_mul(t, d[j].c[0], p[j].c[2]);
+ fmpq_sub(fmpq_mat_entry(b, ii, 0), fmpq_mat_entry(b, ii, 0), t);
+
+ ii++;
+ if (ii == 6)
+ break;
+ }
+
+ if (ii == 6)
+ break;
+ }
+
+ fmpq_mat_solve(x, A, b);
+
+ fmpq_set(res, fmpq_mat_entry(x, 0, 0));
+ fmpq_add(res, res, fmpq_mat_entry(x, 1, 0));
+ fmpq_add(res, res, fmpq_mat_entry(x, 2, 0));
+
+ fmpq_mat_clear(x);
+ fmpq_clear(t);
+ fmpq_mat_clear(A);
+}
+
+int main(int argc, char **argv) {
+ char **lines;
+ size_t nlines = readlines(&lines, "input");
+
+ pt_t p[nlines], d[nlines];
+ read_pts(p, d, lines, nlines);
+
+ fmpq_t res;
+ fmpq_init(res);
+
+ systemsolver(res, p, d, nlines);
+
+ fmpq_print(res);
+ printf("\n");
+}
diff --git a/day25/Makefile b/day25/Makefile
@@ -0,0 +1,26 @@
+CC=clang
+CFLAGS+=-std=c99 -pedantic -Wall -Werror -Wstrict-prototypes
+CFLAGS+=-Wmissing-prototypes -Wmissing-declarations -Wshadow
+CFLAGS+=-Wpointer-arith -Wcast-qual -Wsign-compare
+CFLAGS+=-O2 -g
+CFLAGS+=-fstack-protector-all -Wtype-limits -fno-common
+CFLAGS+=-fno-builtin
+CFLAGS+=-I/usr/local/include
+CFLAGS+=-I/usr/local/include/igraph
+CFLAGS+=-L/usr/local/lib
+CFLAGS+=-I../utils
+#LDFLAGS=
+
+UTILS=../utils/reading.o ../utils/graph.o ../utils/stack_u64.o
+INCLUDES=-I../utils
+
+all: utils uppga
+
+uppga: $(UTILS) uppga.c
+ $(CC) $(CFLAGS) -o uppga uppga.c $(UTILS) $(INCLUDES) -ligraph
+
+utils:
+ make -C ../utils
+
+clean:
+ rm -rf common.o uppga uppgb
diff --git a/day25/common.h b/day25/common.h
@@ -0,0 +1,15 @@
+#ifndef COMMON_H_
+#define COMMON_H_
+
+#include <assert.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <graph.h>
+#include <igraph.h>
+#include <reading.h>
+
+size_t fn(char **lines, size_t nlines);
+
+#endif
diff --git a/day25/exinput b/day25/exinput
@@ -0,0 +1,13 @@
+jqt: rhn xhk nvd
+rsh: frs pzl lsr
+xhk: hfx
+cmg: qnr nvd lhk bvb
+rhn: xhk bvb hfx
+bvb: xhk hfx
+pzl: lsr hfx nvd
+qnr: nvd
+ntq: jqt hfx bvb xhk
+nvd: lhk
+lsr: lhk
+rzs: qnr cmg lsr rsh
+frs: qnr lhk lsr
diff --git a/day25/input b/day25/input
@@ -0,0 +1,1220 @@
+mgz: mbb
+bll: chq kss
+knv: vrs gvd hcf
+lxq: kpc
+dvn: sfp rbx
+gss: pfp dts hkg rvr
+bqv: mjc bmn jlt
+txs: fpv vrn
+qpn: tvx
+vlh: lns vbx
+hsd: rts trh kdz
+crj: tml qvk zvj jcb
+dnt: bpc vmz
+hsv: hqp fth djt
+tjq: grs tpp pzd jkz
+rbz: tbb bcm pjp sgm
+vfg: gjc jnm hzd pdt
+szg: fpt qxc dqv jbp
+vjx: dtk lzz
+kjj: kxb cqs
+hzs: clk gdv
+knq: hbk nsm
+dsp: kpj frb bck tgv
+clx: sfh jnm
+ncb: rhp ghk
+fth: fxm
+vbl: vjh jlt rmf kdh
+hvb: gvn zmk hdp nmf
+fmp: ccn fjn mkd nxh pcz clt
+ktr: fxm xgf
+slr: dnz dnt dhz ggm
+ckf: vzc fnv
+pfh: sbx hzf vpp dhm dgh
+mbk: kxb
+svf: xxc
+pgt: pbl
+shq: fxj szx zhg
+bnl: pbl qsk mrz dnk znf
+rjx: gpn
+xzt: ptk
+jbl: chq
+cjp: vqh khh
+csz: jmn chq vpj jxr
+pjc: pdc xqt sbh
+bkz: cfg clb
+dtb: fmb vsb qfg lcr
+zmb: thk
+gch: njt
+cfx: tgn vfc shr
+vbr: rxf
+xkv: kgg
+cmd: rtn
+ffr: cpm znh mqz
+mcq: vml tgc lth gfb
+jtv: pdt
+brd: ggc
+xjs: rnd xcx hvv rpc
+njh: tqq kzx tnv ghc
+dvm: sjv bmb kzk
+fmm: hgp xgz vxq bxz
+vjn: hlg cpx fcp qqr
+qlf: rtn vlt dln vpv
+jpv: ntx fgg bhg
+bbm: mnl
+hjz: mhr dcg xtc
+dhf: hxj qxh ncb cjs
+xxq: rrd ffg ndx glq
+tgn: fpp
+lzr: hpm lsr jkq tms
+dtz: bhg rmf bjf
+jrm: vxn
+khj: sdp bcj dcm lbl
+mvv: rnn thk tcl kkn
+zjn: qxp qdf bpd
+ztg: lzx nmt dmg
+dlm: hzm szx cgn xxx sfh
+zft: sbx tsx qfx qlt
+xvk: kch tcp nqp vxk
+zxq: mbb dcm
+zlq: knl hpt qhv fpn
+nsm: vpp
+sgq: hgg hcs kdq pjb jjt
+tvc: flm
+nlk: vtl fjn khh
+lmb: fzh ghz dtb vqx
+mtq: llz bqz
+qbf: qnk ztv gvl
+mgg: qqb vbv
+fsm: jtm
+bcm: lnp fcc
+ldp: hcg
+gsk: lcg dkt
+jbf: vgp lvk
+qcz: tbh crj qgk kmd
+xtm: cng xhv nkr cfg
+nmn: bxn bqc tmt
+frj: gnt jkq cpx jpl
+qkk: bjb bpl hgp rvr
+grk: zfs qxh
+lzl: jdh
+czl: tjq vcg bcn jhs gzq
+qcn: jpk pcn bmj
+rnb: tdk thk
+xjl: xrd lkm kgm psr
+nqb: zhn
+slg: ttv bqj prs
+vfx: ptn
+bsv: bcp prs dbr smc ksb
+rpf: mcb hfd
+sbk: mrv
+hfp: ccn rfp qjg
+rlk: cfg
+pqh: mhr dln ltt
+pxz: cfg mhb
+kdz: tqs shr
+zzj: qlx zvl jjz nmt
+ddv: vgd dbt
+lqn: sdz kzk tmz vsr
+bkc: jrm nbx rjx
+hnn: jhx
+hxs: sfp flz tch
+jjn: skm bts vcg kvf
+tkm: pcz rmc nfb bhc
+fbx: qlz rnx hch
+jdg: kzd cmd ggp
+ghz: ndx
+fhk: jzc bhk kdc vch mdm
+szc: cbh
+bhg: mnp
+jlg: cfx lzz dxt fnv
+gzj: dbn
+hfb: bcb dhn
+frh: nlv tpp qjn jst
+jxz: cbm bbm qpz xhv vml
+jgn: pxp kjj sqv ztj
+fdm: tbc nfh gnn
+vfk: hhr zzv nxz htl
+hlm: ghk
+vpj: gbh
+nfd: qfx vhp hrb tlt htq
+ktp: jgm
+ngb: gdd xxb jzl
+bhc: tkv lcv vml
+qpv: ccs cxb
+bbc: xpn
+dnk: djg vpp
+knl: lrr bcp qmn hsd
+bgj: ltm kcj dzj tjp cxk mbz hkk
+plg: mlj txk
+tbg: nxj qmb
+dcc: snb grk jml
+jkq: vfb cxd trr ctx
+dcg: jzl hzm
+bmn: zxc vsl
+dvd: ghk xrt dkt
+ttg: vgq
+rmx: rvd zjd jkp jdg
+ccs: vbv
+tqp: vsv mqj tdz cbm qnf
+dlh: ktp
+rqc: jkd hgg
+bkd: vmz kfh gzj
+ssf: tjz dtl smp
+ttr: kpc qmz
+kmg: ljp npx
+xrp: zhd
+kdq: xch xzt fzh
+qgk: pht jjz ckf
+rnd: czh
+fnt: zdb cgb fjx
+tpf: bxk
+ztj: ccs ssc
+czq: cgn dcg rlt kgx
+tld: ctf
+qnr: tqk ckf
+nsr: vgp mdd
+tzr: shr
+ksq: qzk nfb
+rdq: qhv vbx
+xnc: mdm djx lcg kcz
+mnr: ktx
+kqq: tgn kjj dpz qbk
+rll: pxx
+nzx: ncf tdv mfc hmr
+ctl: mmk zxc qmr
+frs: zqx
+jxl: nlv
+dhz: vps bmj tsx mbc
+bqj: tvx svf
+tbc: fll
+trl: srg vcz pdt nlz
+bcp: bjz
+jkd: bxx
+dmj: xpr bbm xkv
+qhf: nlv nfx gvt thl
+zsn: hch llz gvl
+zmg: bvg zsp nfd jvx
+njt: nsm kkl
+tkv: zrd zmz ldp
+zzs: vzc pps lln dmg
+rts: dtk kgz
+glx: dhd tms hjz vgc
+hkz: cmk hnp hxt
+tcl: gbh
+skh: ccb ctf qvg
+cds: ncf
+vdj: cds mnq sgm fcc
+plm: trh fkr
+qkb: vnl jst
+jlk: zbx zrd tbc gvd
+xnz: blq rgr tvx qkg
+jvv: zmb hfb brh djt
+vxj: jst
+phf: spr vlh blp png
+mqt: stc
+hpn: qck vjx gfs bqj
+prt: bcn rsp tkv kpj
+qbs: dbp xrp gvd
+fpt: kxb
+bnt: ghz dzl bjr rxn zmf
+fmn: bqz clk dbg
+fnk: dqz hxj
+qmq: nqd bmn gbg kvz
+rkm: fll qbx cgz
+lpk: xqv xkv qrt ccv bsc bnb
+sdb: kct jzb
+chq: dnk cqh rbc
+dkt: kch ghc btt
+lhv: qpn
+mhr: nqd
+qmn: hlm dqq dxr
+phb: brx pxz mnr ndp
+vcz: lkm
+rgq: hgp xtp tzf sbk
+blq: kjj ght lvk
+njv: jsn
+tfk: lch ckn zvt
+lxf: mtq vrs qvg mvx vtm
+lth: mfs vmz
+djk: zbh lxt rfq bkp
+jll: dqz gdc vlt bgm
+xdx: vsd mrv vcg pjv
+mpm: bsk
+lbv: gbj qpv dxt vlt
+mvj: tqs zvl
+shd: jhr
+zrd: czh rpr tbq
+fpk: hcs nvr gnt fkr
+zvj: gjc lcr dbr
+stt: ghk rqh jkq nlb
+rsp: sgj ctf xvj
+cqh: vqh dnz xgl gds
+xtp: vcg
+hsz: bjf xvv vcz srm klr
+hsp: hmh tmt tfk
+lxp: njk qms bjz srb
+fpd: bhz tmz kss
+tgs: vsv gxx rfp xsj rxt
+ntb: xvm pqx
+gzq: bbc cbh
+ssk: crh cjp gbh bsr dlr
+hqh: jtv
+sqz: pcl rsr scf zmz qjn hmv
+dmd: pfp kzb gdv
+qrt: xrp frs htm jzg
+hph: qnr jdg
+lrn: str vzc zvk
+tmr: kgz dxt hph ztg
+qfg: cfx cmq fmb qxh jlm gfg
+rxt: brz nfx lzk
+lpr: blp jdh
+lzk: vps bxm
+zth: ssc qpn hsn tjp
+mbz: fnl cnt
+nht: lmk xvv hjz ttr
+vqm: bll nfl kjh ggc
+nng: mqz ktb ktn hxf zmb
+ftc: xpn qfd
+mtm: rvr vtp lpn zhb zrc
+svp: dvn mgg jjz
+dpr: vnl
+klj: cgx ztl jrm
+gsv: tld gvq qdv tlt rzd
+rvs: ccb
+kdh: gsm
+njk: lzl fxj qfm jtv
+xgb: qns phc zxq zct
+slz: tgn mmk nmf rdz mnp
+nkr: pgk
+zxp: pht
+xvv: xdg hfh
+qnf: kzk
+trh: cxd vdd
+rbk: vnl
+fmb: rvd
+xxb: pxd
+kjh: htl dpr
+qzm: rtv zxq
+gmd: zzv spk mqv pfp qts
+mtd: dcd xpx fsn
+tnv: mdm
+grs: clk
+bvm: jgm sbx qkt
+vlt: vgj pnh
+krg: kkl hpq nfb pzd dzh qpb
+mvx: lth
+qsk: vtm
+bbx: njv mfs gvd tbq
+hhk: pzz qnr
+snv: dbv tdz gdv zhc
+qfj: jsn sfz qtv jsh
+tzq: gsk zfs
+psc: vzt xrj htc rxf
+vkf: thl qbv fgq vpd
+hbb: qpz cng
+ljq: mtz mlz vxn
+lcg: tbh ggp
+pfs: nqd nvr
+zsz: zhd bhv
+cjs: bhq
+xsl: gbg
+bvr: jml qpt mpm
+xcq: hdn pqd lxk xbc rsk
+gvt: gpr
+jhs: nqb
+qzr: qpt
+qfd: spn tdk
+tmc: nqx bbc
+dbp: cbx
+ndz: gtr xgm vsl lbz
+rnx: xjc gdj rlk
+cxk: gdc
+lnq: ktp spn
+mtt: gvn hcx
+jqn: fzq xfl hnh
+pqs: xtq xbv kct
+jkb: rbk spb
+zct: szc
+znx: llz tgc lpq khj
+spr: bgm
+pqd: dtn gtr
+qfx: bxz
+gfg: zvk
+bxj: gbj vsl xrt xrd
+tpp: mqv
+ngc: gqr lmr vts mqz
+xzk: pgt tqp spb mqv
+plt: trr lzl vjh pht
+kpc: hzm bhq
+slb: brd mvs
+jbp: qms mjc
+mgm: chq gnz clb
+htc: rrp rxf
+fps: khc
+ndp: zrc htm
+zsp: vtm hdm
+xml: flb hnn rpf shx
+msb: lmk
+qns: vpj rfj ggc
+qts: smb dhn pnx bxn
+lcp: vpp vtl ztv nhl
+vhx: pqx pxz vps
+zgv: rns cls jpv gpc
+qhm: hcg
+jcd: pbl
+dtl: zhn dkj
+tzf: gxq
+vgc: lkm mbk vcv
+qvk: pxd bxx rqc
+hpt: fpp
+lkm: vmk
+zdb: kgz
+dgh: xsj xgz
+csj: dbm shx
+ddz: vmj cqs lzd
+bbz: vhz gcf dmd xzk
+sbh: qqb
+kxx: pqd lzm xfl fnk
+xmr: gfb ktz xmm xrp
+ltt: nsd mpm tzr
+hbm: szz bjb
+qrs: xgz hfc bkc
+rlt: cxk vlh
+bzb: tgv ckl ktr
+btp: snb znt vbv mcm
+qpc: nnj kjh pfh nhp
+fht: qlz thk zsn zhn mdv tdz
+rkh: gcv tdz fxm
+cmk: clx pps stn
+jml: lhc nlb
+pdg: phc hvx qdc lnq txs
+vtl: zrc
+qrm: pxd
+ctx: kdh
+nhp: vrs tzj
+dlx: kgg
+knb: gnk kcf tzf tzt htm
+lpd: qqr qrq xzm
+jlm: kch gbj blb
+hrb: mgr
+prk: gpz zlt clx
+ljp: cmq lbz bcx
+jtg: tvn
+tpq: rll lpg htc hfv nbp
+jcv: cgz gxq
+hkg: mtz vmz
+fjc: jpl qvq qhv nxj fpp svp hkk
+xpr: mqz czh
+qxm: thl xpk zdv gfb
+rsk: kfs gjc dqq
+vrs: ppg
+nlx: vpt
+bfh: rll pck xdh
+kvh: nmt
+xrd: ghc vcv
+qck: gdd
+vlv: ckn gzj ktb vjc lnq
+hqp: lqr
+vmz: mhq
+hfc: dlv vnl rvs
+kpg: psb ccb tzf lvf cft
+cdf: bhv mvs gzj
+gxx: hpz
+skz: zhn kgk sll hzs
+qbv: gpn dlt
+shl: blr tcn fvn
+pzt: gnt ttr vmj
+flt: sll xpk
+nmf: qqb kvh rhp
+fkk: pvd thl xrq jbl
+lvk: vgj
+dlt: jgm
+gvh: vqh
+tcg: bnb rlk pnx plg mxb
+snn: lhv bcp jcl rgd
+szx: hcs clq xsl
+jrg: cgb klr xgm
+zql: tkc ccv
+zpp: xgm gvn nlx
+lvp: gcd fps qpc sjv
+stn: ctl
+ggk: gpc hfh tbg fsm
+fhb: zmb zhb
+bpc: fxm rfj cch
+rfq: lsk phf jbf
+pzd: bxg gvg
+nlq: ddv xpk
+txj: fkr cxk hgk
+llh: vgq hbm vsd
+rrd: rmf vtb tqs trx vzt
+rfx: tmz djg gvq
+rtv: lqr ggm
+cgn: tqk
+psn: bmj grs qfd vhz
+vhr: kdh sqd vzt sfq
+vjh: xsl dqv
+lrb: vqx lnp shq
+dxr: qnl gpc
+tbk: cqs
+mtx: mvs ppg hdm
+kgz: jdh
+rqt: qdf kmg vdh fdt
+bls: bvg nqx nfl qxz
+rfn: snb bgm gqp xbv
+cgz: chx
+fcp: jqn klr
+xrn: jft mtd fnt ptk bpd
+bmj: szz
+dcd: xxk
+rxn: mnz ksb hmr
+mmx: ksx gch vxr kzk
+bxn: tzj mbc
+djq: ktz
+znf: qkt dpr
+dct: kpj kbd hrb sxm dnh
+bnh: sfq rrm kfs vdh
+vzt: gdc
+gms: csg tzr smc vjx
+bjr: npx nsr znt qmb
+gbl: mrx fnv bcg
+xvj: lms
+fvb: jlg tvj gbl prs dkp
+ngk: qhm kbf tcl
+sdk: mhj vrx smb nfb
+jxx: blq jzb kkm
+tls: bls vqg mfs tfc
+hgb: dmg qlx
+smb: lzk
+rbr: rjx gxx kzq
+ffg: jcl ptn jdj srg
+jfv: fgx rbr dbp dbg
+dsg: brh
+djn: mtq shx dtl
+lhc: rtj
+hvv: rnb bjb zgb cbl
+vxq: tkc
+dlr: zqx ktp
+hbg: pnd crj qgk bfq fcc
+kss: rbd
+rzt: mdd qvq
+kqz: vtz fmn mnr bkz
+rfp: rnd tlt
+pnx: tgv vhp jpk
+mcm: srp rsk ptn
+rqr: txs xdx fdm lpn
+zrj: zjm bcb
+ktx: nxz
+xzb: shn rlt jtv lxq
+nkn: dhm ppp hqp nfb bcb
+knp: kfh njv stc nkn knq
+gnk: dlt sqf
+qbn: gqb dqv krm kkm znt crn
+dtt: zjk sqv frr lxk zbh
+vdk: fzq mrx cds qkl
+qcg: vhx dsm vgq hbt shl
+dzj: lxt lln msb
+bsc: llz psb
+qjt: gvh bsb
+dbm: bqc
+htm: fvn rlk
+sjv: dbm ktx
+mnz: mgd hgg xzt
+xvm: rrf fqv
+mlz: rrs ftx zvt
+plp: gjc llg zjd xqt mdd hxj
+tdv: ztn zxv flz
+lqr: ppg ckl
+ljt: jhr lqr lsb qdc
+pqb: rrp
+kdc: str
+xcm: gph tcn rrs plg
+ftb: jhx
+ktc: czq zmk xkm tpq jkd pql
+pfr: rbx nxj plm
+rgb: jtv xxx
+blp: lzx jxx mnp
+qbk: zhg dmh
+ctt: xjr xlq
+tkt: xgm qmr
+vhp: flt hvx kbd
+kbd: qbg
+xzm: nlx vpt
+hxt: vcc stn nrf
+pzx: vpq prd qfj npp ctt
+gpr: tmz
+fxt: nps ccn mkp ntb qzm pbl
+gfs: mdm
+pdk: lvf hhr jbl bll
+nlz: dmg
+txk: xjc
+kgg: vml
+sjg: qrm pxx jtd
+gsm: nlb
+jtk: rzt lhv hcx lln
+frr: rtn hgk
+bkp: lhc psr fsm
+bfr: hqh zjn srg rts
+hbk: dbt
+sxh: zbh mdm
+jzd: tgv
+mfc: ttr qck
+qdf: cgb kkm
+vgz: mtq plg tzj
+llg: ztn qjj
+nhl: tcl jcd nrx
+stl: dkj
+hdp: tbk nqd
+fsd: hkz fzq jln stn
+stc: qhm
+kkn: bsb zrj sxm tlt szc
+nhb: dkp str bjz csk
+grj: nbx fnc
+dts: bck szc hzs
+ksx: qvg zzv
+qqb: kzd grk
+qpl: mhs lcg lkp xfc
+ftj: ssc fzh tnk
+zmk: sfp btt
+vkx: ntx psr xpx
+gpz: vxj bdn
+rdz: nbp fpp
+zgf: tgd cjb fbn mrx
+xsj: vtp
+jbs: lhc pqb lgq zxp
+rpr: lzk
+vfb: vsb qlx
+lsf: vrm zzf mcp
+ldz: bqz fmn rkh
+bhk: mbk lhv pck cgb
+mdv: dbv gjm
+bkk: mvj kfs vsl xrj
+ftx: grj bdn
+gtr: pzz rbx knd xch
+xhc: dlx zfl
+txz: ggm ctf lvf cpm
+bcx: qxc bqv
+vkn: qpt rvd
+qjg: fps clk fnc
+qlx: frr
+tqb: shd bqs bxk vtz mqq
+mfp: svf rlb
+xgl: ldp mhj
+smp: vtp
+gds: mtz
+ndx: xrj
+hsg: jbp lxq npm xgm
+pvs: mnl vrm
+cpx: cqs
+ldf: qkb mgz
+tlc: rll tml cgn
+bdd: pvs dtl prd cnr
+khd: gvl rpr dbm mhq
+jts: tbk pjb qqr
+hpm: sbh
+ptk: ncf
+kgx: str
+hnp: kgm
+zmx: kmg lgq pfs qkv
+qvc: zjk nht jzc
+sdp: ktz
+hhr: hxd
+vtb: ghk str zlt
+vmh: dpl sps fdt lns jph lcr dln
+gcd: khc rvs cbx
+xbc: ndx hpm dcd
+bxc: vpt sqv fmb gfs
+mnp: hfv
+gtc: ssc cxb bxx
+fgb: gpn flb hbm cdf
+lzz: lpd
+lsb: tjz rmc ktz
+crh: vxj mqt qbv cgx xqv
+rrm: lmk
+sqd: smc
+tzd: nkr cdf mvx shl
+dzg: cgz qjt hpd
+tqq: jqn npm cgb
+mrp: rcm qrs zzf dcm
+hvx: dlr nrx
+cnq: qsn cxd
+ffl: hpv jmr cng
+gdv: jgm
+jvx: qbf qzm nfx
+vmj: pnh
+flb: zbx rvs
+qbx: kzb qbv
+sff: ndp mkd
+lxt: pps grk
+xmm: brx rnn
+bjh: vch djx gqb
+rtc: mrh slj kbh qbv
+gxq: ktz
+ztf: tbb hfv gdc vbr
+szr: ggt nfx
+xlb: vjh xrt qcz zmf
+vcn: hcf nsm tls tqp
+jlf: vdh kgm krm kgx
+nfh: hch
+khp: fpt fnj kvh hhf jtd pqs lzd jtm
+ncp: hmh zbx ctt cbm mls
+xsh: lxg ktx vqg shx njv
+fsn: rdq tzq hjz
+gsl: mgm gvd qmh clt mlj
+rgs: tnv hlm fnk
+rpm: lsr tml
+dxh: rzd crh lqr
+qsn: nlb
+ltc: bnb nxz xmm pcl
+rns: xch ppn
+bmb: gdj brh
+dnh: mls mqj
+xqt: jtg rpm pzz
+hmr: fjx rtn
+zgb: bxk xlq msr
+cvt: qzr nmt fqm
+qlh: ncf hlm vcc hdn
+glq: mfp hnp tqs
+bcn: zsz
+dxl: rbd
+hbn: nxz
+jxr: gjm qdv
+sfq: str xdg
+pjb: trr
+rtj: nlz fkr tvj
+xkm: fbn rqc kdc
+cft: lzk gvg
+qpz: gjm gvg
+jjp: qtv bpl kjm sbx kzb
+dgd: zlt jqn vdd kdz
+rlb: llg
+skm: tsx dlh pvg
+zhg: qmn lsr qdv
+mqm: hvx sbf kkn qsk
+hzf: rnb tsx
+xrc: qrq mfp hgb vfc hkp
+zgj: tdv pck zvk pqh hpm
+vqx: qjr vsb jpl
+hbp: mgz qrt fbx
+pqq: sdp vpj
+hhq: bjf vpv
+vfz: txk jkb mcs thl kss
+qdd: xkv khc nqx
+pgq: gqb hnh fbn vmk
+bcg: ccs
+fvd: dlx hsp gph jzg jqb
+gcv: gvp
+cnr: gfb dxh gxq qbx
+hbt: hch dbv pcl
+gqr: cch qnf nrx
+jcb: ksb jpl pck
+pfb: hsv jhs pqq kbf
+kmr: gvh mtp sxg
+jmr: bjb
+jzn: bhv gxx dbn djg
+pnj: vbv vdh xgh lzl
+qlr: dbt qbs lcv bbc
+zjk: jph
+tch: prs vbx rrm lzx
+xpx: dbr jnm
+mhs: jkp dhf ngb mfc
+clq: rrp
+ssd: nmn xlq ljq nrx
+gps: dxl pgk bjb gpr
+mlp: mnl hpq tdk rtv
+pzz: jtm
+pnr: vxj dnh rbc
+sqf: tmt czh
+xpb: tqq cxb lft pht
+zxf: pfr jjz mrb vfb
+gsq: rbx kkm
+vjt: hcg brd xhv
+tgc: shx nxh
+pjl: fpv grj bvm sll nfd
+kxj: ttg dpr dlx clb cbm
+scf: szz vtp
+vjc: zjm nbx
+blb: hxj dxr vgj
+ppn: kxb ntx dxr bmn
+pvd: mtx qfx lch
+qnk: vml
+pnd: tnv lrb jcl
+pht: hfv
+tzt: nxh dlv xlq
+hpx: jtd vxk bgm dqv dtz
+bnb: vpp tkc
+qxz: jdl gvh dbn
+sdz: xvp jsq dgh
+vcj: knd ptk
+dbl: ggc cjp bzb dpr
+ztl: tjz vjg spn
+nfl: skh tpf
+pcl: gvp
+zrs: gsm kct
+hmv: grj gkk
+xgf: vgd
+gcf: djn slj ftx
+lkd: htl xvj ktp qjg hnn
+dhm: dnz cbx
+jtm: rxf
+jmk: mbk slg prk smc
+xkr: ckn khh xgf gds
+rdg: hsp xcl hbp
+rnn: jcv lxc jcd
+qss: nfh kfh
+llz: tld
+kjm: djq
+tdd: pvq crh bsc
+kdp: hgb fsm zmr nbp
+brz: hbk hmt mhq
+djz: vsv slb
+npx: ztn
+zzq: hpd ktr ptl xhs
+kbf: vxn
+sxm: ktx slb
+vgr: xtp dnz hqp tvc
+lnp: qmb jdh
+lvf: zfq
+dhd: plm jkd cqs
+spk: mgr vrh nlq ngk
+nxd: txs mlj frs qdd kgk
+nnr: vcz cpx hsn rlb
+sfz: bhv mkd
+jph: hlm jtd
+ttv: zpp xsl hhf tgd
+zbk: xpx ctx qzr mct zzj
+dcm: pqq hcq
+dtn: zqg qsn qxp mtt
+jsh: tkc mrh
+pxc: lmk zjn kvz msb vsb
+fnl: rgr hqh
+ltm: cmd vdd hph
+mls: dbn dxl gvq
+tjp: krm
+hbl: vjc sdz tmc scf
+dpl: jtm bjh nlb nlz
+msr: mcp mtp
+brb: hxs kjj fnt cgg
+fbn: kzd
+zmr: vfc ksb kcz
+tdz: jhr rcm
+rmc: khh mbc
+trc: mhq szz
+clt: hbb qkt
+qnl: pjb tbb
+hzd: kpc dbr qrm
+fnd: sbh lpg vxk ddz
+nlv: hcq
+fgg: kpc
+lhr: ktb bpl jcv
+mbb: dhn
+hnj: xmc jbl ljb ldf rpc
+gjh: vrx xqv
+bjb: sll
+gnz: flm
+zqg: shr vcj jtm npx
+zqs: sgt xzm hpt pjc
+xcg: msr dgh fth xvp
+tnk: pdt mhr
+mnq: dvn qmr bfq
+jxh: szr vhx qtv gph
+qvg: jgm
+hpz: dlv tjz brd
+zvr: tcn trc dkj nqx
+prd: fgx gpn
+dln: pxx zxp
+tcp: hgk nqp jzb
+gvd: rcm
+xxx: ght zxv
+dxt: sdb
+xqv: plg
+hpd: bqs cch
+rqh: cmq cls rmf
+tbq: grs
+rgf: hfd qcn bbm csj bqz
+zjd: dmh vfc sgt
+dpz: pzt bcm qpn
+lch: flm
+hlt: gnt hsn dvd zcv qbn
+bgb: vbt jtm krm ndx
+bjz: pdt
+mjc: zfs
+srm: lvk bsk sqd
+bhx: ffr qnk jxz qdv
+kmd: qkv
+bts: clb kvf
+brx: hcq fgx
+dxj: dnz gdv xjc
+mvs: vjg
+fnj: lqc pxx jbf jzc
+bpr: hfp zfq jzg ldp vqh
+flm: ztv nqx
+hmz: hzn qbk ffg
+vhz: hgp pgk
+qjn: hpq
+ptl: plg xgz dbv
+ntx: tkt
+hdm: qdv fxm
+kbh: szz xtm vrm
+shn: ctx sfh lft
+gqp: hqh zst gsq
+kpf: tzr hzd dqz pqb bcg
+crb: qvq lhv npx jzc
+pcz: bkz czh
+nhc: jxr
+bdn: qbg
+dpk: zdb jlt lkm rdq qfm
+qmh: vtm csj nps
+phc: bxn fpv
+nhr: fpd jrm grj pnr vpq
+lzs: cch gnz fth jxr hlv
+qjh: bmn jtv clx jlg
+dnv: jbp bxx spr ftj tlc tjp
+jdl: bmb szt qnk sfz
+fmj: vkx tnk rdz cjs
+qvq: lgq
+pjp: gsq tkt fzq
+cvd: rlb kdp qck zvk
+bxp: dvn hmz gfs lpr mbz
+hxd: mbc
+mct: lxq nsd
+zvt: zql bqc
+mlx: tjz bsl rpc pvs
+gzf: htl vfk rpf nhc dmj
+jlr: ctl svf tvj bjf
+bsk: tvx
+hkp: cgn bfh vlh qnr
+btt: bhg zfs
+hqr: rts hnp nsd ghz
+vvq: mnr bck xpr
+qzk: stc bdn clk
+hfs: knd gbg tbg dcd msb mrb
+cgx: fgx gvt
+slj: flt stl
+lzx: kmd
+hcq: dkj
+fjx: qrq
+vsd: vgd qsk
+vbt: xdg
+fnc: dbt bxm
+djt: gds
+qgx: bxg mtp xvm zfq vlv
+lpg: dqq qpt
+zdv: ckl zjm
+hxf: ksx hzf
+zfl: qfd qbg
+tfc: qdd nfb
+jzl: jkp
+fxd: hxd xsj
+sfh: fxj
+cpm: hhr zrc djq rbc
+vgp: lrn
+qkl: stn gvn
+mrb: bgm dmg
+vzp: tvc lcv qtv jmr
+gph: fqv smp
+hgk: pck
+tsz: hfd jsn mrz hbn bpr bsb
+blr: tmz
+zpk: zzf zxq dxj fth
+vvt: znt gsk vbr
+hmk: jgb hfb mnl mlj
+fdt: gdd txj sjg
+hcs: jtg
+htq: sdp gvq pnr
+zvl: ghc fgg
+zmz: sxg
+vfl: rkm znf gcv mjh jxr
+lmg: nsr rmf jft xtc cfx
+gnn: tmc cbl
+mcs: hmt hpq tfc
+tms: cnq pql
+vrh: tdd bls bmz
+kvf: xpk
+vgj: hdp bgm
+qpb: nqb bqs lch
+pcn: plg cng
+tbh: tnv nmt
+bvg: xrp jcd mhb
+kvs: cgg gjc cmd xjl
+qtz: mvx hmt lzs ksx frs
+mqb: jnm mpm
+jft: qqp gpc
+mzt: vxk tqk trx ltt
+ghn: xhv mtx ksx mqt
+mmk: srp lzm
+ktb: rjx tcl jsn
+vjg: mgr
+pdc: vsb blb bfq
+znh: szr ksq vjc
+fpj: mct hzm tlc gsm
+hcx: vch cmd vpv
+mqq: sxg qbg
+rgd: kcz sxh ghk rns
+bsr: zvt xjr dsg
+nbx: kzk mhb
+kzx: plm fxj
+nrf: zxv fbn pxd
+krj: tcp lzz hpt gpv
+bzk: cxd qmb sgt zxp kzx jlm
+ggc: rbd
+kmv: csk snb bvr dtk
+lbl: vnl gjm ppg ccb
+kjv: hfb brx bxk
+fsf: rrp lmk ssc
+sbf: pgt vps vxj
+lmr: rnn ttg fhb jkz dbt
+hzn: gvn
+hqk: vrn ffl jhs djz
+bfb: vtm zsz ftb knq hpd
+hkk: rvd jcl
+kgc: mvs fmm cbx ftx
+gbh: jhr
+cpv: hxj hdp rgs pfs
+kvz: fzh vcc
+sjz: vpt ptn zjk kvj
+rrs: khc jxl
+vdr: lcv ldf hfc nlk bqc
+xxc: hfh qmz vpt tbk
+bgm: kmd
+gkk: kbd bxm ggt pvq
+csg: hhf lzm
+vrn: nhc bpl
+dzt: djt kjm bkd vxq
+zhc: zct rcm smp gcd
+pvq: bcb ccv
+hjt: dbg dzg sgj gdj
+vtz: clk
+jjt: nxj bcg lrn
+ggm: ftb
+srg: pnh zlt kdc
+ccn: hfd hbn
+tml: kkm
+rtn: srp
+mzf: spr fnl qms mrx
+rhp: pxd fpt
+hdn: pxx zrs
+qqp: nsd
+xdh: prs qrq cmq vmj
+mnn: zpd jts pgq jlt gfg
+mjh: hbm ckn vnl
+xrj: kcz qrm
+sgj: mhb hbb
+gdd: tvn
+bxz: mrv dlt
+kvl: jgm gjh lcp vgz
+nnz: bxc mgd txj
+qkg: fnl kgx qqr ncb
+pps: srp vbx qck qjr xxb
+zhb: mgr tpf
+lpq: zfq rnd qss
+jnm: vpt
+pzv: prk khn lzr jkp
+tcj: hvb fjx nvr clq
+pvg: bxz gvg fgq
+zcv: lrr kjj lzd
+psr: sps ltt
+bsl: dzn njt frb
+nvv: jdl vml qjn djn
+jrp: tqs flz szg qmz
+djx: trr dkp
+rtz: bqz lqr zbx hxf
+mgd: tbb
+hsn: vcc
+hlv: zzv vrs
+dsm: dbg ddv qhf
+vdd: tnv
+rfj: mhb
+qjj: nvr nbp tvn
+lln: pxx
+nqp: nmt
+mhj: dbn
+cbk: dkj tjq bnl gbv
+pgd: bcx vfx rzt cds vvt
+xmc: zxq rbk xjc
+fpn: knd dqz lns vbt
+bcj: fvn ztv
+dzn: txk qss qnf
+xrq: dvk szr kbf dnt
+lsr: hzn pht
+chx: rbd gnk szc
+pjr: qfm lpr sgt ght
+qmr: qfm
+rzd: llz vcg
+ttn: xhc brd zmz gpr dlv spn rdg
+gbv: qpz gpz
+szt: lqr gch vxq
+xvp: rrf cbl kgg
+lms: ckl
+rpj: zfl kfh ggt qtj
+xhs: zrj bmb lms
+lsk: zrd jxl bcn rbr dvm vvq
+xfl: lns
+bpd: xxk rgr
+hlg: sqv qqp kdq
+vqh: gdj
+hqs: nhp fxd ldz nlq rmc ssf
+hpv: gvd rpc
+lqz: tzj bsr tld kkl rrf
+btk: csg jrg mdd qmr
+bvd: zhd llh ftb ztl jxl dmj
+dzl: kch zxc cxd
+vcv: bqv
+lcl: qxc lxq nnz lkp
+dbv: jhx
+xcx: dkj mtp
+vjr: rfx vpp sxg mpv
+kvj: zqg fnd vfx bhg
+ggt: mdv
+qtj: brx gvh
+fxv: pxp sps dcc vdd
+jzc: tqs
+fqm: mct ncb zvl
+mxb: bxm rbc clk
+xcl: fll hxd fvn
+xgh: zxv qms mvj
+zlm: qxh vcv qjr qkv sxh
+trx: xgm nmt
+xmb: kmr xcx dsg gjh
+jmn: jsh xhc xgl
+frb: bxk rpc jmr
+mqj: trc
+lxk: kxb mqb
+crn: jzb jtg hhf gqp
+nnq: svf
+bmz: dbp tvc qns
+gvp: vtl
+cjb: zdb zbh hgg
+bhz: pgk hcf ntb
+hzj: lhq rfj jhx hfd xjr
+lbz: nbp
+jpk: bsb dhn
+nfn: qfx hmh gnz qjt
+vrx: nfl fps
+khn: nnq fsf vcj
+qxp: ztj kvz rxf
+zpd: xfl gtc
+dmh: lbz mgg
+cbh: lcv
+qlt: jzd qtj jzg
+hxj: ztn lbz
+vxn: nrx
+cls: zrs
+mcb: ccv nxh tdk
+bld: vjg hpv vmz nfb
+ggp: cjs qsn clq vmk jtm
+shx: mqj
+pqx: xgf
+bpn: vgp xvv pqb qzr
+skq: xrd lhv rzt
+hnh: klr jzl
+dkp: bhq
+jkz: djg sbx
+kzb: mls
+zqx: pfp cbh jhx
+kkl: stl gvt
+jsq: skm vrx ffl
+csk: qnl gtr
+xtq: hhq qkl pxp
+dvk: sff pgk grj
+jgb: hgp gvp nfh
+npm: hhk xzt
+lxg: mrh jmr dxl
+vsr: hcg mhj blr
+ppp: dnt pcn hdm bsl
+ktn: vnl jzd fnc
+mrz: kjm tpp
+zrv: dsg bhc rrs tbc
+zhd: lzk
+kfh: hmt
+jpt: hrb kjv ntb hlv gzq
+fhz: hnp hhk cls vmk mtt
+bqb: cnq zpd rgb sqd fcc
+fnv: zbh
+xdg: llg
+qvs: ttg dlh lhr ftb
+vts: mrv xhv tmt
+thk: lms mtz
+rxs: jzd bqs qdc gnn rpr gdv
+vvh: vgr fgx hmv vgq
+zlt: qpn qms vkn
+mtj: lcr rgb dhf tvx
+tvj: qqp ght
+xbv: hjz qnr rgr
+vxr: xjr gnk zqx zjm
+kgk: hbn vxn zzf fll
+pql: tvn vfx
+gvj: cvt shr ctl qjj
+vpd: vrm nqb mxb mfs zmb mrh djz
+jpc: pjp tzq nnq qms
+zmf: xxb sdb
+qhn: sqf gch mnr vgd
+vpq: bts blr dts
+lmk: kfs
+gvl: kvf
+nps: nnj ftc
+rsr: shd tvc hnn
+vrf: spr cfx sfp pnh
+jqb: xcm hkg zql
+pjv: tcn knv mvs
+qmz: zxc
+srb: hfh vsl pfs qkv qjr zlt
+gqb: jzl
+kcf: qss mhq fxd mlz nfx
+dzh: cng kss qmh
+kgm: bsk
+lpn: fhb kzq mqq vjt
+mcp: rrf shd
+mzm: fcp lgq xxk kzd
+lrr: flz qxc
+cbl: pqx djq vsv
+cnt: nqp jkd nlx
+lxc: gbv zsp rbk fmm
+kct: bfq
+npp: hbk pgt zdv stl mcb
+zst: vpv rvd dqq
+xpn: ckl fll
+cgg: snb vbt vbv
+fxq: bzk crb txj kcz nnq
+dxc: dzn dhn xvj fgq nhc
+lft: jzb gbj vch lzm
+lkp: xxk jtk lzd
+ctj: khj fqv ftc dlv
+lqc: rtn gbg vsl
+pxp: mqb
+bnr: djn qdc tbq mkd
+mkp: htq klj jkb
+vxc: mjc hzn tml kvh
+kcj: cxb pxp vjx
+sgm: qvc lzz
+mdq: skq hhq qxh xtc
+bxg: bxn qkb
+rvr: qlz xgf
+vfc: npx gfg
+jgq: spb hcf mbb
+mqv: grj
+sps: tqk xch
+fjn: xtp
+vqg: jst fgq
+sxj: kpj fpv ccb mqt qkt
+nnj: hdm mqj lsf
+xfc: rpm xtc bjf rrm
+xjj: bxz mgz ksq djn stl
+jjz: qhv
+jdj: klr xrt xrd
+pjn: qlz shx nkr sff
+tgd: vbr qpv mhr dtk dmh
+jln: fgg tzr vcv blp
+mpv: fqv hkg fpv
+ljb: hmh gcv zct
+gpv: bhq tdv vkn
+bvs: gkk cft brh dlh
+rjq: skm frb frh rsp
+png: qvc vzc lcr
+psb: sbk hgp bcj
+btx: kfh smb fmp qhm
+lns: mgd
+kzq: vtz bqc
+crp: sbk tpf gvp jgq
+lhq: bxn tdk kgk
+spb: bck fjn
diff --git a/day25/uppga.c b/day25/uppga.c
@@ -0,0 +1,94 @@
+#include "common.h"
+
+#define ASIZE 26
+
+static inline size_t idx(char *s) {
+ size_t a = (size_t)(s[0] - 'a');
+ size_t b = (size_t)(s[1] - 'a');
+ size_t c = (size_t)(s[2] - 'a');
+
+ return (a * ASIZE * ASIZE) + (b * ASIZE) + c;
+}
+
+static void graph_setup(graph_t *g, char **lines, size_t nlines) {
+ char *cp;
+ size_t c = 0;
+ size_t i;
+ size_t dict[ASIZE * ASIZE * ASIZE];
+ for (i = 0; i < ASIZE * ASIZE * ASIZE; i++)
+ dict[i] = SIZE_MAX;
+
+ for (i = 0; i < nlines; i++) {
+ cp = lines[i];
+ while (*cp != '\0' && *cp != '\n') {
+ if ('a' <= *cp && *cp <= 'z') {
+ if (dict[idx(cp)] == UINT64_MAX) {
+ dict[idx(cp)] = c;
+ c++;
+ }
+ cp += 3;
+ } else {
+ cp++;
+ }
+ }
+ }
+
+ graph_init(g, c);
+
+ size_t cnode;
+ for (i = 0; i < nlines; i++) {
+ cp = lines[i];
+ cnode = idx(cp);
+ cp += 4;
+ while (*cp != '\0' && *cp != '\n') {
+ if ('a' <= *cp && *cp <= 'z') {
+ graph_add_edge(g, dict[cnode], dict[idx(cp)]);
+ cp += 3;
+ } else {
+ cp++;
+ }
+ }
+ }
+}
+
+static uint64_t partition_wrapper(graph_t *g) {
+ size_t i, j;
+ igraph_t h;
+ igraph_vector_int_t partition, partition2, cut;
+ igraph_real_t value;
+
+ igraph_empty(&h, g->n, IGRAPH_UNDIRECTED);
+
+ for (i = 0; i < g->n; i++) {
+ for (j = 0; j < (g->nbrs[i]).nmemb; j++) {
+ igraph_add_edge(&h, i, (g->nbrs[i]).data[j]);
+ }
+ }
+
+ igraph_vector_int_init(&partition, 0);
+ igraph_vector_int_init(&partition2, 0);
+ igraph_vector_int_init(&cut, 0);
+
+ igraph_mincut(&h, &value, &partition, &partition2, &cut, NULL);
+
+ size_t p1s = igraph_vector_int_size(&partition);
+ size_t p2s = igraph_vector_int_size(&partition2);
+
+ igraph_vector_int_destroy(&cut);
+ igraph_vector_int_destroy(&partition2);
+ igraph_vector_int_destroy(&partition);
+ igraph_destroy(&h);
+
+ return p1s * p2s;
+}
+
+int main(int argc, char **argv) {
+ char **lines;
+ size_t nlines = readlines(&lines, "input");
+
+ graph_t g;
+ graph_setup(&g, lines, nlines);
+
+ uint64_t prod = partition_wrapper(&g);
+ printf("%llu\n", prod);
+}
diff --git a/day3/Makefile b/day3/Makefile
@@ -0,0 +1,30 @@
+CC=clang
+CFLAGS+=-std=c99 -pedantic -Wall -Werror -Wstrict-prototypes
+CFLAGS+=-Wmissing-prototypes -Wmissing-declarations -Wshadow
+CFLAGS+=-Wpointer-arith -Wcast-qual -Wsign-compare
+CFLAGS+=-O2 -g
+CFLAGS+=-fstack-protector-all -Wtype-limits -fno-common
+CFLAGS+=-fno-builtin
+CFLAGS+=-I/usr/local/include
+CFLAGS+=-I../utils
+#LDFLAGS=
+
+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) $(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)
+
+utils:
+ make -C ../utils
+
+clean:
+ rm -rf common.o uppga uppgb
diff --git a/day3/common.c b/day3/common.c
@@ -0,0 +1,59 @@
+#include "common.h"
+
+void nbrs(coordinate_t *res, const size_t i, const size_t j, const size_t nrows,
+ const size_t ncols) {
+ size_t idx = 0;
+ if (i > 0) {
+ if (j > 0) {
+ res[idx].y = i - 1;
+ res[idx].x = j - 1;
+ idx++;
+ }
+
+ res[idx].y = i - 1;
+ res[idx].x = j;
+ idx++;
+
+ if (j < ncols - 1) {
+ res[idx].y = i - 1;
+ res[idx].x = j + 1;
+ idx++;
+ }
+ }
+
+ if (j > 0) {
+ if (i < nrows - 1) {
+ res[idx].y = i + 1;
+ res[idx].x = j - 1;
+ idx++;
+ }
+
+ res[idx].y = i;
+ res[idx].x = j - 1;
+ idx++;
+ }
+
+ if (i < nrows - 1) {
+ if (j < ncols - 1) {
+ res[idx].y = i + 1;
+ res[idx].x = j + 1;
+ idx++;
+ }
+
+ res[idx].y = i + 1;
+ res[idx].x = j;
+ idx++;
+ }
+
+ if (j < ncols - 1) {
+ res[idx].y = i;
+ res[idx].x = j + 1;
+ idx++;
+ }
+
+ while (idx < 9) {
+ res[idx].x = SIZE_MAX;
+ res[idx].y = SIZE_MAX;
+ idx++;
+ }
+}
diff --git a/day3/common.h b/day3/common.h
@@ -0,0 +1,20 @@
+#ifndef COMMON_H_
+#define COMMON_H_
+
+#include <assert.h>
+#include <reading.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+typedef struct {
+ size_t x;
+ size_t y;
+} coordinate_t;
+
+#define is_defined(c) (c.x != SIZE_MAX)
+
+void nbrs(coordinate_t *res, const size_t i, const size_t j, const size_t nrows,
+ const size_t ncols);
+
+#endif
diff --git a/day3/exinput b/day3/exinput
@@ -0,0 +1,10 @@
+467..114..
+...*......
+..35..633.
+......#...
+617*......
+.....+.58.
+..592.....
+......755.
+...$.*....
+.664.598..
diff --git a/day3/input b/day3/input
@@ -0,0 +1,140 @@
+........................................................862...........20.............453...619......58........694...312.................292.
+...846................132.49........308..........................=............50.....*..............*........+.....+...............59.......
+........../46....140.......*............735......852&..706.....860...............297.459..........998................661..418.883.......+...
+....*...............*....727......613..#.....517..........-........*..............*.......................888.......*......*...*.........982
+.828.865....395......163......................*......381............312....34...533..............................291.....440.488..370.......
+.................+............122.....598*....400....+......................+.=.......451........746*...............................*.......
+......864......279........203....*731.....335.....41....23..365.&.......659...817.......*.............89.931......672....661*92....72.......
+943.....%..................*....................../..............455.....*...........155................*............*......................
+........................966.......823.................%702..881........874...494..........................364+..$.......#587....&....157....
+.......701.621......................%........%....93...........*................*.........*.&273.................497............814.........
+.........*..+............201.863-.........113...-.+...*363....900.............111......586.......289........898.......306....*..............
+...*...894.....&...754...*........#803........609...80...............52....................246..=.............#....../....118..........633..
+...321.......642...*...764...644/......980..............$726.........*...306........787...*...................................550...........
+.......666........902..............946*..........230...........45.245.......%...481*.......203......433......+.........294...%..............
+..........*862..........261...184..........744...*...................................................*........782........&...........984....
+....992*........678&.....$.....*..................229......60..........239.........*437...*...681....809......................541#...&......
+........812.................704........+......*.......33.......434....*...................840...*..................@300...../...........257.
+.37..................-.17.......26..793.....71.486...............*..240........261.............605........*..............953................
+...............65.724....*..6....*......446.........#854.318...86................*........+922.........546.762.......................137....
+........279....*........382...925............*323........................364.....616.&.........................597.......-419..985*...*.....
+..........@.370....................735+...597......@....*966.........................699.874/............446...%............................
+..................798.........%..................711.........905........*694.........................700*............................492....
+......706............+...%....536.$417................913$......@.....39.......+.......................................-................*...
+......*........77.......975..................876..........................-954..443.804....&......36*..............51.369..247..........244.
+..787.639......../.................$........./.........49..482.........*............/......952.......365....$.......*......*................
+....................................377....$.......603*...........&.....540.......$......................369..215.276.....397.856......-....
+...........&.........959...81............370..958..............768..............41..853......................*..................*.473..737..
+...802$...560...........*...*....................*......286................/596.....#............+..........490...............411...........
+..............817.791...101..727.....404.689....606.......*.718.+...233...........=.......59..202..&...............61..................420..
+.....+..730...%.........................*............328@.......90....*..........460......-.......155........913..*...881...................
+....928.............285....142......../............................819......755..........................609*.....927.*.....................
+..........408..816...*......*.........539..850..21.....&...699.............+......#....952..&844.....88................952..................
+......................409...539..674.............=.....337...*....59...........+..698./..............*.....67....930.....................185
+......775/....726+.................+..259...141*............471...%..........172.....................185.....*.............670...411....*...
+...............................=.......*........246.................447....................554...951........201...723...67.#....*......914..
+....................482...../...777.78.507..................$..................918............%...@.../..........&...........688............
+.457............40..*....564........$..................29...199..%537.............*....................489.....*........730.................
+.......220..239....16........269..........220....#782......................592....857.......................435.343.....%...............913.
+.............*.................$...487....$..............183=.........481...-..........118..........419....................286......163.*...
+.........../..752.....................*...............#...........933....*.........10.....*........*......................*....735..*....315
+.........958.........934.............882............51....512....*....769....$.......$...533.....264............$...6....720.........550....
+..408...........366...$......................132.........=.....794........615...........................297...60....*.......................
+....$.........6...*........&.....292.....&.................%..........106........889.......@..............@.........468.......$...239.......
+.......314.........831.130..48......+.655.....757..976......594...924*......932....*....99..759.2.............750.*..........236.....*251...
+..451....*................*......................*....*..........................274....*.................868*.....939......................
+....*..477....580..........739...743..346..802#...91...531......739*661..................925..........#................894.55...995.........
+.178.........@..........90........*.....*....................................139.....855.............583..#....377........*....../..........
+........588.............*...65...261....28..10.............22....697+.812.....*.........&..141.............342.*....710.....................
+.......*..............255......*............*.....@155..................@..254......#........*.................516................777.......
+......876......364..............453.......745...................216..............187...&..686..............782............936...............
+...........579....*...#.......................736................*...@..................9.........797..809....*...........=.....983.....*448
+............../.700.152....587..........444...&...375%.744#....21.....140.......=.........576........*..*.....420..............*.....399....
+........822...............*............./...................#.....377........657....$.856..*...811.658............111..+.....718............
+...689...*..............764....................758..........40...*................632.*...574.....................*...850.........626.......
+........112.......................833.........*.......&........456.345..707.....*.....35......96..*.............891.......@218.....#........
+................714............................850.....131.................@.334.776.....896..*....878.....729.......846...............641..
+............121*.....736....737......742.....&..............429.125..104................*......397................................389.......
+....................*.........*...............441....$......*...*...@....841*363...*...103.............*......#.....820....306...$..........
+.......772..........851.......580...................750...601....38...............715......./........54.832....226..-.......*............861
+.282/....*......264.....-.................63*...........................655...223..........360...........................887................
+........130......*....208....................2......976.............241...............969......588...........942.....................542....
+............782...208.....+....255........................918...476*......606*464....*.....447....=......674......979........+..............
+..............*...........979..........@..........@..........%.....................302........*...../...*..........@.......642........937...
+.....200...837....=..109.......525..476...../..564.......#......571..........129........295..623...647...825..........*385......-.....*.....
+.....*..........275.#....354....+........492............2...............303............+...........................991.......290...830......
+...246....912......................-.........104..940......440*931.595=../..........$.........741*......977....272......778*...../..........
+.........+.........@.......507.....803.........*...-.........................559*....328..........966.............%.........516..494.=......
+....*842..........464.........*........%750...338........253....386=..656........529......662............/..........757...............868...
+.258........................843...................413...*.............*.....513......359.%........588*16.359.........@.........#...%........
+..........498.......$..555......@....................*.....*10.....145........%........+......*.............................136.....980.....
+.....681......625.147.....*.....588..82%.397........376.677....633.........................523...607.372................................855.
+.....*.......*........439..311..............*.....................-.96.......938*815.839...........-.$....................%.........286.....
+...830........115......*.......908.........351...850....290..959/...*...................*.....*453................392......750.........*954.
+.....................-.627.......................+..................120............50.900..........818.....668......*.............848.......
+.....979*.....603.863......250.......*507.*751......411..../350...........@......../.........702...*...292..*........615...........*........
+...........................#......676...........140....*..................800.........$..895....#..93..*....51..295.........=....59.........
+...............594.801.84................335.....*..521...883.......=33.......801....917....&..........667.....*.........893..........485...
+........................+......................55........*....................-................#................895..................*......
+.........315.574..168...............................%.215.....123...........................966.........+...........774...526......11.......
+...........*...*...-........533...&766...........709............$....931....624......275.............@..189......$....*......#..........=836
+..........342..551.........+...........178..621...........561..................&.....*..............214.......207...822.....................
+.................................63...+......=......615..*.............499*825....167...................870.....................265.891.....
+......................758..........%.....+................953......&...................727/.....273............413...............=.....*818.
+....275..........81.....*.447.506/...67..242............+.........793...531*885...18...............*710........*...#....906.................
+.......-..645.....-.........*......#.........98*520.565..958.....................*............88..............66..911.............44*.......
+.........%.................455...@..298.......................=....510......-...366..162......*..........306.............354.........153....
+..................@....53......689...........#.....690.......318..*.........701............156....%519..*....386..917..........#............
+......718..754....606...............164.....28.303....*...........921..............342.558..................*......$..67.......682..........
+..............*.........586.....541*...........#.....756..931.....................*.......*.....92.......826..........-.....................
+662...........775.........*................../.............*...................419........510..$....................*........-822......-....
+...*..........................690.398....98...9...999....617............681.........360.............&......*508..594.437..............385...
+..647...709...............71....*...*.............$......................*..........*...539*864......826..................@.................
+.......$......529...........$.260..672.538+........................996.560.........639....................867.......922....891........695...
+..........$..*................................376..............922*............................875...........*.......*...........%....*.....
+....331.542..........932..409$..........815..*......................888.322..............205.....=.940..2#.......................411.635....
+....................*..........698*119.......65.511................*....+....-......34......=........*......$..574...971.85.*630............
+...104.311.....561#..556...........................*514.............663.....416.......................243.728.....&.....*...................
+...........521...........*131...979....227..556...........499....-..............895...42.........%..............=.........../............898
+............*..........*........../...*.....*........=....*.......614.....498..*......*...........612.205...138.664........190..............
+.........834...348..887.730...........475.404.....474..168..620.............$..175...549...............*.....*...................11..459....
+.....320........-................401..........261....................................................267......676..=629....-487.............
+......./..%142...............................*....................551................-......961.751.........&......................360......
+.............................41&.504......416.............144........+..........&.....438.......*...385....635.330................*.........
+....544.369..349..&.....=479..........995......566.80......*....595-....=..468..507............301..&.............*619...383.....498........
+.......*......*....950................*..........*..=....484.........258...-..............926..............=................*...............
+...............224..............*394...81.....904..............................*.........*................537......521...882...231.....*837.
+.......370...........625.....116................../11.866..288.........311.....375.708..67...*......380........170../...........&...........
+...600*..........811..*....=...........287................................*211......=.......987....*.......448......................-....92.
+............408.....+.405...17....32...+.................180...81................*.....*.........315......*..........-..............148.....
+.......*401...-....................&.....713.67......475*......*....707.852*...830..484.77.............902........505..=273.................
+..837...........................33........*...............492/.80...&......................203...686..........722...............178.........
+...*......191.791..........433....$....342..................................689........988..*....#.........@.....#.923*622......*...........
+.850.679.%....*.......376.-.....................308.812...742.........-.148....@.........$.663.........818..177..................839...388..
+......./...269...496...*........-....274*............*.....*........791..*........@....%.......*190.............*..241....127.........*.....
+.74.................*........912.........435..107..790...640...200......578.112..83....252..269...........970.823.....................875...
+...%..787.........515.305..........274.&.........*............*.......................................261...*..............+........&.......
+...........136.-........*.564.......*..635.....26../....438.469.................@............193.......*.....55.....244#...185..258.287.....
+............*...556...............245......855....928....*.................*61.370..74......-.........488...................................
+.....970....315...........999.65..........=...........928.....164.......431.........*...........370.....................#...909...468...471.
+.961..@..................%......../350.............*................746.............38....261......*.......301...278..750.....*......*.*....
+....*.................7.....................%...860.900....300.........*410..............*.........209.+98..*...............801....313.491..
+...845......%160.......=......=.....*......313.............*............................547...986............139.331../401..................
+........513........362...540..913..655.510..............483......@...#..670..651..433/...........*264.....43.....*............176...........
+211.892....*..253.....%...*...............*.....................645..16..................116...............%...309......*569....*.......+...
+.........402....*.83$...884......618.......465.............989..........................=....505..%..................101......974....871....
+...4..........565...................*....&.......297&.......*...........@....179..637...........*.199...924...-..713........&.....@.........
+...................@.367&.#308.....752...997.23...........396..........883....&..............306...........*.148../.........76.979...382-...
+.................677..........................*..933..................................637...............659...........678...................
+.....*...............445..........952...837.....*............755........795.....#.....=.....178*731..............855.....=..................
+......173.15.417......./.....180....*....*....328...607.........*.392...-.....495.546...............183...&.....-..................224......
+..........*.....*.............*......16...65.................772...*..............+........937...........981......92.....+.....164......833.
+.116.....149.225....*....287....................136..............240..242.749.............*....688.................=......49...-.......*....
+...&.............202.985..-...732*812.......................-../.....=......-.798.......533........468...30%.........................228....
+.........94...................................+798..&.....431...425............................929*............+............................
+.........*.......................704...982...........332.................447............307%................704...775%.......$973...90..424.
+..........711..253.....#...........*......*119..............486........#...........89...........438..666...............487..........*.......
+.....947..........*.....823..544....883............291.....@..........813............*.425..659*..........28..491.....+..........896........
+.............../...943......................590...*....145....414*969..............896....*.........622.........*.938.........=.............
+....@...#184.935.............................*.....71......$................84*.........825.....637...*.......528...*......990..............
+..745...............534..............58....901...........974...................637.....................87..........361......................
diff --git a/day3/uppga.c b/day3/uppga.c
@@ -0,0 +1,54 @@
+#include "common.h"
+
+static inline int is_digit(char x) { return '0' <= x && x <= '9'; }
+
+static inline int is_symbol(char x) { return x != '.' && !is_digit(x); }
+
+static int has_adjacent_symbol(char **lines, const size_t i, const size_t j,
+ const size_t nrows, const size_t ncols) {
+ coordinate_t n[9];
+ nbrs(n, i, j, nrows, ncols);
+
+ size_t nbr_i = 0;
+ while (is_defined(n[nbr_i])) {
+ if (is_symbol(lines[n[nbr_i].y][n[nbr_i].x]))
+ return 1;
+ nbr_i++;
+ }
+
+ return 0;
+}
+
+int main(int argc, char **argv) {
+ char **lines;
+ size_t nlines = readlines(&lines, "input");
+ size_t cols = strlen(lines[0]) - 1;
+
+ uint64_t sum = 0;
+ size_t i, j;
+ int in_number = 0;
+ uint64_t cnum = 0;
+ int symbolic = 0;
+ for (i = 0; i < nlines; i++) {
+ for (j = 0; j < cols; j++) {
+ if (is_digit(lines[i][j])) {
+ in_number = 1;
+ if (has_adjacent_symbol(lines, i, j, nlines, cols)) {
+ symbolic = 1;
+ }
+ cnum = cnum * 10 + ((int)(lines[i][j] - '0'));
+ } else {
+ if (in_number) {
+ if (symbolic) {
+ sum += cnum;
+ }
+ in_number = 0;
+ cnum = 0;
+ symbolic = 0;
+ }
+ }
+ }
+ }
+
+ printf("%llu\n", sum);
+}
diff --git a/day3/uppgb.c b/day3/uppgb.c
@@ -0,0 +1,104 @@
+#include "common.h"
+
+typedef struct {
+ size_t identifier;
+ uint64_t value;
+} adj_t;
+
+static inline int is_digit(char x) { return '0' <= x && x <= '9'; }
+
+static inline int update_adjacents(adj_t *adjs, const adj_t x) {
+ if (x.identifier) {
+ if (adjs[0].identifier == 0) {
+ adjs[0] = x;
+ } else if (adjs[0].identifier != x.identifier) {
+ if (adjs[1].identifier != 0) {
+ if (adjs[1].identifier != x.identifier) {
+ return 0; // more than 2
+ }
+ } else {
+ adjs[1] = x;
+ }
+ }
+ }
+
+ return 1;
+}
+
+static uint64_t gear_ratio(char **lines, const size_t i, const size_t j,
+ const size_t nrows, const size_t ncols,
+ adj_t *table) {
+ if (lines[i][j] != '*')
+ return 0;
+
+ adj_t adjs[2];
+ adjs[0].identifier = 0;
+ adjs[1].identifier = 0;
+
+ coordinate_t ns[9];
+ nbrs(ns, i, j, nrows, ncols);
+
+ size_t k = 0;
+ while (is_defined(ns[k])) {
+ if (!update_adjacents(adjs, table[ns[k].y * ncols + ns[k].x]))
+ return 0;
+ k++;
+ }
+
+ if (adjs[1].identifier != 0) {
+ return adjs[0].value * adjs[1].value;
+ }
+
+ return 0;
+}
+
+static inline void make_tables(adj_t *table, char **lines, const size_t nrows,
+ const size_t ncols) {
+ size_t count = 1;
+ uint64_t nnum = 0;
+ int innum = 0;
+ size_t i, j;
+ for (i = 0; i < nrows; i++) {
+ for (j = 0; j < ncols; j++) {
+ if (is_digit(lines[i][j])) {
+ if (nnum == 0) {
+ nnum = strtoull(&lines[i][j], NULL, 10);
+ }
+ table[i * ncols + j].value = nnum;
+ table[i * ncols + j].identifier = count;
+ innum = 1;
+ } else if (innum) {
+ count++;
+ innum = 0;
+ table[i * ncols + j].value = 0;
+ table[i * ncols + j].identifier = 0;
+ nnum = 0;
+ } else {
+ table[i * ncols + j].value = 0;
+ table[i * ncols + j].identifier = 0;
+ }
+ }
+ }
+}
+
+int main(int argc, char **argv) {
+ char **lines;
+ size_t nrows = readlines(&lines, "input");
+ size_t ncols = strlen(lines[0]) - 1;
+
+ adj_t table[nrows * ncols];
+ make_tables(table, lines, nrows, ncols);
+
+ size_t i, j;
+ uint64_t ratsum = 0;
+ for (i = 0; i < nrows; i++) {
+ for (j = 0; j < ncols; j++) {
+ uint64_t rat = gear_ratio(lines, i, j, nrows, ncols, table);
+ if (rat > 0) {
+ ratsum += rat;
+ }
+ }
+ }
+
+ printf("%llu\n", ratsum);
+}
diff --git a/day4/Makefile b/day4/Makefile
@@ -0,0 +1,30 @@
+CC=clang
+CFLAGS+=-std=c99 -pedantic -Wall -Werror -Wstrict-prototypes
+CFLAGS+=-Wmissing-prototypes -Wmissing-declarations -Wshadow
+CFLAGS+=-Wpointer-arith -Wcast-qual -Wsign-compare
+CFLAGS+=-O2 -g
+CFLAGS+=-fstack-protector-all -Wtype-limits -fno-common
+CFLAGS+=-fno-builtin
+CFLAGS+=-I/usr/local/include
+CFLAGS+=-I../utils
+#LDFLAGS=
+
+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) $(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)
+
+utils:
+ make -C ../utils
+
+clean:
+ rm -rf common.o uppga uppgb
diff --git a/day4/common.c b/day4/common.c
@@ -0,0 +1,29 @@
+#include "common.h"
+
+void parse_sets(smallset *ls, smallset *rs, char **lines, size_t nlines) {
+ size_t i;
+ char *cc;
+ uint64_t v;
+
+ for (i = 0; i < nlines; i++) {
+ cc = lines[i];
+
+ // until data
+ while (*cc != ':') {
+ cc++;
+ }
+
+ smallset_init(&ls[i], 128);
+ smallset_init(&rs[i], 128);
+
+ while ((cc = sread_next_u64(&v, cc)) != NULL) {
+ smallset_insert(&ls[i], v);
+ if (cc[1] == '|')
+ break;
+ }
+
+ while ((cc = sread_next_u64(&v, cc)) != NULL) {
+ smallset_insert(&rs[i], v);
+ }
+ }
+}
diff --git a/day4/common.h b/day4/common.h
@@ -0,0 +1,15 @@
+#ifndef COMMON_H_
+#define COMMON_H_
+
+#include <assert.h>
+#include <reading.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <reading.h>
+#include <smallset.h>
+
+void parse_sets(smallset *ls, smallset *rs, char **lines, size_t nlines);
+
+#endif
diff --git a/day4/exinput b/day4/exinput
@@ -0,0 +1,6 @@
+Card 1: 41 48 83 86 17 | 83 86 6 31 17 9 48 53
+Card 2: 13 32 20 16 61 | 61 30 68 82 17 32 24 19
+Card 3: 1 21 53 59 44 | 69 82 63 72 16 21 14 1
+Card 4: 41 92 73 84 69 | 59 84 76 51 58 5 54 83
+Card 5: 87 83 26 28 32 | 88 30 70 12 93 22 82 36
+Card 6: 31 18 13 56 72 | 74 77 10 23 35 67 36 11
diff --git a/day4/input b/day4/input
@@ -0,0 +1,202 @@
+Card 1: 74 8 2 86 40 25 93 17 61 32 | 65 25 73 55 75 94 54 99 53 17 89 4 44 13 15 32 57 92 8 21 74 64 5 87 24
+Card 2: 8 18 79 59 71 84 72 23 96 74 | 22 83 74 78 72 30 8 59 6 23 7 71 31 84 18 96 21 36 51 67 80 79 60 28 42
+Card 3: 63 27 56 19 85 86 40 78 67 54 | 34 32 79 64 35 46 61 31 24 41 33 44 10 56 49 36 4 82 98 54 23 21 63 86 51
+Card 4: 2 95 87 25 13 12 9 24 68 29 | 84 54 49 78 52 60 34 25 97 26 55 39 66 79 23 94 29 67 12 51 9 16 19 76 8
+Card 5: 70 92 50 61 43 16 53 71 91 7 | 17 70 62 84 82 9 14 16 56 15 63 91 77 57 58 60 96 35 88 26 51 54 59 74 80
+Card 6: 34 86 44 60 10 4 89 5 94 92 | 60 95 35 2 86 32 94 79 82 64 4 5 92 89 44 69 34 21 76 72 9 6 52 48 61
+Card 7: 99 36 57 20 46 38 26 58 72 11 | 99 70 20 58 38 67 76 36 84 27 94 11 26 35 46 21 81 31 72 62 13 10 57 54 4
+Card 8: 19 95 24 99 44 36 58 26 31 6 | 69 10 43 42 70 64 92 40 38 47 21 98 41 49 20 71 65 59 91 72 34 74 84 29 22
+Card 9: 87 77 90 73 7 27 48 1 13 55 | 96 28 40 62 19 3 25 47 80 85 68 94 82 50 12 65 84 75 83 41 91 89 55 42 48
+Card 10: 6 89 13 82 16 54 27 67 19 76 | 65 67 94 58 97 61 54 80 53 6 73 41 95 7 83 2 23 11 63 24 78 29 13 16 82
+Card 11: 27 50 4 17 31 70 18 75 91 20 | 71 85 67 80 92 6 31 48 15 70 51 7 78 34 8 72 16 62 4 52 75 39 2 82 74
+Card 12: 27 68 79 78 21 56 53 29 2 74 | 96 69 59 49 20 42 23 71 54 72 25 7 55 19 64 37 62 41 10 66 26 75 93 18 84
+Card 13: 1 75 85 51 47 45 93 11 57 80 | 97 66 4 61 42 36 12 83 86 51 99 90 52 82 30 33 20 56 44 59 18 24 28 40 41
+Card 14: 24 28 85 42 5 3 33 76 98 75 | 31 95 54 8 90 10 6 85 75 44 94 40 62 47 83 26 9 27 68 63 88 80 82 55 93
+Card 15: 52 28 90 27 6 37 44 3 51 39 | 65 44 64 85 47 20 86 83 38 49 80 21 56 30 89 69 84 93 1 48 88 76 36 77 97
+Card 16: 28 7 3 39 71 85 84 13 44 31 | 93 79 33 21 4 18 63 23 68 49 57 9 22 54 27 69 75 29 30 78 37 98 91 38 94
+Card 17: 97 20 84 50 98 82 45 22 33 60 | 53 10 68 92 43 76 99 52 38 96 31 4 25 15 11 42 69 56 62 23 29 74 51 39 40
+Card 18: 28 66 82 85 94 35 72 29 63 68 | 73 86 63 60 20 10 64 89 66 61 90 35 72 8 85 28 29 1 88 49 76 36 82 94 68
+Card 19: 58 41 33 29 38 60 3 73 10 13 | 52 73 20 51 47 75 74 26 69 18 70 24 62 53 91 85 63 1 76 5 42 43 97 10 84
+Card 20: 46 8 66 7 27 4 9 78 24 18 | 13 14 57 92 6 59 3 81 70 10 4 51 98 23 66 64 74 49 83 27 24 73 95 35 7
+Card 21: 15 32 12 47 53 89 24 58 59 18 | 47 82 1 53 58 93 44 19 12 96 13 61 15 72 75 83 65 41 54 49 71 78 68 59 79
+Card 22: 92 27 79 68 46 97 2 96 94 80 | 18 81 12 13 39 93 83 38 52 46 89 17 24 58 49 74 10 8 57 65 35 19 54 41 11
+Card 23: 92 72 68 65 54 18 34 62 41 82 | 96 32 74 10 12 8 34 55 54 83 91 22 47 68 52 21 41 65 72 97 30 70 46 18 9
+Card 24: 49 76 13 10 59 33 86 29 95 32 | 16 60 38 33 68 51 15 50 95 61 29 93 76 6 31 71 10 25 13 40 49 77 2 32 23
+Card 25: 38 66 33 7 77 73 44 50 25 76 | 20 12 63 92 61 5 88 37 75 21 41 47 73 77 13 76 31 80 60 34 93 90 54 3 45
+Card 26: 77 45 81 84 53 80 76 22 75 61 | 25 58 38 45 98 10 6 92 70 82 24 22 4 68 97 72 14 49 17 83 27 53 77 89 75
+Card 27: 60 16 79 54 85 56 92 41 26 44 | 63 44 69 60 96 7 36 2 37 5 41 73 6 51 64 56 53 76 57 99 21 30 67 85 66
+Card 28: 41 84 40 62 67 89 29 7 2 8 | 35 9 24 29 20 33 6 98 50 95 10 36 14 80 1 3 88 15 13 48 18 72 26 76 31
+Card 29: 68 66 52 34 99 70 29 58 19 98 | 88 64 1 14 79 31 44 39 45 40 21 6 97 13 73 11 48 67 8 50 10 57 51 94 91
+Card 30: 99 45 9 78 88 76 60 86 12 98 | 54 60 30 57 68 22 64 26 98 23 89 50 7 61 91 87 83 25 2 37 56 78 94 36 31
+Card 31: 59 93 89 84 66 44 34 88 54 27 | 29 12 61 23 49 86 24 19 54 99 35 90 65 82 13 76 20 87 48 40 62 16 80 33 43
+Card 32: 44 13 99 31 54 52 55 66 58 16 | 40 88 79 93 67 20 30 37 26 24 77 2 81 62 71 82 49 92 86 41 32 59 53 16 90
+Card 33: 76 34 40 17 37 46 72 62 47 20 | 68 73 3 5 44 78 86 82 52 22 80 91 95 42 66 77 38 88 75 33 41 4 54 65 18
+Card 34: 45 19 5 25 68 70 82 73 95 54 | 28 97 19 95 89 42 27 70 17 73 15 25 61 77 82 1 45 7 65 57 54 90 5 68 79
+Card 35: 9 66 65 71 20 89 4 27 15 54 | 97 24 49 64 14 93 77 99 78 34 88 52 83 39 60 56 79 48 57 50 82 18 3 53 95
+Card 36: 66 89 69 77 32 37 22 40 82 11 | 42 74 69 97 60 22 11 49 82 67 56 90 17 15 27 40 66 13 89 77 32 5 3 37 57
+Card 37: 93 31 41 27 36 50 59 97 86 62 | 21 28 79 92 16 86 23 5 45 34 90 66 95 37 9 71 81 67 58 85 15 73 31 25 30
+Card 38: 61 92 74 75 1 70 96 71 30 68 | 66 44 94 35 78 1 92 18 83 93 2 33 70 71 68 38 61 86 56 40 20 30 74 3 46
+Card 39: 20 15 47 8 33 55 29 94 16 18 | 21 63 8 33 15 58 94 66 16 45 30 59 29 52 20 61 86 31 48 40 25 62 47 95 18
+Card 40: 27 23 32 47 55 48 31 93 74 20 | 15 77 85 31 58 53 60 98 20 22 99 92 64 44 76 1 79 9 36 87 72 21 13 48 59
+Card 41: 57 74 11 92 16 78 44 41 13 64 | 39 34 76 80 84 58 54 38 97 23 46 86 65 69 9 15 91 53 6 29 10 49 47 64 4
+Card 42: 5 4 99 36 85 18 63 81 61 47 | 43 73 80 88 76 64 79 7 86 94 98 39 37 56 33 51 49 90 70 6 20 1 21 59 82
+Card 43: 93 18 47 21 75 30 43 90 52 23 | 50 25 65 33 90 58 57 10 55 61 30 41 62 23 76 21 2 75 18 83 92 69 37 5 98
+Card 44: 24 68 45 26 90 76 33 52 19 72 | 80 68 99 1 12 97 90 26 7 32 4 40 77 8 48 83 96 14 49 27 52 94 54 81 37
+Card 45: 94 48 13 95 73 11 8 91 84 53 | 78 84 12 59 62 57 90 5 75 55 29 22 71 92 54 47 39 53 20 14 26 69 34 48 51
+Card 46: 43 63 30 28 71 57 77 20 27 46 | 49 35 56 20 79 75 44 48 95 52 5 66 12 93 24 85 39 7 16 8 99 9 80 78 71
+Card 47: 25 62 88 36 24 10 15 90 8 23 | 4 54 9 80 42 78 32 19 21 65 86 26 28 7 96 71 48 64 36 95 69 44 89 34 57
+Card 48: 54 27 17 84 63 35 73 61 65 83 | 53 6 88 32 87 63 69 19 20 49 17 29 37 45 73 93 41 27 90 54 3 83 36 56 71
+Card 49: 84 14 88 11 45 63 90 76 38 49 | 86 60 58 31 82 98 55 8 99 92 27 50 85 96 33 19 32 3 62 46 56 2 57 16 77
+Card 50: 61 24 52 67 50 37 36 75 3 2 | 32 61 84 75 22 29 21 80 70 56 86 44 96 97 99 6 65 68 81 60 90 43 85 58 66
+Card 51: 89 91 62 39 50 92 79 7 87 6 | 36 47 77 12 98 83 54 11 31 33 68 52 41 75 62 80 18 14 43 65 15 58 19 71 13
+Card 52: 79 38 23 82 69 27 67 86 48 58 | 83 17 90 42 60 68 65 47 45 33 62 7 23 76 29 91 35 95 28 71 13 24 5 25 92
+Card 53: 86 76 93 98 81 57 44 49 65 11 | 88 28 53 34 58 4 48 23 59 41 7 87 55 74 77 14 18 8 94 99 16 19 56 61 2
+Card 54: 59 11 64 1 14 17 74 82 70 6 | 99 22 37 19 2 18 13 38 26 39 46 5 86 97 56 89 78 91 33 10 30 69 52 90 44
+Card 55: 1 18 55 64 16 44 96 20 21 46 | 64 57 21 69 42 18 89 99 20 88 33 37 55 60 31 67 24 26 1 58 96 44 46 16 98
+Card 56: 10 12 98 27 64 75 70 53 9 5 | 41 26 29 93 7 98 78 66 80 57 31 88 35 18 92 58 47 50 79 74 65 84 71 69 42
+Card 57: 52 84 86 58 4 17 91 35 12 83 | 66 17 35 81 22 25 84 10 26 42 58 4 89 83 12 91 52 47 61 9 50 54 88 86 5
+Card 58: 39 77 53 52 71 86 47 31 35 87 | 54 68 67 36 96 14 70 42 65 85 79 97 39 80 72 95 9 60 4 17 81 30 50 91 55
+Card 59: 48 4 42 32 17 24 13 30 25 90 | 65 38 97 19 16 8 52 11 15 64 73 71 74 66 58 62 49 9 37 91 75 12 56 35 80
+Card 60: 82 20 70 4 17 26 94 99 47 35 | 77 16 6 22 49 83 26 91 8 47 94 44 99 59 52 10 70 90 63 86 82 67 41 4 69
+Card 61: 44 95 42 85 16 26 81 92 61 55 | 67 7 17 8 69 34 13 82 47 18 59 76 70 11 25 99 40 85 21 12 22 77 38 44 24
+Card 62: 56 81 21 43 99 50 20 88 62 51 | 81 99 95 38 43 98 88 20 30 64 79 48 6 62 50 73 7 69 34 56 36 39 85 26 21
+Card 63: 36 72 91 33 84 95 15 50 27 24 | 21 39 47 46 65 51 16 36 6 35 89 95 62 15 75 37 56 84 13 63 31 92 93 44 77
+Card 64: 24 12 30 35 3 45 38 67 73 78 | 3 37 27 12 21 92 58 55 33 14 85 74 13 68 57 15 34 94 65 2 70 63 83 61 98
+Card 65: 54 68 51 13 20 2 26 7 91 18 | 71 11 84 8 35 2 87 24 83 89 75 82 91 28 44 79 63 67 9 46 42 53 13 93 31
+Card 66: 56 80 96 75 66 83 8 37 7 22 | 28 66 87 80 4 21 92 37 90 75 57 22 65 59 99 39 8 31 63 93 89 56 29 26 96
+Card 67: 16 46 47 23 79 96 69 93 45 33 | 76 68 18 60 89 55 23 14 25 21 92 62 52 75 28 13 98 90 94 57 12 64 31 73 45
+Card 68: 76 16 78 19 61 43 35 83 55 80 | 23 51 47 64 10 87 40 77 6 84 27 48 91 38 31 22 39 62 43 67 76 58 5 7 80
+Card 69: 23 33 56 51 8 18 58 1 61 72 | 75 14 18 12 32 23 2 41 57 35 33 61 67 27 56 10 72 58 8 31 43 5 1 87 90
+Card 70: 30 44 77 73 93 35 2 72 96 88 | 40 82 38 69 34 22 31 13 90 28 80 30 92 39 5 14 83 33 93 79 71 2 58 67 97
+Card 71: 7 6 91 81 74 36 90 20 22 97 | 12 30 96 64 34 89 56 21 15 10 76 16 14 50 11 9 95 63 55 92 66 59 27 26 75
+Card 72: 83 63 17 81 44 10 18 3 99 92 | 34 42 46 3 55 37 31 47 92 41 61 39 98 29 14 10 69 62 83 48 44 28 26 93 96
+Card 73: 47 24 29 98 77 93 27 8 73 90 | 23 72 55 65 48 70 27 86 50 68 28 77 37 40 87 14 99 49 62 97 56 36 66 47 71
+Card 74: 55 23 63 86 58 94 48 20 72 79 | 77 36 17 49 39 10 47 23 31 94 3 13 40 70 79 72 8 93 56 62 2 18 55 78 97
+Card 75: 58 16 64 19 99 22 20 89 76 44 | 50 39 92 33 32 61 44 72 88 46 25 5 68 54 74 55 78 77 7 89 64 96 95 47 76
+Card 76: 39 10 25 12 88 89 42 14 32 71 | 34 30 22 46 55 43 77 24 36 20 53 47 8 26 48 45 94 62 93 82 79 63 9 89 88
+Card 77: 12 7 66 55 73 83 43 69 37 27 | 96 81 10 89 17 22 29 44 21 3 18 45 60 32 95 62 67 42 39 49 83 82 99 65 16
+Card 78: 16 73 23 52 38 81 64 25 84 87 | 20 97 9 31 95 36 77 33 63 70 68 17 27 83 53 69 94 74 96 5 99 72 89 13 67
+Card 79: 94 28 21 83 49 34 42 9 89 10 | 81 31 85 74 60 39 38 11 15 79 55 32 72 50 99 19 3 96 98 8 76 1 90 30 47
+Card 80: 18 40 55 13 5 9 66 61 20 57 | 68 85 64 60 94 34 1 27 12 43 95 80 58 38 66 91 74 56 37 88 55 20 44 57 72
+Card 81: 88 79 67 89 83 49 50 91 48 35 | 79 87 29 2 24 48 99 18 88 89 22 91 42 4 49 67 20 73 83 17 23 50 27 76 35
+Card 82: 14 49 40 54 10 90 53 63 8 65 | 8 9 60 54 42 72 87 56 79 76 90 93 40 82 49 63 38 28 10 65 69 97 14 96 53
+Card 83: 37 31 96 81 56 70 38 66 95 54 | 24 92 38 32 23 31 29 90 33 54 80 10 66 13 86 37 1 79 95 81 44 70 3 56 8
+Card 84: 78 23 98 84 3 52 37 59 56 95 | 32 36 38 24 90 7 18 74 48 21 71 57 44 8 58 6 82 25 19 72 62 70 67 47 94
+Card 85: 74 25 65 88 20 52 39 21 17 70 | 76 93 62 26 90 34 25 7 36 98 97 70 45 19 47 22 33 21 11 27 8 57 56 71 61
+Card 86: 1 44 73 15 24 94 87 84 33 51 | 53 38 56 26 16 39 99 72 7 8 36 59 69 98 34 27 5 89 25 78 55 29 62 65 83
+Card 87: 25 27 78 39 14 43 56 36 60 33 | 85 93 71 9 39 7 72 20 13 91 30 76 68 52 94 21 56 15 70 60 32 14 84 57 77
+Card 88: 37 97 26 89 54 64 57 98 32 62 | 77 29 63 33 71 20 99 9 78 4 67 31 8 51 41 12 82 19 61 55 11 56 74 24 66
+Card 89: 75 27 74 63 42 45 72 18 85 50 | 52 2 22 57 45 50 8 10 58 65 69 74 99 32 14 42 27 51 56 30 44 20 84 12 16
+Card 90: 42 22 5 75 28 20 82 31 41 32 | 31 35 75 36 23 64 14 50 25 65 7 81 46 70 27 96 44 15 77 99 39 33 61 12 54
+Card 91: 86 76 17 16 3 93 69 13 8 95 | 12 97 48 33 55 35 84 91 5 31 57 77 28 79 6 19 98 26 43 49 1 82 37 61 24
+Card 92: 76 90 89 65 20 95 59 24 63 22 | 25 71 69 47 36 32 50 77 43 85 33 20 39 27 67 96 40 19 84 34 90 98 81 52 80
+Card 93: 91 96 47 12 2 46 61 58 39 77 | 1 69 67 60 65 63 19 32 64 46 62 8 15 94 92 93 74 20 54 29 99 89 23 75 28
+Card 94: 36 66 11 56 96 54 42 44 83 84 | 19 33 82 32 15 16 97 47 64 73 72 2 12 10 29 75 38 27 5 80 39 6 22 53 24
+Card 95: 35 26 10 67 65 73 5 75 78 18 | 75 99 54 38 73 24 33 7 28 9 64 67 74 5 26 30 37 18 39 35 53 10 4 78 65
+Card 96: 17 63 42 20 93 48 94 41 89 5 | 48 88 41 89 1 40 26 53 46 5 49 97 20 91 42 28 74 17 94 79 63 32 93 7 72
+Card 97: 48 77 23 12 8 80 59 88 92 42 | 96 88 13 97 27 86 8 48 33 99 59 23 12 39 90 36 42 92 94 38 76 80 77 26 9
+Card 98: 70 35 92 63 28 96 50 20 94 98 | 70 12 13 22 96 94 61 74 50 32 92 52 93 54 98 66 20 63 28 99 35 87 78 67 91
+Card 99: 49 65 8 14 33 57 92 90 22 97 | 14 92 84 29 61 97 72 43 26 63 57 19 60 46 49 95 35 86 39 36 80 21 30 73 74
+Card 100: 44 47 96 69 98 77 52 31 80 14 | 34 74 18 25 75 67 16 2 49 36 68 39 87 97 33 43 3 19 46 10 45 86 91 50 71
+Card 101: 28 86 75 77 17 78 96 5 20 30 | 31 67 62 83 58 90 23 25 27 35 29 22 64 50 10 15 6 88 17 78 77 9 4 66 63
+Card 102: 15 8 61 1 24 98 32 16 81 93 | 99 69 26 70 88 71 25 40 53 54 79 58 15 32 48 87 18 24 52 2 98 82 10 21 6
+Card 103: 86 29 83 91 56 31 74 87 53 22 | 45 15 79 95 3 14 94 83 16 72 65 36 38 53 78 52 39 91 50 54 86 31 99 22 56
+Card 104: 22 63 37 54 36 96 90 80 8 7 | 63 75 84 80 48 54 36 35 14 74 53 25 47 37 96 23 56 22 6 8 34 90 7 64 55
+Card 105: 49 2 17 32 41 45 85 25 83 12 | 77 13 34 83 80 20 50 47 78 30 11 48 44 86 84 21 25 63 36 49 97 74 68 53 81
+Card 106: 64 2 46 80 75 13 69 56 54 71 | 42 60 95 16 48 30 75 38 46 69 18 98 59 14 93 84 55 70 97 53 32 20 76 2 19
+Card 107: 22 64 50 79 55 18 87 8 20 98 | 28 69 96 15 70 42 11 12 38 83 55 99 62 98 3 79 53 24 91 44 19 9 4 66 82
+Card 108: 1 71 73 45 2 50 17 72 19 9 | 1 62 77 47 27 54 2 55 60 89 71 96 31 43 10 67 3 65 25 9 45 68 50 88 73
+Card 109: 39 61 22 80 23 78 85 99 71 52 | 45 53 46 75 82 84 44 33 76 57 31 65 80 2 66 49 47 39 35 95 19 96 30 14 43
+Card 110: 50 31 7 42 72 16 28 77 81 43 | 2 6 90 72 16 71 48 77 63 38 31 4 93 76 49 78 45 46 5 80 27 25 26 74 33
+Card 111: 89 53 2 28 35 5 68 42 62 23 | 35 8 78 24 85 56 55 27 14 33 48 80 18 11 71 1 53 77 91 44 58 25 74 92 43
+Card 112: 33 40 80 76 16 97 71 67 26 49 | 27 34 11 35 51 26 59 58 44 86 66 54 82 21 8 74 99 77 37 71 16 50 40 61 28
+Card 113: 34 62 21 74 51 35 19 37 89 49 | 41 5 91 23 43 62 42 68 81 89 19 70 55 88 52 15 97 80 58 26 11 63 6 49 28
+Card 114: 11 63 45 75 92 50 57 42 29 79 | 13 89 23 20 58 50 26 40 3 27 16 47 71 49 85 78 59 21 37 68 34 7 98 45 19
+Card 115: 6 64 20 23 50 14 24 33 9 15 | 61 42 74 40 95 30 18 60 46 43 3 25 14 16 92 56 53 90 19 24 78 58 63 80 49
+Card 116: 69 25 32 2 1 6 24 17 89 4 | 13 57 77 49 27 87 91 68 52 96 20 21 5 62 90 39 47 55 56 63 30 38 14 79 45
+Card 117: 8 5 28 47 41 25 87 73 17 56 | 43 63 88 32 35 20 13 66 64 86 30 10 92 71 45 57 70 69 62 18 9 93 1 81 95
+Card 118: 38 54 10 60 63 36 90 47 83 18 | 63 47 45 65 78 60 55 98 91 36 22 81 83 18 90 15 40 10 87 38 54 33 8 32 4
+Card 119: 82 95 23 76 45 72 16 62 71 83 | 46 66 81 9 16 93 87 4 40 97 5 72 78 54 67 56 61 12 21 74 64 52 23 14 26
+Card 120: 64 42 36 63 41 71 84 69 85 29 | 80 31 87 20 18 71 43 64 94 7 54 36 45 86 41 60 28 84 88 26 63 85 69 58 77
+Card 121: 66 77 99 55 75 31 44 30 47 73 | 20 59 45 34 63 89 88 52 39 13 91 61 78 76 73 99 38 23 40 50 4 1 65 67 58
+Card 122: 9 20 68 24 25 67 3 63 34 12 | 81 48 31 89 72 99 11 26 13 73 58 94 42 57 59 5 74 12 18 20 60 88 83 76 2
+Card 123: 51 24 73 56 61 57 79 46 37 69 | 55 38 63 17 85 75 59 61 88 50 53 72 1 5 66 52 14 80 74 6 57 22 97 70 77
+Card 124: 59 97 26 20 53 15 27 65 2 23 | 75 2 74 22 72 91 85 33 98 11 26 99 9 62 61 16 87 69 8 32 10 37 59 20 48
+Card 125: 30 58 23 6 81 8 3 37 53 15 | 75 66 81 42 32 84 57 40 63 19 70 76 74 54 61 82 44 8 16 80 55 87 10 92 22
+Card 126: 30 71 38 18 91 61 68 99 13 16 | 91 5 99 88 86 61 16 90 13 9 58 30 69 50 71 1 28 54 20 40 68 46 18 4 73
+Card 127: 74 60 96 29 69 68 16 80 45 20 | 53 31 71 26 42 64 99 5 81 92 43 96 16 69 22 19 88 60 54 20 29 76 6 56 11
+Card 128: 47 88 77 56 66 5 38 14 70 1 | 19 5 1 76 2 77 35 51 68 22 75 44 45 13 37 96 86 60 85 87 25 26 64 11 65
+Card 129: 76 13 49 32 89 52 40 43 54 86 | 57 12 64 59 21 1 40 45 20 24 60 68 77 14 55 80 88 11 83 94 84 4 58 71 18
+Card 130: 77 98 41 54 64 1 14 20 51 26 | 5 53 6 80 46 14 29 9 77 55 94 40 84 60 33 97 66 64 81 1 75 73 28 16 36
+Card 131: 16 88 64 81 42 51 13 10 45 48 | 18 77 28 84 75 94 13 35 27 83 29 2 11 44 48 20 19 46 17 25 70 38 30 42 54
+Card 132: 17 95 50 10 52 65 94 91 49 44 | 30 19 5 13 49 97 44 60 54 38 64 92 37 87 33 67 35 43 40 16 91 15 7 96 36
+Card 133: 3 51 66 53 19 60 34 26 32 75 | 87 29 64 65 10 50 98 42 69 35 89 26 41 23 14 94 38 49 13 37 53 31 95 90 27
+Card 134: 81 88 58 61 11 31 54 29 42 50 | 44 35 72 34 21 57 86 79 2 11 67 85 37 49 83 70 64 63 95 12 62 52 71 15 3
+Card 135: 8 45 79 72 50 38 17 92 89 91 | 77 23 59 53 36 80 25 95 69 83 33 40 62 49 86 19 18 75 84 48 44 47 96 39 73
+Card 136: 4 41 75 98 60 79 65 9 74 20 | 90 98 16 2 41 9 1 79 28 27 37 47 20 80 74 36 48 60 42 26 75 65 58 4 6
+Card 137: 96 77 70 23 91 54 43 61 25 4 | 36 96 45 18 42 10 24 65 52 99 93 38 76 27 77 95 23 61 35 34 85 43 59 70 54
+Card 138: 74 87 59 72 88 15 14 97 68 13 | 11 84 15 27 33 38 8 72 12 40 88 37 14 75 97 82 39 57 87 2 83 68 74 59 13
+Card 139: 12 20 1 36 10 91 16 42 94 8 | 74 10 86 57 3 27 25 15 33 78 24 84 19 35 58 38 17 77 59 85 4 92 2 55 60
+Card 140: 62 18 78 34 56 35 70 69 12 50 | 60 8 52 72 95 97 56 69 39 59 38 78 35 43 25 7 16 89 87 57 49 36 88 62 76
+Card 141: 7 36 86 91 88 37 23 67 92 41 | 86 36 60 4 83 14 88 45 44 23 90 16 7 10 30 92 64 52 91 58 9 72 67 37 94
+Card 142: 15 68 29 85 72 87 78 4 45 33 | 70 5 78 53 22 13 88 52 72 37 55 7 24 41 90 58 84 23 73 83 3 66 96 61 92
+Card 143: 8 47 60 23 42 79 66 44 68 62 | 44 66 79 51 8 39 22 85 38 81 42 21 60 67 11 25 7 47 23 9 68 12 70 62 83
+Card 144: 46 62 12 26 90 16 95 99 8 93 | 23 5 94 99 30 85 75 16 34 81 11 53 27 8 90 82 26 62 87 55 14 73 97 67 93
+Card 145: 48 96 83 27 12 82 3 29 86 49 | 21 27 96 82 84 49 3 70 76 91 32 29 12 22 58 86 44 87 61 2 83 72 48 40 68
+Card 146: 62 1 12 83 72 10 50 17 98 5 | 19 26 83 98 49 87 24 32 40 35 50 85 18 17 38 7 61 8 5 20 77 34 1 33 62
+Card 147: 5 62 85 11 61 49 2 88 75 59 | 59 23 11 44 73 35 82 63 2 33 68 49 75 56 88 62 67 61 5 98 89 19 24 90 76
+Card 148: 89 21 6 97 13 61 82 71 37 84 | 71 5 7 34 19 66 4 61 55 10 25 82 97 9 72 30 89 13 21 77 6 31 58 84 48
+Card 149: 46 96 58 2 92 66 52 39 22 23 | 70 31 7 45 46 58 27 2 42 25 59 66 52 99 96 63 39 14 62 51 95 84 69 8 89
+Card 150: 85 61 42 49 66 9 40 74 8 77 | 41 89 97 87 48 49 69 82 21 54 91 52 71 46 28 99 47 78 98 39 81 95 9 33 85
+Card 151: 70 35 27 20 42 47 72 89 8 64 | 73 42 3 10 59 72 89 70 50 35 2 8 32 5 36 47 29 98 75 51 30 58 43 86 56
+Card 152: 65 21 42 45 83 97 90 96 12 28 | 21 30 83 14 24 49 10 65 88 79 64 8 33 15 57 1 97 32 91 78 39 62 4 99 23
+Card 153: 22 82 23 85 32 25 83 63 68 59 | 52 48 27 94 43 18 21 90 10 62 22 35 55 50 77 93 12 42 91 73 64 36 84 9 8
+Card 154: 86 15 55 71 88 99 77 18 66 30 | 31 18 38 57 76 53 82 1 49 84 77 14 26 11 40 86 41 87 47 9 62 88 20 59 21
+Card 155: 34 52 7 30 51 83 42 86 49 16 | 51 57 77 36 21 13 17 88 56 98 96 66 62 63 6 37 52 70 50 32 43 45 47 64 53
+Card 156: 1 48 76 45 33 51 16 20 25 47 | 49 41 1 64 13 57 79 53 35 6 52 71 97 83 95 87 88 58 37 16 24 63 31 94 46
+Card 157: 20 3 5 93 75 15 89 14 96 43 | 42 30 91 82 34 44 31 41 4 59 62 54 38 33 25 51 84 28 96 85 8 60 83 10 36
+Card 158: 68 19 67 1 7 92 4 81 98 53 | 71 64 18 83 66 57 25 49 30 62 95 77 93 40 75 47 15 84 78 9 48 52 24 38 34
+Card 159: 3 32 42 47 90 1 27 66 50 97 | 4 41 22 18 36 57 76 50 80 24 27 45 25 88 58 29 83 87 86 89 59 66 3 11 13
+Card 160: 76 74 90 64 70 1 97 28 68 84 | 18 19 67 84 12 51 97 60 68 92 28 90 1 94 93 64 30 2 74 76 61 49 85 70 96
+Card 161: 75 12 21 36 44 85 1 43 29 45 | 99 87 38 73 60 33 80 25 1 54 85 45 4 57 41 29 43 90 49 44 27 12 31 16 23
+Card 162: 23 69 91 77 84 98 55 89 92 74 | 26 44 25 49 10 15 82 37 39 64 61 83 53 1 38 69 22 96 5 91 36 65 75 41 98
+Card 163: 78 64 29 96 73 12 35 19 65 38 | 76 96 35 9 34 41 46 39 3 10 27 24 13 84 91 92 22 58 62 16 8 12 60 18 56
+Card 164: 82 84 96 81 23 19 58 2 24 62 | 36 93 49 5 71 87 34 39 2 98 97 28 77 70 17 53 51 23 57 81 3 48 29 27 62
+Card 165: 53 95 19 88 39 99 29 62 91 77 | 18 51 63 11 99 71 84 86 57 96 60 62 77 32 35 27 98 23 97 1 65 17 15 87 38
+Card 166: 17 46 33 41 80 57 47 91 1 64 | 33 98 57 1 88 23 64 41 43 61 84 11 7 52 80 60 4 97 75 46 55 21 47 91 79
+Card 167: 47 3 71 68 6 94 54 61 66 72 | 69 9 10 67 68 87 49 61 56 6 85 59 75 23 44 90 94 13 66 52 53 72 64 45 31
+Card 168: 90 57 89 45 63 53 61 46 96 55 | 57 94 39 18 45 53 27 24 81 79 50 30 21 31 83 99 67 98 92 90 22 47 46 80 7
+Card 169: 7 47 36 15 24 51 52 9 48 61 | 15 88 48 99 3 12 22 7 47 87 89 57 9 24 82 51 97 61 52 1 36 54 94 63 62
+Card 170: 26 42 91 72 64 18 69 81 44 22 | 46 60 73 35 4 52 33 51 13 82 62 5 27 90 95 2 7 56 44 76 75 50 87 70 74
+Card 171: 17 80 28 54 57 90 86 59 67 1 | 1 59 19 90 37 57 76 87 42 73 20 41 68 33 67 53 28 50 86 54 80 99 6 17 91
+Card 172: 95 28 26 47 83 76 31 52 70 89 | 69 18 8 50 20 27 16 60 11 88 75 13 34 57 90 1 5 91 38 32 6 68 65 35 33
+Card 173: 15 74 3 88 42 10 62 59 39 27 | 34 61 14 52 74 88 22 39 67 23 10 73 27 46 55 24 30 89 35 82 66 83 86 15 43
+Card 174: 6 8 3 61 1 87 94 18 20 93 | 59 56 13 57 85 8 67 6 14 60 10 69 29 3 99 26 44 78 82 22 49 24 36 90 87
+Card 175: 47 64 30 84 70 92 51 53 12 73 | 11 79 23 33 4 2 36 47 7 53 10 13 20 92 51 72 32 61 94 78 5 64 69 19 54
+Card 176: 55 57 29 40 25 44 96 7 70 14 | 51 88 85 62 5 66 23 30 81 33 50 75 25 61 59 43 87 71 32 76 27 48 8 11 86
+Card 177: 57 9 53 8 63 88 32 52 79 28 | 35 42 99 1 72 64 51 11 58 16 50 70 21 87 65 77 66 94 63 96 47 32 62 81 92
+Card 178: 48 22 72 59 60 61 8 39 24 67 | 34 88 67 4 48 59 84 98 83 26 50 10 57 45 14 7 9 21 63 17 94 91 37 39 36
+Card 179: 11 60 35 51 80 12 53 22 71 72 | 10 18 70 11 16 19 72 23 83 63 61 58 56 50 28 89 7 75 59 48 81 54 33 2 40
+Card 180: 50 48 20 85 86 18 67 91 27 22 | 7 14 31 51 36 42 66 56 46 16 15 10 5 67 90 2 19 63 26 35 91 82 43 68 49
+Card 181: 75 78 86 53 61 26 68 77 85 25 | 95 40 18 73 6 43 74 87 51 64 37 83 62 24 19 33 2 7 13 52 48 63 57 70 75
+Card 182: 6 60 67 18 39 29 33 54 37 83 | 15 72 38 35 8 96 36 44 81 19 21 1 40 87 46 52 9 4 28 31 85 13 68 32 41
+Card 183: 52 18 27 20 7 46 38 58 91 37 | 20 46 27 9 37 90 63 99 59 78 66 65 88 91 18 21 1 49 85 71 26 4 8 58 50
+Card 184: 38 58 36 50 76 43 32 98 69 23 | 36 24 69 33 48 92 28 44 43 91 58 50 86 4 98 78 76 81 23 32 71 27 66 40 38
+Card 185: 53 21 69 24 51 39 88 3 78 5 | 89 78 73 61 59 21 8 79 64 51 39 66 53 69 67 68 36 29 88 38 44 47 46 19 13
+Card 186: 48 54 68 40 60 27 45 51 61 17 | 52 78 51 35 45 74 62 89 27 76 48 17 56 53 40 14 61 11 68 37 31 54 39 60 4
+Card 187: 64 49 14 90 67 54 40 21 60 71 | 8 30 55 89 17 90 97 60 16 49 74 14 67 24 82 64 51 25 61 98 12 19 35 40 43
+Card 188: 53 51 65 17 4 88 5 69 28 34 | 11 24 78 69 77 26 88 4 60 71 28 20 59 10 51 2 17 49 52 65 34 8 53 64 5
+Card 189: 53 78 45 15 50 2 6 16 3 38 | 53 10 27 45 67 38 76 56 50 4 41 77 91 16 3 6 60 13 2 43 15 9 98 20 78
+Card 190: 72 54 84 76 69 10 13 19 97 26 | 84 45 29 49 71 72 2 47 16 32 46 14 5 34 35 99 6 93 56 89 22 79 73 24 64
+Card 191: 18 70 33 56 72 68 98 52 24 46 | 55 52 25 18 24 12 49 15 46 23 71 72 89 26 33 2 76 7 44 56 68 97 83 70 98
+Card 192: 33 34 57 40 93 14 12 45 79 25 | 97 20 48 39 90 64 27 40 26 58 42 60 45 2 81 80 23 34 79 57 24 18 71 53 5
+Card 193: 87 90 72 76 10 83 41 6 54 23 | 23 18 1 76 93 88 96 72 7 31 20 90 68 30 39 40 44 11 35 3 78 54 17 46 60
+Card 194: 5 10 25 27 6 45 67 86 92 32 | 68 32 21 5 33 74 42 27 84 48 46 14 38 39 64 47 95 86 45 56 31 25 67 15 17
+Card 195: 31 33 64 80 68 21 20 29 63 11 | 80 81 1 56 61 21 12 33 64 30 76 82 97 43 27 52 31 20 70 45 17 4 60 77 68
+Card 196: 73 91 78 83 14 54 94 92 9 8 | 3 56 55 76 96 22 17 43 15 40 52 51 13 50 79 65 41 25 60 11 93 53 99 4 87
+Card 197: 63 64 25 48 91 95 77 7 38 69 | 40 29 14 72 27 5 10 97 56 30 51 13 15 34 75 87 86 60 45 88 33 61 90 32 85
+Card 198: 70 60 61 56 16 81 18 12 88 65 | 5 67 62 45 43 21 32 94 19 27 77 58 50 41 9 85 29 40 92 87 54 24 76 48 33
+Card 199: 29 26 70 45 22 86 27 64 95 80 | 46 5 38 61 44 97 9 15 78 93 73 34 7 23 67 41 58 33 1 85 48 98 4 14 53
+Card 200: 3 88 81 61 64 39 54 51 49 17 | 16 87 35 37 82 68 55 19 80 33 10 2 48 25 79 89 52 4 44 59 26 72 90 83 9
+Card 201: 28 44 46 58 13 92 35 16 30 14 | 32 79 85 98 67 55 21 41 93 43 19 72 35 24 90 64 88 82 84 20 45 91 81 38 49
+Card 202: 85 43 47 11 9 21 27 53 17 95 | 10 6 26 91 30 69 52 20 28 16 82 45 72 54 58 96 88 99 38 55 78 98 15 70 4
diff --git a/day4/uppga.c b/day4/uppga.c
@@ -0,0 +1,34 @@
+#include "common.h"
+
+int main(int argc, char **argv) {
+ char **lines;
+ size_t nlines = readlines(&lines, "input");
+ size_t i;
+ uint64_t card;
+ uint64_t sum = 0;
+
+ smallset ls[nlines], rs[nlines];
+
+ parse_sets(ls, rs, lines, nlines);
+
+ smallset in[nlines];
+
+ for (i = 0; i < nlines; i++) {
+ smallset_init(&in[i], 128);
+ smallset_intersection(&in[i], &ls[i], &rs[i]);
+
+ card = smallset_cardinality(&in[i]);
+ if (card != 0)
+ sum += (1 << (card - 1));
+ }
+
+ printf("%llu\n", sum);
+
+ for (i = 0; i < nlines; i++) {
+ smallset_clear(&in[i]);
+ smallset_clear(&ls[i]);
+ smallset_clear(&rs[i]);
+ }
+
+ return 0;
+}
diff --git a/day4/uppgb.c b/day4/uppgb.c
@@ -0,0 +1,43 @@
+#include "common.h"
+
+int main(int argc, char **argv) {
+ char **lines;
+ size_t nlines = readlines(&lines, "input");
+ size_t i, j;
+ uint64_t card;
+ uint64_t sum = 0;
+ uint64_t copies[nlines];
+ smallset ls[nlines], rs[nlines], in[nlines];
+
+ parse_sets(ls, rs, lines, nlines);
+
+ for (i = 0; i < nlines; i++) {
+ copies[i] = 1;
+ }
+
+ for (i = 0; i < nlines; i++) {
+ smallset_init(&in[i], 128);
+ smallset_intersection(&in[i], &ls[i], &rs[i]);
+
+ card = smallset_cardinality(&in[i]);
+ for (j = i + 1; j <= i + card; j++) {
+ if (j >= nlines)
+ break;
+ copies[j] += copies[i];
+ }
+ }
+
+ for (i = 0; i < nlines; i++) {
+ sum += copies[i];
+ }
+
+ printf("%llu\n", sum);
+
+ for (i = 0; i < nlines; i++) {
+ smallset_clear(&in[i]);
+ smallset_clear(&ls[i]);
+ smallset_clear(&rs[i]);
+ }
+
+ return 0;
+}
diff --git a/day5/Makefile b/day5/Makefile
@@ -0,0 +1,30 @@
+CC=clang
+CFLAGS+=-std=c99 -pedantic -Wall -Werror -Wstrict-prototypes
+CFLAGS+=-Wmissing-prototypes -Wmissing-declarations -Wshadow
+CFLAGS+=-Wpointer-arith -Wcast-qual -Wsign-compare
+CFLAGS+=-O2 -g
+CFLAGS+=-fstack-protector-all -Wtype-limits -fno-common
+CFLAGS+=-fno-builtin
+CFLAGS+=-I/usr/local/include
+CFLAGS+=-I../utils
+#LDFLAGS=
+
+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) $(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)
+
+utils:
+ make -C ../utils
+
+clean:
+ rm -rf common.o uppga uppgb
diff --git a/day5/common.c b/day5/common.c
@@ -0,0 +1,47 @@
+#include "common.h"
+
+static inline int is_digit(char x) { return '0' <= x && x <= '9'; }
+
+size_t read_ranges(size_t *nranges, range_t *ranges, char **lines,
+ size_t nlines) {
+ size_t i = 2; // skip to range data
+ size_t count = 0;
+ uint64_t t, s, b;
+ range_t ran;
+ char *cp;
+ nranges[count] = 0;
+
+ while (i < nlines) {
+ if (is_digit(lines[i][0])) {
+ cp = sread_next_u64(&t, lines[i]);
+ cp = sread_next_u64(&s, cp);
+ cp = sread_next_u64(&b, cp);
+
+ ran.lb = s;
+ ran.ub = s + b - 1;
+ ran.delta = (int64_t)t - (int64_t)s;
+ ranges[count * nlines + nranges[count]] = ran;
+ nranges[count]++;
+ } else if (lines[i][0] == '\n') {
+ count++;
+ nranges[count] = 0;
+ }
+
+ i++;
+ }
+
+ return count + 1;
+}
+
+stack_u64 read_starts(char **lines) {
+ char *cp = lines[0];
+ uint64_t t;
+ stack_u64 r;
+ stack_u64_init(&r);
+
+ while ((cp = sread_next_u64(&t, cp)) != NULL) {
+ stack_u64_push(&r, t);
+ }
+
+ return r;
+}
diff --git a/day5/common.h b/day5/common.h
@@ -0,0 +1,22 @@
+#ifndef COMMON_H_
+#define COMMON_H_
+
+#include <assert.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <reading.h>
+#include <stack_u64.h>
+
+typedef struct {
+ uint64_t lb;
+ uint64_t ub;
+ int64_t delta;
+} range_t;
+
+size_t read_ranges(size_t *nranges, range_t *ranges, char **lines,
+ size_t nlines);
+stack_u64 read_starts(char **lines);
+
+#endif
diff --git a/day5/exinput b/day5/exinput
@@ -0,0 +1,33 @@
+seeds: 79 14 55 13
+
+seed-to-soil map:
+50 98 2
+52 50 48
+
+soil-to-fertilizer map:
+0 15 37
+37 52 2
+39 0 15
+
+fertilizer-to-water map:
+49 53 8
+0 11 42
+42 0 7
+57 7 4
+
+water-to-light map:
+88 18 7
+18 25 70
+
+light-to-temperature map:
+45 77 23
+81 45 19
+68 64 13
+
+temperature-to-humidity map:
+0 69 1
+1 0 69
+
+humidity-to-location map:
+60 56 37
+56 93 4
diff --git a/day5/input b/day5/input
@@ -0,0 +1,236 @@
+seeds: 2880930400 17599561 549922357 200746426 1378552684 43534336 155057073 56546377 824205101 378503603 1678376802 130912435 2685513694 137778160 2492361384 188575752 3139914842 1092214826 2989476473 58874625
+
+seed-to-soil map:
+341680072 47360832 98093750
+1677587229 1836834678 160297919
+1122651749 4014790961 280176335
+2279929873 2689269992 53644948
+3916120104 1199400457 172302726
+0 381576527 58197295
+1402828084 3450816018 274759145
+3909949227 2540063154 6170877
+802918801 2384227172 155835982
+4088422830 3244271552 206544466
+958754783 1997132597 28874650
+58197295 306349987 75226540
+180784667 145454582 160895405
+2334903647 1543332738 293501940
+3699983017 2997982209 25342830
+2333574821 2687941166 1328826
+3111317969 1371703183 171629555
+2806959198 2135774873 248452299
+2766721604 717118138 40237594
+3055411497 2632034694 55906472
+2628405587 3023325039 138316017
+1837885148 757355732 442044725
+3725325847 2813358829 184623380
+3353391413 2026007247 109767626
+987629433 3962399141 10015813
+717118138 2546234031 85800663
+3282947524 2742914940 70443889
+1080275742 3972414954 42376007
+133423835 0 47360832
+3463159039 3725575163 236823978
+997645246 3161641056 82630496
+
+soil-to-fertilizer map:
+303672059 1087423328 103502353
+171922589 2907629744 91556518
+2064217168 468859004 91214014
+1129888530 1046445685 40977643
+3698610046 4215442249 79525047
+1045870106 1586657152 41455160
+1170866173 1322928302 17679660
+4160148003 3332238470 107558461
+4267706464 3853049576 27260832
+0 3007612896 90771201
+3447204990 3880310408 249339913
+1189561657 1438888401 43309463
+4019710828 3219712242 104981462
+2226263856 2187322171 114088350
+553216166 1847338068 182148047
+3217647099 3439796931 229557891
+2832115692 1482197864 23307900
+867366834 94995931 178503272
+1969221237 0 94995931
+3785679859 3704810535 148239041
+1095751900 2693816297 34136630
+4124692290 3669354822 35455713
+454935727 1340607962 98280439
+2204466075 1628112312 21797781
+1947833351 2164918461 21387886
+2634687717 1649910093 197427975
+263479107 2850768768 40192952
+3696544903 3217647099 2065143
+735364213 1190925681 132002621
+3050783393 2337205982 47600704
+1087325266 2999186262 8426634
+3778135093 3324693704 7544766
+2855423592 273499203 195359801
+90771201 1505505764 81151388
+2340352206 560073018 290906919
+1531641800 939263745 107181940
+1188545833 2186306347 1015824
+1355686961 850979937 88283808
+1492181516 2029486115 39460284
+1638823740 2384806686 309009611
+2155431182 2894390312 13239432
+1443970769 2068946399 48210747
+1232871120 2727952927 122815841
+3933918900 4129650321 85791928
+2631259125 2890961720 3428592
+407174412 2117157146 47761315
+2168670614 2301410521 35795461
+
+fertilizer-to-water map:
+4253126168 3603943470 41841128
+3150812716 3873122781 161556325
+4132148538 3445929121 16652907
+4071215062 2557593856 10373731
+3585414898 2401284809 61555959
+124617758 989226185 56063423
+1311995731 916233018 72993167
+180681181 891200267 25032751
+1577315548 1448436684 231921083
+69948934 1391916079 39397864
+2730663795 3577458422 26485048
+2453473122 3255362867 102306532
+4148801445 3801350502 12292818
+3002725397 3107275548 148087319
+3525935437 3813643320 59479461
+3982955340 3357669399 88259722
+2631712351 2567967587 98951444
+628324302 2038793089 109830184
+3427245435 3721480891 3936914
+796140554 1045289608 36965524
+939693576 1140241200 24301167
+205713932 1680357767 358435322
+4161094263 2666919031 92031905
+1103981621 0 206162329
+1809236631 761213122 129987145
+1310143950 1431313943 1851781
+4081588793 3056715803 50559745
+738154486 1082255132 57986068
+564149254 206162329 64175048
+3722667150 4034679106 260288190
+3431182349 2462840768 94753088
+109346798 1433165724 15270960
+2757148843 2811139249 245576554
+1044349135 2294919620 59632486
+833106078 270337377 106587498
+3646970857 3645784598 75696293
+0 2354552106 4006979
+1974270838 376924875 384288247
+3312369041 3462582028 114876394
+2401284809 2758950936 52188313
+1384988898 1199589429 192326650
+963994743 2214565228 80354392
+1939223776 1164542367 35047062
+4006979 2148623273 65941955
+2555779654 3725417805 75932697
+
+water-to-light map:
+1553071310 2767299260 81555093
+1638385137 3758734 7165416
+3923895602 3742459208 355646104
+2563492152 40550035 317968
+357175543 151852464 53516575
+756535305 2730597762 36701498
+1142337672 1915537677 164067723
+436470886 2848854353 61956232
+1316538987 1679005354 102639946
+609765571 2079605400 146769734
+1306405395 2660382036 10133592
+3817572860 3406157555 106322742
+2023184953 353497588 62195869
+3531543848 4223491605 71475691
+410692118 126073696 25778768
+4279541706 3727562743 14896465
+2903607795 1495097536 74179449
+1794747312 2279656479 95385933
+2783150325 2269091374 10565105
+3406157555 4098105312 125386293
+2145462956 205369039 148128549
+2833741244 2401175172 69866551
+793236803 685594104 306384629
+1645550553 2511185277 149196759
+1419178933 1781645300 133892377
+1634626403 0 3758734
+3274934245 2471041723 36449164
+0 1097896179 357175543
+2563810120 991978733 105917446
+4294438171 3727033618 529125
+2688189328 1569276985 94960997
+2669727566 2507490887 3694390
+3311383409 10924150 29625885
+1099621432 2226375134 42716240
+1890133245 2910810585 133051708
+583632811 2375042412 26132760
+498427118 40868003 85205693
+2293591505 415693457 269900647
+2673421956 1664237982 14767372
+2085380822 2670515628 60082134
+3603019539 3512480297 214553321
+2977787244 3043862293 297147001
+2793715430 1455071722 40025814
+
+light-to-temperature map:
+3752181853 3850028427 61847460
+3392702182 4061054452 68370555
+3610251302 4129425007 141930551
+2019529001 2633762146 55812503
+1423059901 2612524947 21237199
+1637625157 3160312690 128493598
+2109055159 2018596226 368399035
+343891384 811352094 920120231
+154347384 2422980947 189544000
+2075341504 1978947609 33713655
+1444297100 2966984633 193328057
+35985686 2689574649 118361698
+2477454194 0 811352094
+1772053717 1854798742 124148867
+1264011615 2807936347 159048286
+0 2386995261 35985686
+1766118755 2012661264 5934962
+3814029313 3392702182 457326245
+3461072737 3911875887 149178565
+1896202584 1731472325 123326417
+
+temperature-to-humidity map:
+3344602117 2991074372 262457649
+1707309180 3911386116 383581180
+3778482785 2130995124 374719434
+3607059766 3253532021 171423019
+584508486 478912361 161371970
+1578590582 2505714558 128718598
+3294145751 1806488186 50456366
+1143023241 2829557603 161516769
+1304540010 1856944552 274050572
+2090890360 3424955040 344665999
+2435556359 1143023241 663464945
+496214964 1000471163 88293522
+0 640284331 360186832
+3099021304 2634433156 195124447
+360186832 342884229 136028132
+745880456 0 342884229
+4153202219 3769621039 141765077
+
+humidity-to-location map:
+3114211644 984440400 35385940
+3530465412 479339778 128291026
+0 3699707734 285474938
+2898087648 3606829306 92878428
+2762235329 607630804 135852319
+4210792153 4197161772 84175143
+3149597584 31394121 380867828
+1848709689 0 31394121
+1880103810 412261949 67077829
+285474938 1579019790 1563234751
+2990966076 3566305423 40523883
+2434079297 1019826340 328156032
+2371232521 3985182672 62846776
+1947181639 3142254541 424050882
+3899713715 1347982372 148315733
+3031489959 1496298105 82721685
+4197161772 4281336915 13630381
+3658756438 743483123 240957277
diff --git a/day5/uppga.c b/day5/uppga.c
@@ -0,0 +1,47 @@
+#include "common.h"
+
+static uint64_t get_value(uint64_t start, range_t *ranges, size_t *nranges,
+ size_t np, size_t nlines) {
+ size_t i, j;
+ uint64_t cv = start;
+ range_t ran;
+
+ for (i = 0; i < np; i++) {
+ for (j = 0; j < nranges[i]; j++) {
+ ran = ranges[i * nlines + j];
+ if (ran.lb <= cv && cv <= ran.ub) {
+ cv += ran.delta;
+ break;
+ }
+ }
+ }
+
+ return cv;
+}
+
+int main(int argc, char **argv) {
+ char **lines;
+ size_t nlines = readlines(&lines, "input");
+
+ uint64_t min_value = UINT64_MAX;
+ uint64_t t;
+
+ size_t nranges[nlines];
+ range_t ranges[nlines * nlines];
+
+ uint64_t np = read_ranges(nranges, ranges, lines, nlines);
+ stack_u64 starts = read_starts(lines);
+
+ size_t i;
+ for (i = 0; i < starts.nmemb; i++) {
+ t = get_value(starts.data[i], ranges, nranges, np, nlines);
+ if (t < min_value)
+ min_value = t;
+ }
+
+ stack_u64_clear(&starts);
+
+ printf("%llu\n", min_value);
+
+ return 0;
+}
diff --git a/day5/uppgb.c b/day5/uppgb.c
@@ -0,0 +1,108 @@
+#include "common.h"
+
+static uint64_t backmap(uint64_t x, range_t *ranges, size_t *nranges, size_t i,
+ size_t nlines) {
+ size_t j;
+ range_t ran;
+
+ for (j = 0; j < nranges[i]; j++) {
+ ran = ranges[i * nlines + j];
+
+ if (ran.lb + ran.delta <= x && x <= ran.ub + ran.delta) {
+ return x - ran.delta;
+ }
+ }
+
+ return x;
+}
+
+static uint64_t compute_value(uint64_t x, range_t *ranges, size_t *nranges,
+ size_t nlines, size_t np) {
+ size_t i, j;
+ range_t ran;
+ uint64_t cv = x;
+
+ for (i = 0; i < np; i++) {
+ for (j = 0; j < nranges[i]; j++) {
+ ran = ranges[i * nlines + j];
+ if (ran.lb <= cv && cv <= ran.ub) {
+ cv += ran.delta;
+ break;
+ }
+ }
+ }
+
+ return cv;
+}
+
+static int is_in_ranges(uint64_t x, stack_u64 *lbs, stack_u64 *ubs) {
+ size_t i;
+
+ for (i = 0; i < lbs->nmemb; i++) {
+ if (lbs->data[i] <= x && x <= ubs->data[i])
+ return 1;
+ }
+
+ return 0;
+}
+
+int main(int argc, char **argv) {
+ char **lines;
+ size_t nlines = readlines(&lines, "input");
+ size_t i, j;
+ int u;
+ uint64_t val;
+ uint64_t minval = UINT64_MAX;
+
+ size_t nranges[nlines];
+ range_t ranges[nlines * nlines];
+
+ uint64_t np = read_ranges(nranges, ranges, lines, nlines);
+
+ stack_u64 starts = read_starts(lines);
+ stack_u64 lbs, ubs;
+ stack_u64_init(&lbs);
+ stack_u64_init(&ubs);
+ for (i = 0; i < starts.nmemb; i += 2) {
+ stack_u64_push(&lbs, starts.data[i]);
+ stack_u64_push(&ubs, starts.data[i] + starts.data[i + 1] - 1);
+ }
+
+ stack_u64 lowpoints[np];
+ for (i = 0; i < np; i++) {
+ stack_u64_init(&lowpoints[i]);
+ }
+
+ stack_u64_push(&lowpoints[np - 1], 0);
+
+ u = np - 2;
+ while (u >= 0) {
+ for (j = 0; j < nranges[u]; j++) {
+ stack_u64_push(&lowpoints[u], ranges[u * nlines + j].lb);
+ stack_u64_push(&lowpoints[u], ranges[u * nlines + j].ub + 1);
+ }
+
+ for (j = 0; j < lowpoints[u + 1].nmemb; j++) {
+ stack_u64_push(&lowpoints[u], backmap(lowpoints[u + 1].data[j], ranges,
+ nranges, u, nlines));
+ }
+
+ u--;
+ }
+
+ for (i = 0; i < lbs.nmemb; i++) {
+ stack_u64_push(&lowpoints[0], lbs.data[i]);
+ }
+
+ for (j = 0; j < lowpoints[0].nmemb; j++) {
+ if (is_in_ranges(lowpoints[0].data[j], &lbs, &ubs)) {
+ val = compute_value(lowpoints[0].data[j], ranges, nranges, nlines, np);
+ if (val < minval)
+ minval = val;
+ }
+ }
+
+ printf("%llu\n", minval);
+
+ return 0;
+}
diff --git a/day6/Makefile b/day6/Makefile
@@ -0,0 +1,30 @@
+CC=clang
+CFLAGS+=-std=c99 -pedantic -Wall -Werror -Wstrict-prototypes
+CFLAGS+=-Wmissing-prototypes -Wmissing-declarations -Wshadow
+CFLAGS+=-Wpointer-arith -Wcast-qual -Wsign-compare
+CFLAGS+=-O2 -g
+CFLAGS+=-fstack-protector-all -Wtype-limits -fno-common
+CFLAGS+=-fno-builtin
+CFLAGS+=-I/usr/local/include
+CFLAGS+=-I../utils
+LDFLAGS=-lm
+
+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) $(CFLAGS) -o uppga uppga.c common.o $(UTILS) $(INCLUDES) $(LDFLAGS)
+
+uppgb: $(UTILS) common.o uppgb.c
+ $(CC) $(CFLAGS) -o uppgb uppgb.c common.o $(UTILS) $(INCLUDES) $(LDFLAGS)
+
+utils:
+ make -C ../utils
+
+clean:
+ rm -rf common.o uppga uppgb
diff --git a/day6/common.c b/day6/common.c
@@ -0,0 +1,35 @@
+#include "common.h"
+
+void read_data(stack_u64 *times, stack_u64 *distances, char **lines,
+ size_t nlines) {
+ char *cp = lines[0];
+ uint64_t t;
+
+ while ((cp = sread_next_u64(&t, cp)) != NULL) {
+ stack_u64_push(times, t);
+ }
+
+ cp = lines[1];
+ while ((cp = sread_next_u64(&t, cp)) != NULL) {
+ stack_u64_push(distances, t);
+ }
+}
+
+uint64_t counter(uint64_t t, uint64_t d) {
+ if (t * t < 4 * d)
+ return 0;
+
+ uint64_t r = t * t - 4 * d;
+ long double rr = sqrtl((long double)r);
+
+ uint64_t lb = (uint64_t)floorl(((long double)t - rr) / 2);
+ uint64_t ub = (uint64_t)ceill(((long double)t + rr) / 2);
+
+ while (lb * (t - lb) <= d)
+ lb++;
+
+ while (ub * (t - ub) <= d)
+ ub--;
+
+ return ub - lb + 1;
+}
diff --git a/day6/common.h b/day6/common.h
@@ -0,0 +1,17 @@
+#ifndef COMMON_H_
+#define COMMON_H_
+
+#include <assert.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <math.h>
+#include <reading.h>
+#include <stack_u64.h>
+
+void read_data(stack_u64 *times, stack_u64 *distances, char **lines,
+ size_t nlines);
+uint64_t counter(uint64_t t, uint64_t d);
+
+#endif
diff --git a/day6/exinput b/day6/exinput
@@ -0,0 +1,2 @@
+Time: 7 15 30
+Distance: 9 40 200
diff --git a/day6/input b/day6/input
@@ -0,0 +1,2 @@
+Time: 59 68 82 74
+Distance: 543 1020 1664 1022
diff --git a/day6/uppga.c b/day6/uppga.c
@@ -0,0 +1,22 @@
+#include "common.h"
+
+int main(int argc, char **argv) {
+ char **lines;
+ size_t nlines = readlines(&lines, "input");
+ size_t i;
+ uint64_t mul = 1;
+ stack_u64 times, distances;
+
+ stack_u64_init(×);
+ stack_u64_init(&distances);
+
+ read_data(×, &distances, lines, nlines);
+
+ for (i = 0; i < times.nmemb; i++)
+ mul *= counter(times.data[i], distances.data[i]);
+
+ stack_u64_clear(×);
+ stack_u64_clear(&distances);
+
+ printf("%llu\n", mul);
+}
diff --git a/day6/uppgb.c b/day6/uppgb.c
@@ -0,0 +1,28 @@
+#include "common.h"
+#include <math.h>
+
+static inline int is_digit(char x) { return '0' <= x && x <= '9'; }
+
+static inline uint64_t read_u64(char *str) {
+ char *cp = str;
+ uint64_t r = 0;
+
+ while (*cp != '\0') {
+ if (is_digit(*cp)) {
+ r = 10 * r + (uint64_t)(*cp - '0');
+ }
+ cp++;
+ }
+
+ return r;
+}
+
+int main(int argc, char **argv) {
+ char **lines;
+ uint64_t mul;
+ readlines(&lines, "input");
+
+ mul = counter(read_u64(lines[0]), read_u64(lines[1]));
+
+ printf("%llu\n", mul);
+}
diff --git a/day7/Makefile b/day7/Makefile
@@ -0,0 +1,30 @@
+CC=clang
+CFLAGS+=-std=c99 -pedantic -Wall -Werror -Wstrict-prototypes
+CFLAGS+=-Wmissing-prototypes -Wmissing-declarations -Wshadow
+CFLAGS+=-Wpointer-arith -Wcast-qual -Wsign-compare
+CFLAGS+=-O2 -g
+CFLAGS+=-fstack-protector-all -Wtype-limits -fno-common
+CFLAGS+=-fno-builtin
+CFLAGS+=-I/usr/local/include
+CFLAGS+=-I../utils
+#LDFLAGS=
+
+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) $(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)
+
+utils:
+ make -C ../utils
+
+clean:
+ rm -rf common.o uppga uppgb
diff --git a/day7/common.c b/day7/common.c
@@ -0,0 +1,56 @@
+#include "common.h"
+
+static inline size_t count_occ(uint8_t *cards, uint8_t val) {
+ size_t i;
+ size_t c = 0;
+
+ for (i = 0; i < 5; i++)
+ if (cards[i] == val)
+ c++;
+
+ return c;
+}
+
+static inline int has_occ(uint8_t *cards, size_t val) {
+ size_t i;
+ for (i = 0; i < 5; i++) {
+ if (count_occ(cards, cards[i]) >= val)
+ return 1;
+ }
+
+ return 0;
+}
+
+uint64_t hand_value(hand_t h) {
+ size_t i;
+ smallset s;
+ smallset_init(&s, 64);
+
+ for (i = 0; i < 5; i++) {
+ smallset_insert(&s, h.cards[i]);
+ }
+
+ size_t card = smallset_cardinality(&s);
+
+ smallset_clear(&s);
+
+ if (card == 1) {
+ return 7;
+ } else if (card == 2) {
+ if (has_occ(h.cards, 4)) {
+ return 6;
+ } else {
+ return 5;
+ }
+ } else if (card == 3) {
+ if (has_occ(h.cards, 3)) {
+ return 4;
+ } else {
+ return 3;
+ }
+ } else if (card == 4) {
+ return 2;
+ } else {
+ return 1;
+ }
+}
diff --git a/day7/common.h b/day7/common.h
@@ -0,0 +1,20 @@
+#ifndef COMMON_H_
+#define COMMON_H_
+
+#include <assert.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <reading.h>
+#include <smallset.h>
+
+typedef struct {
+ uint8_t cards[5];
+ uint64_t maxval;
+ uint64_t bid;
+} hand_t;
+
+uint64_t hand_value(hand_t h);
+
+#endif
diff --git a/day7/exinput b/day7/exinput
@@ -0,0 +1,5 @@
+32T3K 765
+T55J5 684
+KK677 28
+KTJJT 220
+QQQJA 483
diff --git a/day7/input b/day7/input
@@ -0,0 +1,1000 @@
+3A399 27
+46645 201
+8A9K4 40
+88333 578
+55353 817
+99Q99 146
+553J5 45
+AAQ2A 547
+TKQ2K 120
+57592 534
+7Q49K 229
+JK949 744
+688T6 657
+98888 392
+4K638 337
+J8888 96
+Q92KJ 778
+48J96 374
+955J6 307
+62TT6 896
+934AK 776
+44654 720
+AJAAA 568
+K6J5Q 162
+T29A4 342
+46342 467
+22227 694
+TQ4TT 468
+88688 728
+88999 183
+Q7T6J 463
+92T9J 884
+KAQQQ 299
+3275Q 913
+Q5535 82
+93A4J 48
+J9888 552
+2QTQ4 846
+44554 795
+JJJJJ 348
+TT477 733
+58883 460
+77377 317
+357J3 725
+T9J4Q 346
+88228 953
+Q4858 982
+5T5TT 405
+TTKTT 322
+QKKKK 197
+A5Q5A 956
+2T22A 962
+TQJTT 734
+84TAK 360
+T39Q7 375
+QJJTT 925
+62236 928
+474T7 302
+37KK3 411
+7J474 325
+55K5J 850
+TTJ2T 780
+Q5259 127
+93K6J 191
+T996T 333
+99929 193
+9JKK3 115
+2A647 409
+3AAAA 966
+85K58 464
+22893 607
+QJQJJ 471
+59T9T 690
+K8484 167
+TKKK2 526
+44243 273
+KQ888 792
+6J3K3 216
+44446 169
+325QK 461
+47T2T 990
+7J78J 410
+A7JJA 562
+2253J 598
+QK385 103
+65556 721
+TTQQ9 943
+Q4Q44 176
+JJ8JJ 539
+J799A 237
+994QK 510
+78996 458
+AK663 145
+QAA78 767
+2Q662 797
+A696A 572
+QA82J 975
+T7KJQ 126
+722JT 416
+2J222 57
+6Q937 719
+AKJ58 39
+QQJQJ 582
+AJATT 187
+Q484A 384
+T9T87 272
+5T7T3 699
+44K44 812
+44228 505
+983Q5 444
+55355 74
+J2JJ2 353
+TJ2T2 883
+Q96J9 708
+7KKKK 447
+557J5 280
+AT4T7 407
+AQ9JJ 73
+K6K2J 597
+K7Q7K 394
+QQ4JQ 635
+2JK35 269
+94934 78
+99K9K 235
+K7K27 91
+QQQTQ 588
+773A3 702
+26232 110
+AA44A 909
+33Q3Q 313
+83335 518
+7AA84 287
+484T4 662
+7JKK7 29
+9J999 38
+Q58T9 17
+29JQ7 355
+772TT 783
+JK66K 473
+TKKTK 433
+52T56 318
+8Q734 628
+K43J7 226
+AA569 77
+J4A54 988
+84J4J 500
+97TQ9 240
+4K554 305
+27999 847
+8QQ83 85
+57638 521
+K5KK9 974
+97K3Q 234
+T88TT 747
+22JAT 71
+TJ337 983
+TA3QK 555
+87686 372
+5KKKK 828
+QK868 168
+99J59 813
+AA28A 875
+47382 837
+27K77 46
+2KKKJ 10
+22292 448
+K4KKK 774
+A3A9K 428
+99222 184
+Q9Q4Q 336
+QQQQ4 631
+KJQTT 249
+T3K46 644
+929J9 165
+2KK22 527
+AKAA5 358
+Q2224 369
+T273J 265
+282JJ 28
+Q488Q 513
+38J88 633
+3T3T3 283
+88855 863
+6J39Q 75
+J44K4 543
+27272 731
+5576K 880
+JTTKT 400
+55J55 750
+2QQ99 919
+4668Q 55
+9A999 5
+JK294 536
+TJ937 692
+KKKKJ 86
+647J4 625
+94227 308
+6AJ5J 841
+99AA5 224
+685A7 24
+TAAKK 112
+286K4 762
+J5Q8A 232
+33323 494
+2A6Q3 495
+JQKT2 37
+AAAQA 978
+K34KJ 703
+7J74T 994
+2J828 723
+5T3T4 535
+48658 140
+J99JJ 954
+TT826 678
+KK3J8 840
+TTT6J 439
+7QQ6T 589
+58585 963
+TTT2A 190
+JQT52 261
+66J76 682
+925KQ 951
+T3223 141
+J78QJ 785
+QQ277 567
+4K6TK 349
+K888K 309
+2J664 713
+75657 218
+96J96 614
+23727 610
+89477 134
+T8456 957
+7K47A 230
+A3AA3 107
+24KK3 538
+65J48 119
+JA98K 647
+KKT6T 935
+A4AAK 248
+K7779 225
+J5574 438
+Q6QQQ 697
+39QTT 469
+K9J62 282
+2K242 971
+QJJK6 41
+49J77 122
+393KK 403
+Q222Q 789
+88Q8Q 587
+4Q8AA 247
+63396 211
+KKJJK 111
+JQ4K7 918
+79775 506
+T5T55 532
+8J558 125
+2QAK8 641
+59548 537
+345K6 106
+Q42K7 695
+88KKK 934
+4J8J6 519
+644JJ 612
+J796K 368
+3J633 621
+66T3A 707
+7Q3K3 768
+A258Q 866
+9463A 820
+58555 843
+36T4J 914
+96K4A 8
+Q34J7 654
+88QAA 651
+AA5J5 58
+73333 740
+JTT9T 609
+3QQQQ 871
+33957 442
+84888 446
+83Q83 742
+K2K3K 243
+JKJ94 377
+K62K2 385
+6QJ87 704
+847J7 61
+87J89 594
+77JQQ 54
+56KA5 56
+AAQQ9 233
+A8AKT 236
+37KKA 711
+J8279 244
+J2Q23 987
+666J6 939
+3JJ77 16
+QQQKQ 104
+96QQ4 398
+J38JA 585
+8QKQ8 899
+4TJK2 806
+66686 421
+5T4T5 889
+K4944 206
+65KQ6 443
+36366 59
+TJT36 996
+JAA3A 367
+4985K 395
+999QQ 926
+832J6 821
+88K7K 890
+J7777 902
+35855 991
+332KK 710
+76AT7 365
+533K3 65
+AAAA9 864
+45TT4 758
+TJJTT 418
+282TT 178
+T536K 474
+J5J3A 259
+Q3QAA 796
+222JJ 793
+Q4666 64
+93TT9 219
+69555 26
+449JA 238
+64935 754
+7K24K 622
+Q7999 932
+55474 288
+J5QQ5 929
+J794A 669
+44K4K 634
+8T6A5 808
+77252 7
+JA8Q4 70
+3JTKJ 181
+34433 845
+A3444 548
+84889 262
+4A9TQ 32
+85A88 189
+73883 321
+7T776 274
+K62QJ 138
+TQ7TQ 80
+6A7AA 786
+TA379 872
+25T33 584
+73747 965
+Q28KQ 1000
+2A222 144
+94993 345
+A9238 172
+8468T 630
+99646 649
+69KK7 210
+QK5K6 457
+6QJ6Q 12
+36339 643
+88A4J 63
+K57JK 549
+77888 382
+T4J56 198
+AQQA7 481
+644K2 492
+T46AA 397
+5J3TJ 861
+J7J79 20
+3333A 42
+QQ555 892
+3AJT5 36
+J4K8A 208
+874TJ 376
+J999J 215
+A8AK3 782
+84444 504
+TT2TT 905
+8746J 752
+AA5A5 449
+A75JT 204
+55595 379
+KK665 775
+22244 364
+22283 152
+AA25A 149
+AA3KA 826
+K399K 981
+93384 97
+46494 347
+3TQJ4 19
+KKK7Q 158
+776J2 267
+7A77J 486
+A4454 9
+6857K 858
+3J3TT 435
+339J3 99
+JAQJQ 105
+82367 571
+3QQ3Q 556
+QJTJQ 599
+696T3 334
+JKA22 829
+J6686 576
+92Q4J 217
+8288K 289
+7JJKA 904
+33383 613
+J339T 315
+88483 503
+9995A 319
+8K92J 483
+TJ244 266
+KJ957 574
+74A44 148
+77KK7 591
+QJQ75 898
+88J8J 885
+92K54 137
+64647 579
+66226 560
+JJ488 839
+43J42 673
+3K3K3 849
+99977 108
+JTT47 113
+2634T 68
+TJQT5 838
+77Q77 763
+2AAKA 972
+78QJ7 257
+6J923 544
+2J2KK 164
+259K3 882
+88K78 602
+4786Q 924
+42444 650
+8536T 52
+AQTT5 546
+3333J 581
+3K984 501
+A8832 685
+34J55 133
+62985 700
+4353J 386
+44454 23
+77772 116
+65665 679
+KKK7J 124
+A7578 749
+5AQ54 396
+7KK8Q 807
+7T7T8 911
+73JJT 157
+98A99 753
+446J4 477
+4T43A 205
+TT999 798
+88885 915
+9Q64J 659
+7767K 357
+A5329 559
+85KKK 739
+9969J 714
+QJQQ9 427
+KT4KT 15
+5T5J5 638
+J74AJ 736
+56666 524
+5T558 930
+2233A 350
+7AA4A 502
+QAAA7 595
+7737T 151
+JQ4Q6 677
+67864 691
+2KK3Q 117
+8272K 414
+75J57 159
+443J4 479
+55KK5 207
+K88TK 910
+3Q9J9 332
+JAJAJ 338
+69369 339
+82KJ6 335
+K39KK 773
+99492 422
+3T663 270
+T5958 328
+9A45K 715
+23593 922
+JKK37 765
+KJKT7 769
+Q74QQ 173
+6232T 729
+227Q2 436
+7AQK4 430
+8Q4JQ 509
+J8248 297
+TT779 306
+A3K34 852
+97228 832
+TJTJ7 300
+A8898 553
+82TJQ 4
+92738 131
+AAAJJ 440
+TT972 51
+69AQK 646
+QQ7QJ 705
+4JK85 718
+7Q63T 220
+44A24 737
+7QAQT 292
+66699 979
+3Q974 329
+TTT6T 648
+85288 686
+989QT 278
+7Q6AK 964
+66466 251
+99744 271
+TTQTQ 163
+3433T 177
+K2333 142
+QQ4Q4 938
+9Q6Q9 787
+47T63 831
+2J56T 493
+94494 72
+25552 869
+936K2 390
+A8AA8 605
+3TT35 727
+2A24T 129
+94999 323
+64A2J 824
+K7676 756
+QQQQ7 18
+882J8 748
+2J77A 611
+222TJ 959
+T6266 722
+823J3 627
+8T569 771
+58KK3 331
+59329 209
+K9K87 6
+82484 150
+9444A 98
+TQ445 487
+J999K 462
+JT4TT 246
+5A455 640
+67KAJ 687
+6A83J 570
+36J6J 90
+6AK6A 573
+88K88 781
+5A3K4 931
+22J27 499
+44T44 948
+K44TT 213
+554K5 927
+6528A 202
+999JT 667
+7J256 401
+A2272 937
+2QJ3Q 900
+63736 973
+32522 933
+T666T 664
+88992 706
+JK267 603
+QQ99Q 316
+AKKKK 507
+8688J 862
+48858 970
+66229 378
+K495Q 14
+79539 761
+A33K3 491
+QAQQQ 417
+T92JA 620
+AQQ8J 475
+64A4K 295
+4A824 231
+8KTK3 453
+229K5 969
+Q3Q53 284
+Q6K34 35
+QJQ8Q 402
+39922 69
+J9TK8 920
+4Q3K8 881
+454AA 999
+556Q9 531
+22K22 496
+6AA39 291
+792K3 810
+TQQTJ 660
+J677K 764
+QTTTT 998
+22223 529
+3333Q 842
+2AAJA 755
+J64K6 466
+TJA4T 693
+J2622 441
+42442 566
+754K8 459
+35826 976
+4743T 676
+693TA 672
+58887 391
+K4899 434
+TTTT3 88
+356T2 894
+77784 212
+3373T 399
+78777 895
+Q97TT 950
+88T8T 760
+J48K2 663
+J3A3A 424
+555T5 25
+37373 389
+J6J46 174
+4TAKT 171
+6TKQ7 624
+5A775 3
+TT3T3 326
+28558 489
+TJ38T 936
+6AK66 254
+44664 223
+77QQ7 87
+Q2829 675
+5TTJ5 995
+T2T9J 454
+7878A 264
+83843 84
+JKKK3 802
+98436 192
+3AA22 940
+555A5 136
+J333J 221
+97KJ3 636
+JK582 801
+5Q82K 515
+25J2T 180
+34234 746
+JQ4K9 255
+224J2 668
+68999 639
+7T77T 886
+6A92Q 629
+JJ55J 161
+99599 429
+6JQ3Q 43
+4699A 361
+75AT2 917
+T9TTT 514
+55A95 551
+J6A96 47
+AAJAT 617
+64669 222
+QQ9QQ 626
+44J44 688
+Q3355 92
+J8J8J 835
+T4382 363
+J359A 296
+49Q49 653
+AAT66 908
+44T72 961
+AKA44 901
+49994 290
+A344A 732
+JJQJK 777
+J8JQ8 819
+A89T9 565
+72A72 868
+K7867 153
+K6663 179
+K76K7 854
+9T265 419
+9K7K9 865
+7797J 426
+25KKJ 670
+75575 11
+75955 431
+TK99Q 684
+KJ273 76
+57525 285
+J3AAJ 263
+Q7QQT 590
+Q77AQ 879
+33626 423
+AAA77 139
+76584 730
+2K9QQ 356
+22225 857
+44KKK 656
+954K6 814
+79TA5 135
+KQKKJ 62
+5QQ88 311
+77K87 452
+ATTTT 370
+J64QA 815
+29399 985
+2T792 351
+5782A 324
+57T74 294
+TQJ53 182
+42222 645
+K4Q92 320
+77A7K 583
+AA999 977
+T77TK 279
+5T586 799
+6K67Q 301
+6J8J2 67
+99JJT 344
+A395K 540
+35AAA 779
+68QT3 557
+45T3K 175
+587Q2 717
+8QK39 616
+73574 550
+T8A36 986
+333AA 800
+2KKKK 393
+9Q6T9 250
+A88A8 203
+J4J44 194
+848J8 281
+5A49Q 44
+8J88A 406
+8JTTT 877
+77767 955
+22K46 199
+6A9AT 387
+T5Q7K 482
+52999 577
+Q6685 632
+TQJQQ 525
+77477 712
+K5656 601
+KKA7A 380
+AA66A 373
+83ATT 942
+3JJ9K 508
+89988 791
+TQ746 757
+8J99T 743
+KKK22 642
+J44K2 980
+K9KAA 830
+9AAA9 260
+558J5 870
+KQKK2 352
+JT4T4 498
+K647T 967
+9K364 569
+44833 844
+T2922 856
+T3463 276
+2TTT2 60
+Q542A 724
+7J724 992
+KT92K 286
+8K388 888
+4394Q 600
+Q747Q 818
+433J4 945
+66J45 381
+55J59 912
+9A5A5 606
+3K98A 195
+9J49A 523
+2642J 944
+9K8Q7 89
+3J335 241
+J639J 564
+63J79 383
+5Q4J7 455
+777T7 674
+6793A 166
+KK9KK 277
+4TA95 873
+KQJA9 81
+2T777 834
+4K44A 109
+93572 312
+33537 258
+756KQ 304
+4J449 770
+27JKQ 412
+KK8KK 596
+J9666 415
+34943 93
+85J6K 404
+J6QJ5 118
+4A452 343
+7548A 327
+6644J 472
+T3A7Q 887
+T3J3J 661
+QQ79Q 516
+73JAT 592
+2QQQJ 413
+QJ523 541
+82878 488
+722T2 256
+4KA4K 923
+96T99 490
+3AKK6 696
+6J6JJ 147
+922JA 593
+J88K6 371
+52245 867
+84664 637
+T2T22 853
+T26A9 952
+8686J 253
+J6AA3 53
+6A65A 701
+JAJTA 745
+3843A 859
+39399 114
+J28Q3 121
+98KT4 13
+TTQTA 772
+39KTT 683
+53J53 298
+47434 671
+4J33Q 542
+9Q9J9 214
+TTTT8 984
+A45K7 891
+K488K 916
+AJ636 997
+7QQQ7 563
+68877 359
+655QQ 790
+3AA4A 855
+T4TTT 958
+9246Q 666
+85K48 485
+AJ283 484
+54J5K 21
+KK9K9 2
+Q69Q3 22
+J4555 809
+J322J 921
+752J5 530
+6K43K 480
+6AAAA 836
+92A29 803
+66888 665
+25529 83
+2AJ22 558
+89999 476
+Q8777 155
+7787J 388
+Q2765 123
+TJ2TK 833
+55AA5 903
+22662 33
+7QQQ2 575
+7J77J 561
+72878 874
+QQJQQ 154
+T693Q 520
+5TT3T 31
+JQQ44 340
+2JJ2Q 804
+J24T2 784
+K7J3J 811
+7KTJT 156
+8848Q 228
+44944 947
+K5426 893
+A55A8 655
+AAKK8 619
+75555 751
+Q2222 816
+TJJ9J 906
+J4224 314
+26A7K 738
+97J54 1
+7KK7K 794
+3KKK5 451
+955K9 827
+Q9QA2 293
+J2A28 200
+J2K77 341
+83888 196
+J97K7 823
+75TJ9 186
+J7638 49
+46K36 128
+92JJJ 735
+29A87 185
+89449 100
+3KAJK 445
+QQ343 586
+8466J 79
+T3T37 362
+252T4 528
+A3A5J 242
+6QQQT 822
+7AJA6 615
+K9625 268
+KK3AK 517
+5Q5Q8 658
+T87K3 618
+57629 788
+A7A7Q 160
+889TQ 741
+TT59T 425
+Q2KQJ 30
+A4K3K 143
+6664K 456
+KK4J4 726
+TTTTJ 437
+QT824 132
+J555J 478
+75KK9 354
+94979 34
+K846J 432
+QQ887 130
+TT97T 170
+66TQ6 878
+57K78 993
+88JK8 608
+AK5Q3 907
+AATAA 989
+QJQ8J 533
+8QQQQ 522
+5JQ49 102
+T3T65 188
+66446 759
+3Q695 275
+AAQTA 689
+43J33 623
+TJ444 968
+Q28Q2 330
+J777T 450
+QT3JQ 420
+T327A 897
+QKQKK 580
+92KA7 946
+7A93K 497
+6KAAA 239
+889TA 50
+K5KK5 511
+J443J 303
+TTT7J 310
+QAK8A 252
+J8658 805
+896K6 680
+88482 876
+69QJQ 408
+4A3J2 941
+8868T 94
+7766Q 851
+62J25 825
+3TT9T 716
+Q5KKK 860
+K7488 95
+33343 766
+JT888 366
+J8885 681
+J66J6 554
+JA65K 604
+QTJ44 848
+583QJ 465
+89Q79 66
+27477 512
+JTK33 101
+TTTQK 652
+A4ATA 545
+J3A33 470
+34QAK 245
+6Q668 698
+66777 709
+5K557 227
+43666 949
+66A6A 960
diff --git a/day7/uppga.c b/day7/uppga.c
@@ -0,0 +1,78 @@
+#include "common.h"
+
+int cmp(const void *a, const void *b);
+
+int cmp(const void *a, const void *b) {
+ size_t i;
+
+ hand_t ha = *(const hand_t *)a;
+ hand_t hb = *(const hand_t *)b;
+
+ uint64_t ha_val = hand_value(ha);
+ uint64_t hb_val = hand_value(hb);
+
+ if (ha_val != hb_val) {
+ if (ha_val < hb_val)
+ return -1;
+ else
+ return 1;
+ } else {
+ for (i = 0; i < 5; i++) {
+ if (ha.cards[i] != hb.cards[i]) {
+ if (ha.cards[i] < hb.cards[i])
+ return -1;
+ else
+ return 1;
+ }
+ }
+ }
+
+ return 0;
+}
+
+static inline uint8_t char_to_card(const char c) {
+ if ('2' <= c && c <= '9')
+ return (uint8_t)(c - '0');
+ switch (c) {
+ case 'T':
+ return 10;
+ case 'J':
+ return 11;
+ case 'Q':
+ return 12;
+ case 'K':
+ return 13;
+ case 'A':
+ return 14;
+ default:
+ exit(1);
+ }
+}
+
+static inline void read_hands(hand_t *h, char **lines, const size_t nlines) {
+ size_t i, j;
+
+ for (i = 0; i < nlines; i++) {
+ for (j = 0; j < 5; j++)
+ h[i].cards[j] = char_to_card(lines[i][j]);
+ sread_next_u64(&(h[i].bid), &lines[i][6]);
+ }
+}
+
+int main(int argc, char **argv) {
+ char **lines;
+ size_t nlines = readlines(&lines, "input");
+
+ hand_t h[nlines];
+ read_hands(h, lines, nlines);
+
+ qsort(h, nlines, sizeof(h[0]), cmp);
+
+ uint64_t m;
+ uint64_t sum = 0;
+ for (m = 0; m < nlines; m++) {
+ sum += (m + 1) * h[m].bid;
+ }
+
+ printf("%llu\n", sum);
+}
diff --git a/day7/uppgb.c b/day7/uppgb.c
@@ -0,0 +1,130 @@
+#include "common.h"
+
+int cmp(const void *a, const void *b);
+
+int cmp(const void *a, const void *b) {
+ size_t i;
+
+ hand_t ha = *(const hand_t *)a;
+ hand_t hb = *(const hand_t *)b;
+
+ uint64_t ha_val = ha.maxval;
+ uint64_t hb_val = hb.maxval;
+
+ if (ha_val != hb_val) {
+ if (ha_val < hb_val)
+ return -1;
+ else
+ return 1;
+ } else {
+ for (i = 0; i < 5; i++) {
+ if (ha.cards[i] != hb.cards[i]) {
+ if (ha.cards[i] < hb.cards[i])
+ return -1;
+ else
+ return 1;
+ }
+ }
+ }
+
+ return 0;
+}
+
+static inline uint8_t char_to_card(const char c) {
+ if ('2' <= c && c <= '9')
+ return (uint8_t)(c - '0');
+ switch (c) {
+ case 'T':
+ return 10;
+ case 'J':
+ return 1;
+ case 'Q':
+ return 12;
+ case 'K':
+ return 13;
+ case 'A':
+ return 14;
+ default:
+ exit(1);
+ }
+}
+
+static inline int all_jokers_are_aces(hand_t *t, hand_t *h) {
+ size_t i;
+
+ for (i = 0; i < 5; i++) {
+ if (h->cards[i] == 1 && t->cards[i] != 14)
+ return 0;
+ }
+
+ return 1;
+}
+
+static inline void increment_jokers(hand_t *t, hand_t *h) {
+ size_t i;
+
+ for (i = 0; i < 5; i++) {
+ if (h->cards[i] == 1) {
+ if (t->cards[i] != 14) {
+ t->cards[i]++;
+ return;
+ } else {
+ t->cards[i] = 2;
+ }
+ }
+ }
+}
+
+static inline uint64_t find_max_val(hand_t h) {
+ uint64_t maxval = 0;
+ uint64_t tmpval;
+ hand_t t = h;
+
+ size_t i;
+ for (i = 0; i < 5; i++) {
+ if (t.cards[i] == 1)
+ t.cards[i] = 2;
+ }
+
+ while (!all_jokers_are_aces(&t, &h)) {
+ tmpval = hand_value(t);
+ if (tmpval > maxval)
+ maxval = tmpval;
+ increment_jokers(&t, &h);
+ }
+
+ tmpval = hand_value(t);
+ if (tmpval > maxval)
+ maxval = tmpval;
+
+ return maxval;
+}
+
+static inline void read_hands(hand_t *h, char **lines, const size_t nlines) {
+ size_t i, j;
+
+ for (i = 0; i < nlines; i++) {
+ for (j = 0; j < 5; j++)
+ h[i].cards[j] = char_to_card(lines[i][j]);
+ sread_next_u64(&(h[i].bid), &lines[i][6]);
+ h[i].maxval = find_max_val(h[i]);
+ }
+}
+
+int main(int argc, char **argv) {
+ char **lines;
+ size_t nlines = readlines(&lines, "input");
+
+ hand_t h[nlines];
+ read_hands(h, lines, nlines);
+
+ qsort(h, nlines, sizeof(h[0]), cmp);
+
+ uint64_t m;
+ uint64_t sum = 0;
+ for (m = 0; m < nlines; m++) {
+ sum += (m + 1) * h[m].bid;
+ }
+
+ printf("%llu\n", sum);
+}
diff --git a/day8/Makefile b/day8/Makefile
@@ -0,0 +1,30 @@
+CC=clang
+CFLAGS+=-std=c99 -pedantic -Wall -Werror -Wstrict-prototypes
+CFLAGS+=-Wmissing-prototypes -Wmissing-declarations -Wshadow
+CFLAGS+=-Wpointer-arith -Wcast-qual -Wsign-compare
+CFLAGS+=-O2 -g
+CFLAGS+=-fstack-protector-all -Wtype-limits -fno-common
+CFLAGS+=-fno-builtin
+CFLAGS+=-I/usr/local/include
+CFLAGS+=-I../utils
+LDFLAGS=-L/usr/local/lib -lgmp
+
+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) $(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) $(LDFLAGS)
+
+utils:
+ make -C ../utils
+
+clean:
+ rm -rf common.o uppga uppgb
diff --git a/day8/common.c b/day8/common.c
@@ -0,0 +1,20 @@
+#include "common.h"
+
+uint64_t chrs_to_node(char *s) {
+ return (((uint64_t)s[0] - 'A') * 26 * 26) + (((uint64_t)s[1] - 'A') * 26) +
+ ((uint64_t)s[2] - 'A');
+}
+
+void read_graph(uint64_t *lefts, uint64_t *rights, char **lines,
+ size_t nlines) {
+ size_t i;
+ size_t n, l, r;
+
+ for (i = 2; i < nlines; i++) {
+ n = chrs_to_node(lines[i]);
+ l = chrs_to_node(&lines[i][7]);
+ r = chrs_to_node(&lines[i][12]);
+ lefts[n] = l;
+ rights[n] = r;
+ }
+}
diff --git a/day8/common.h b/day8/common.h
@@ -0,0 +1,19 @@
+#ifndef COMMON_H_
+#define COMMON_H_
+
+#include <assert.h>
+#include <gmp.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <reading.h>
+#include <stack_u64.h>
+
+#define ZZZ 17575
+#define AAA 0
+
+uint64_t chrs_to_node(char *s);
+void read_graph(uint64_t *lefts, uint64_t *rights, char **lines, size_t nlines);
+
+#endif
diff --git a/day8/input b/day8/input
@@ -0,0 +1,736 @@
+LRLRRRLRRLRRRLRRRLLLLLRRRLRLRRLRLRLRRLRRLRRRLRLRLRRLLRLRRLRRLRRLRRRLLRRRLRRRLRRLRLLLRRLRRRLRLRRLRRRLRRLRLLLRRRLRRLRRLRRRLRRRLRRRLRLRLRLRRRLRRRLLLRRLLRRRLRLRLRRRLRRRLRRLRRRLRLRLLRRRLRLRRLRLRLRRLLLRRRLRRRLRRLRRLRLRRLLRRLRRRLRRRLLRRRLRRLRLLRRLRLRRLLRRRLLLLRRLRRRLRLRRLLRLLRRRLLRRLLRRRLRRRLRRLLRLRLLRRLLRLLLRRRR
+
+FCG = (PLG, GXC)
+PQT = (SQK, GHP)
+NVS = (TPQ, PPB)
+CTR = (SXS, KCV)
+FNM = (KHG, FLD)
+TFH = (CLD, CLD)
+MLQ = (QQL, JVK)
+LQR = (TFH, RRM)
+QKX = (VPR, BHD)
+QQL = (VBD, CPM)
+QST = (HPC, DFJ)
+QBX = (HPH, BTM)
+TVB = (SHJ, GMF)
+HJN = (CGJ, QXT)
+PGV = (RXT, DQP)
+TPN = (TQR, LJR)
+BHV = (TGL, GJH)
+DDF = (XLH, TDQ)
+XMK = (XVN, RJP)
+HXH = (JVM, CVB)
+SFX = (VNH, BFS)
+TRF = (HVJ, DKF)
+GGQ = (NNP, PBL)
+KQX = (VXK, FSF)
+KGL = (QSJ, CBM)
+CLC = (MCJ, JGQ)
+GFF = (JBG, TVR)
+FQT = (CMR, CKG)
+HVJ = (FXB, GBP)
+KTF = (PKG, JCL)
+BLF = (QQL, JVK)
+TVN = (QNN, DPQ)
+KVX = (XNV, CJF)
+GDK = (DVX, RKS)
+CHS = (VCL, PSG)
+LFS = (SNS, NTG)
+NCR = (LFV, DRN)
+NLJ = (RCR, XCF)
+SRD = (LGT, PRS)
+FQC = (GBX, RGQ)
+SJH = (CKG, CMR)
+BQP = (PPP, HGT)
+LJR = (FPV, FQD)
+XTP = (PDT, MTX)
+RDG = (JRL, MFF)
+TFF = (MJQ, MVB)
+NGS = (BDG, KHS)
+GXT = (QSJ, CBM)
+VVD = (HJJ, RNK)
+FRL = (CHS, JNV)
+RQS = (CFM, SKM)
+PRS = (VTG, PRR)
+FCD = (VTN, DJQ)
+PDT = (DST, DST)
+MND = (MFV, GDR)
+GJG = (TMJ, HPJ)
+JSL = (DDN, JPZ)
+DNX = (RHD, LKM)
+BGM = (GFC, JTD)
+BPC = (BMN, BKQ)
+PPB = (BFT, PVH)
+VRK = (TCL, JDS)
+MBT = (CBB, JMM)
+JGQ = (GGQ, DFH)
+BGP = (MGH, VHG)
+GGR = (TCX, QLG)
+NCD = (XDT, SSK)
+TDQ = (VPK, HCF)
+PND = (BKV, THD)
+RJP = (KRV, FQN)
+MFZ = (MRL, MFK)
+TCM = (RMM, CLB)
+SDF = (LTS, RVQ)
+KGS = (CTR, SJQ)
+SFK = (SDF, HPF)
+DJC = (MKF, PNR)
+DPF = (KBH, QQX)
+VQJ = (FVB, XPK)
+CGX = (MLQ, BLF)
+GBS = (DJC, XXQ)
+JSV = (RMR, QFK)
+KHS = (HSQ, PTD)
+MKG = (NLJ, MHQ)
+CXQ = (BDG, KHS)
+RRQ = (FCT, CDT)
+JSK = (LBC, CPT)
+VSM = (RGM, VMR)
+NNP = (SRD, VNQ)
+PRR = (GMX, KQX)
+HNP = (GQJ, DGS)
+PKB = (KBL, HXJ)
+MFS = (RMK, JBX)
+RMM = (MFG, BPS)
+PJM = (SFK, HLG)
+BCH = (SRK, LSG)
+VNQ = (LGT, PRS)
+LTC = (TJX, DQD)
+CKG = (NJG, GMJ)
+RPS = (RXT, DQP)
+CCV = (DPB, JQT)
+JDF = (CFF, XFB)
+LQX = (KBD, TVD)
+VLL = (FMK, LCD)
+RTB = (NTG, SNS)
+FBF = (QTH, QFV)
+CBB = (VJK, BHB)
+BCL = (LJR, TQR)
+JDS = (SPS, HRL)
+HHB = (RHD, LKM)
+PLG = (RBV, NJD)
+RNB = (VMR, RGM)
+CJT = (HJJ, RNK)
+JVK = (VBD, CPM)
+HXJ = (JTL, PFD)
+JGX = (XMV, RHF)
+FGT = (LFR, JSK)
+MJQ = (BVP, BXM)
+DFJ = (MRS, LTC)
+GNG = (DPB, JQT)
+VCA = (XFL, JSV)
+KLR = (LTN, BXH)
+VGN = (DGS, GQJ)
+DVX = (JXX, XSH)
+BTN = (PFP, FRL)
+DTM = (DVD, FCF)
+SVN = (PBF, GXR)
+RCC = (BTB, CBD)
+GMJ = (FCH, CSP)
+DVS = (FSV, TVP)
+RLG = (QML, XGD)
+CVV = (HHB, DNX)
+NRG = (NFG, DNL)
+PQC = (RNG, KTF)
+KGG = (DMD, HQG)
+JNV = (PSG, VCL)
+SNS = (CGX, MBK)
+FRA = (MFK, MRL)
+BPN = (QQX, KBH)
+HCQ = (XMK, JDV)
+RDD = (JGB, VHQ)
+HTF = (VLX, RQV)
+XFH = (DPH, RGG)
+LBC = (JTV, DTK)
+RBP = (LLL, MND)
+GDV = (SHJ, GMF)
+MJV = (JGV, JGV)
+BQR = (FPK, HSS)
+XDT = (BTN, FXF)
+NGM = (NTF, BDN)
+HPP = (FQX, FGT)
+JPC = (JHC, PPH)
+GCV = (CCS, TCM)
+VHQ = (PBR, GVP)
+MDD = (GGR, LXC)
+HSQ = (CKV, KGS)
+PPP = (DLP, HPP)
+SNA = (BKK, FNM)
+VLS = (DPH, RGG)
+JGB = (PBR, GVP)
+FPK = (RGS, XKQ)
+LVB = (XMC, MNX)
+FDP = (PFR, GFP)
+NKS = (PCH, TJR)
+VLX = (TLH, KFD)
+DLT = (HGV, XJR)
+MBK = (MLQ, BLF)
+RNG = (PKG, PKG)
+BKV = (DXB, GDQ)
+LLL = (GDR, MFV)
+LNN = (MVG, CKJ)
+FXH = (TCM, CCS)
+TPQ = (BFT, PVH)
+MRH = (CJR, TFF)
+MVG = (BQP, DXC)
+LLN = (VTN, DJQ)
+MLS = (THD, BKV)
+HFR = (HNP, VGN)
+XNF = (PVL, TPD)
+JQT = (DVS, PST)
+LNH = (FHQ, SPG)
+MBR = (LQR, VPM)
+KNV = (SKG, CKF)
+JCV = (XMV, RHF)
+JQJ = (TCQ, BGM)
+SQF = (NRG, HDK)
+FHF = (NNQ, PKB)
+BDG = (HSQ, PTD)
+PBT = (JRL, MFF)
+LNS = (TCQ, BGM)
+PTD = (CKV, KGS)
+LHX = (GRM, XJQ)
+NXN = (SFX, NQC)
+VSZ = (XFS, DHL)
+DPG = (JTS, VBG)
+QTH = (DLT, JNS)
+PMG = (TCL, JDS)
+CCD = (FCG, GPJ)
+SSP = (HTF, MNV)
+STX = (HPC, DFJ)
+KSR = (GKB, TSX)
+KDP = (XGR, LLK)
+NNQ = (HXJ, KBL)
+TPM = (PDT, PDT)
+SJQ = (KCV, SXS)
+PJH = (BPN, DPF)
+JBG = (FPN, XBP)
+XQQ = (TLR, TLR)
+XJL = (FTX, DXR)
+RXT = (RMD, KVX)
+CLD = (NTK, NTK)
+SDM = (MRH, TGC)
+RQV = (TLH, KFD)
+NDL = (VDT, VDT)
+CCT = (QFV, QTH)
+LXL = (VGH, FRM)
+TJR = (KGL, GXT)
+VBD = (RSG, NCR)
+XBG = (BHV, NPX)
+JTS = (QDH, CST)
+BFT = (JDF, MXT)
+XLH = (HCF, VPK)
+XBP = (GCV, FXH)
+JPF = (RNG, KTF)
+HHN = (TMJ, HPJ)
+FSV = (GMC, HJN)
+XFB = (JRN, RDD)
+JPZ = (FNM, BKK)
+BBP = (KDP, KKM)
+TGL = (TGX, XRF)
+JCL = (JDT, JDP)
+RRS = (XPK, FVB)
+NSB = (MCJ, JGQ)
+DMD = (GFG, FDP)
+FFX = (VBG, JTS)
+XRF = (XFH, VLS)
+LSG = (MFX, CVC)
+BJZ = (FNK, QKX)
+DLP = (FGT, FQX)
+JDV = (RJP, XVN)
+HDK = (DNL, NFG)
+GQP = (NQC, SFX)
+NFG = (PMG, VRK)
+CSP = (GDP, NDV)
+BKK = (FLD, KHG)
+SCK = (KKM, KDP)
+DXR = (SCK, BBP)
+JVG = (PBT, RDG)
+GSV = (QTK, JNT)
+QXT = (BPC, NXQ)
+GDQ = (LFJ, KSF)
+NHG = (VVD, CJT)
+DHL = (LNH, RPP)
+NFS = (JGV, MFZ)
+FCS = (BTB, CBD)
+JGH = (VHP, RMG)
+VQC = (GDC, VKQ)
+PCH = (KGL, GXT)
+LGT = (PRR, VTG)
+PFV = (QCC, VSZ)
+QQX = (FTV, LBD)
+QFV = (JNS, DLT)
+SCN = (RVX, RBP)
+QRH = (BCL, TPN)
+GBX = (VRH, CPG)
+NTF = (RBK, RRN)
+NDQ = (MBR, RDL)
+KCP = (GFF, DDG)
+JBX = (JPF, PQC)
+GMF = (KLR, VTD)
+JVM = (TXL, XTR)
+BLC = (MNJ, VFF)
+VTH = (TGC, MRH)
+JHB = (BPN, DPF)
+TMJ = (PND, MLS)
+PFH = (HSS, FPK)
+TDG = (KJV, QTR)
+TGC = (TFF, CJR)
+TVD = (CCT, FBF)
+TKX = (FCT, CDT)
+BKS = (HLG, SFK)
+CGJ = (NXQ, BPC)
+QHN = (SKG, CKF)
+CVJ = (DMD, HQG)
+BMN = (JLD, NHG)
+GRP = (NDL, NDL)
+FTX = (BBP, SCK)
+DXC = (PPP, HGT)
+NJD = (XSP, KSC)
+CST = (RRQ, TKX)
+SVH = (JHC, PPH)
+JTV = (GCM, RLG)
+BXJ = (DVD, FCF)
+HCV = (XDT, SSK)
+RDL = (LQR, VPM)
+PSG = (MFS, MFC)
+MVQ = (DRH, QBX)
+XCF = (FVM, VVS)
+DXB = (KSF, LFJ)
+GHN = (JGH, FGR)
+KLJ = (LSL, QJJ)
+DFH = (NNP, PBL)
+CDL = (XBG, FGD)
+VFF = (KGR, FCJ)
+KBD = (FBF, CCT)
+NJL = (JGH, FGR)
+VHG = (MBT, XPT)
+GKB = (GJB, JKK)
+KQP = (CXQ, NGS)
+VSX = (GDC, VKQ)
+RHX = (CDL, RGD)
+NTK = (QCC, QCC)
+KFD = (SKK, HGC)
+ZZZ = (VFF, MNJ)
+JLK = (HPL, MDF)
+BTB = (PFT, CCD)
+HQG = (GFG, FDP)
+FVM = (VHC, NGC)
+CVD = (NQP, FXM)
+VGH = (CCV, GNG)
+LSV = (NLJ, MHQ)
+PVX = (KGG, CVJ)
+THL = (NJL, GHN)
+KKM = (XGR, LLK)
+XGR = (LRT, DFP)
+RRN = (TPM, XTP)
+GBP = (GTD, QSL)
+KJV = (MDD, QKK)
+TBN = (TLV, JLK)
+LDG = (TPN, BCL)
+JLD = (CJT, VVD)
+DKN = (CXQ, NGS)
+DGV = (HCV, NCD)
+HRL = (QHN, KNV)
+RRM = (CLD, TQC)
+RJS = (MGH, VHG)
+MFF = (QTV, GJF)
+PNR = (BTT, TVN)
+JKK = (RVV, XPG)
+XKQ = (PQT, FJD)
+RMK = (JPF, PQC)
+LCD = (RJS, BGP)
+QTK = (GJG, HHN)
+TBK = (CVB, JVM)
+VTG = (GMX, KQX)
+GFG = (PFR, GFP)
+RSG = (LFV, LFV)
+VCS = (PCH, TJR)
+LJC = (QXF, XQR)
+QHD = (XFM, LQM)
+TSD = (PPB, TPQ)
+RHP = (MXX, MTC)
+GLZ = (JSV, XFL)
+NXD = (VQJ, RRS)
+MTJ = (QJJ, LSL)
+XQH = (NQP, FXM)
+GLK = (XCX, NDQ)
+LSL = (NVS, TSD)
+QGC = (LHX, LHT)
+RHF = (GHM, TBT)
+TQR = (FQD, FPV)
+QSC = (XCX, NDQ)
+RKS = (JXX, XSH)
+HGC = (DCG, GDD)
+XNV = (VQG, PVR)
+CCS = (RMM, CLB)
+RVR = (SJH, FQT)
+JCM = (BKS, PJM)
+GHM = (FCS, RCC)
+PFT = (FCG, GPJ)
+XDJ = (DTS, JVG)
+RVQ = (FQC, PLV)
+LQM = (RMH, XDJ)
+CKV = (SJQ, CTR)
+HPH = (TLX, RQG)
+MTC = (FFX, DPG)
+CKJ = (BQP, DXC)
+MXT = (CFF, XFB)
+VHT = (MQG, GTH)
+QJJ = (TSD, NVS)
+HNA = (DHL, XFS)
+PVS = (TDG, SLR)
+FPV = (GMD, GTK)
+DDG = (TVR, JBG)
+BHD = (LLN, FCD)
+LDF = (NNQ, PKB)
+CKF = (XXD, MJL)
+TJF = (NRG, HDK)
+JDT = (BLC, BLC)
+GXR = (MGP, FNX)
+BPS = (XNF, MXR)
+FXB = (QSL, GTD)
+TLH = (HGC, SKK)
+PKV = (NCD, HCV)
+CBM = (NXD, GTR)
+JNT = (GJG, HHN)
+TCQ = (JTD, GFC)
+MRS = (TJX, DQD)
+FBP = (VGN, HNP)
+HPC = (MRS, LTC)
+TJX = (PKV, DGV)
+LFV = (MJV, MJV)
+XVM = (SQF, TJF)
+VVF = (PGV, RPS)
+XPG = (DGF, DJK)
+RGD = (XBG, FGD)
+GMC = (QXT, CGJ)
+CFM = (VVF, QPN)
+SPS = (QHN, KNV)
+JTL = (MNM, PTS)
+MNM = (SXH, BDT)
+RGG = (LNS, JQJ)
+FPN = (GCV, FXH)
+XJR = (KCP, HJS)
+FQN = (LQX, MVF)
+CFF = (JRN, RDD)
+KSC = (QGH, LPG)
+BHB = (DMR, JTX)
+TBT = (RCC, FCS)
+SKM = (VVF, QPN)
+PVR = (PVS, PQQ)
+QDN = (XMK, JDV)
+JXX = (STX, QST)
+TXL = (LKK, NSD)
+XTR = (NSD, LKK)
+VKQ = (HXH, TBK)
+FQX = (JSK, LFR)
+FRM = (CCV, GNG)
+AAA = (MNJ, VFF)
+BKQ = (NHG, JLD)
+DPQ = (MGT, LXL)
+KXL = (VQC, VSX)
+RVV = (DGF, DGF)
+TQC = (NTK, PFV)
+NPX = (GJH, TGL)
+MGH = (XPT, MBT)
+VMR = (HGG, RHX)
+DCG = (CLF, GBS)
+CVB = (TXL, XTR)
+HPJ = (MLS, PND)
+NNR = (GDV, TVB)
+RVX = (MND, LLL)
+BVL = (SKM, CFM)
+RFS = (XQR, QXF)
+TVR = (XBP, FPN)
+VTD = (LTN, BXH)
+GPC = (XHK, BMP)
+QGH = (RNB, VSM)
+GDR = (PJH, JHB)
+RMG = (KXL, TBV)
+PST = (TVP, FSV)
+GPJ = (GXC, PLG)
+LBD = (KTN, GVD)
+LLK = (LRT, DFP)
+KGR = (MVQ, LKQ)
+MQG = (XJL, NHN)
+QXF = (NSH, STD)
+GMD = (PFH, BQR)
+BFS = (KGN, QHD)
+RCR = (FVM, VVS)
+RPP = (SPG, FHQ)
+FMK = (BGP, RJS)
+FGR = (RMG, VHP)
+SXH = (RTB, LFS)
+GVD = (GRP, TCF)
+TGX = (XFH, VLS)
+JTD = (NCJ, TBN)
+MFV = (PJH, JHB)
+HGV = (KCP, HJS)
+HSS = (XKQ, RGS)
+PTS = (BDT, SXH)
+XSP = (LPG, QGH)
+TCX = (PVX, XVF)
+LKQ = (QBX, DRH)
+FSF = (LSV, MKG)
+XJQ = (RHP, NXM)
+NHN = (FTX, DXR)
+GQJ = (KQP, DKN)
+TLX = (XQH, CVD)
+HJJ = (VCS, NKS)
+GTR = (VQJ, RRS)
+RHD = (FJR, RVR)
+VXK = (LSV, MKG)
+MNX = (HBT, CLM)
+PPH = (LVB, MRB)
+GDP = (LCB, GDK)
+DJQ = (BVL, RQS)
+FCJ = (MVQ, LKQ)
+VHC = (VHT, BSP)
+PVL = (PPR, SSP)
+LCB = (DVX, RKS)
+PFD = (MNM, PTS)
+MVF = (KBD, TVD)
+DJK = (XQQ, TVF)
+QSL = (GSV, KCF)
+NXM = (MXX, MTC)
+TJT = (CKJ, MVG)
+GTH = (NHN, XJL)
+SQK = (SPP, JCM)
+DPH = (LNS, JQJ)
+QPN = (RPS, PGV)
+SRK = (MFX, CVC)
+RFJ = (GKB, TSX)
+QLG = (XVF, PVX)
+QTV = (HLR, VLL)
+PLV = (GBX, RGQ)
+GHR = (SVH, JPC)
+XMV = (GHM, TBT)
+PKG = (JDT, JDT)
+MGP = (RPG, QGC)
+QDH = (TKX, RRQ)
+HJR = (RBP, RVX)
+NDV = (LCB, GDK)
+KRV = (MVF, LQX)
+NTM = (TJF, SQF)
+NXQ = (BKQ, BMN)
+HFF = (VDT, JSL)
+SLR = (QTR, KJV)
+DDN = (BKK, FNM)
+LHT = (XJQ, GRM)
+DST = (QKX, FNK)
+PPR = (MNV, HTF)
+JHC = (LVB, MRB)
+MXX = (DPG, FFX)
+VDT = (DDN, DDN)
+XMC = (HBT, CLM)
+TPD = (SSP, PPR)
+BSP = (GTH, MQG)
+NJG = (FCH, CSP)
+MGT = (VGH, FRM)
+NCJ = (TLV, JLK)
+VCN = (NSB, CLC)
+CBD = (CCD, PFT)
+NQB = (XHK, BMP)
+MFG = (XNF, MXR)
+XFL = (RMR, QFK)
+KCF = (JNT, QTK)
+JTX = (MKB, NGM)
+NTG = (MBK, CGX)
+XCX = (MBR, RDL)
+HGT = (HPP, DLP)
+FJD = (GHP, SQK)
+FXF = (PFP, FRL)
+GFC = (TBN, NCJ)
+NSD = (HFR, FBP)
+HJS = (DDG, GFF)
+MNV = (RQV, VLX)
+VRH = (MTJ, KLJ)
+GJH = (XRF, TGX)
+JMM = (BHB, VJK)
+BDN = (RBK, RRN)
+JDP = (BLC, ZZZ)
+GJK = (HHB, DNX)
+TCF = (NDL, HFF)
+JGV = (MFK, MRL)
+LPG = (VSM, RNB)
+KBH = (FTV, LBD)
+CDT = (NXN, GQP)
+QKK = (GGR, LXC)
+RMD = (CJF, XNV)
+MKF = (TVN, BTT)
+RBV = (XSP, KSC)
+RMH = (JVG, DTS)
+RPG = (LHT, LHX)
+FCH = (NDV, GDP)
+HPF = (LTS, RVQ)
+DRH = (BTM, HPH)
+PFR = (RJR, DBR)
+RJR = (SVN, VXJ)
+MFK = (HCQ, QDN)
+RGQ = (VRH, CPG)
+BSX = (GHN, NJL)
+TLR = (XFL, JSV)
+KCV = (NQF, BCH)
+PJC = (JGX, JCV)
+XVF = (KGG, CVJ)
+DKF = (GBP, FXB)
+SKG = (XXD, MJL)
+MVB = (BVP, BXM)
+MJL = (GJK, CVV)
+NSH = (VCN, VXF)
+DVD = (BCQ, PJC)
+VPR = (LLN, FCD)
+HLG = (SDF, HPF)
+FLD = (BXJ, DTM)
+SKK = (GDD, DCG)
+NQF = (SRK, LSG)
+QNN = (LXL, MGT)
+DMR = (MKB, NGM)
+FVB = (NNR, PBH)
+MXR = (TPD, PVL)
+CLF = (DJC, XXQ)
+FCT = (GQP, NXN)
+RPA = (QKX, FNK)
+MHQ = (XCF, RCR)
+XPK = (PBH, NNR)
+RBK = (TPM, TPM)
+LVX = (TDQ, XLH)
+RMR = (SDM, VTH)
+PBF = (FNX, MGP)
+GCM = (QML, XGD)
+KSF = (BSX, THL)
+XXD = (GJK, CVV)
+DBR = (VXJ, SVN)
+THD = (DXB, GDQ)
+LFR = (LBC, CPT)
+LKK = (FBP, HFR)
+GFP = (RJR, DBR)
+RNK = (VCS, NKS)
+PBL = (VNQ, SRD)
+FXM = (DDF, LVX)
+KGN = (XFM, LQM)
+VPK = (GPC, NQB)
+JNS = (HGV, XJR)
+GTK = (BQR, PFH)
+FTV = (KTN, GVD)
+MCJ = (DFH, GGQ)
+MDF = (LJC, RFS)
+JRL = (GJF, QTV)
+MFC = (RMK, JBX)
+VVS = (NGC, VHC)
+TVF = (TLR, GLZ)
+FCF = (BCQ, PJC)
+SXS = (NQF, BCH)
+GDC = (HXH, TBK)
+XXQ = (MKF, PNR)
+SPG = (GMR, TRF)
+GVP = (LNN, TJT)
+PQQ = (SLR, TDG)
+HBT = (QRH, LDG)
+XGD = (KSR, RFJ)
+QML = (KSR, RFJ)
+LKM = (RVR, FJR)
+DRN = (MJV, NFS)
+MKB = (NTF, BDN)
+GHP = (JCM, SPP)
+XPT = (JMM, CBB)
+KTN = (GRP, TCF)
+LRT = (SCN, HJR)
+BVP = (QKT, GHR)
+FNK = (VPR, BHD)
+GRM = (RHP, NXM)
+BXM = (QKT, GHR)
+CPM = (RSG, NCR)
+MRL = (HCQ, QDN)
+VQG = (PVS, PQQ)
+STD = (VXF, VCN)
+DQD = (DGV, PKV)
+TSX = (GJB, JKK)
+GTD = (KCF, GSV)
+FNX = (RPG, QGC)
+BXH = (LDF, FHF)
+CVC = (GLK, QSC)
+TLV = (MDF, HPL)
+DNL = (PMG, VRK)
+FQD = (GTK, GMD)
+CPG = (MTJ, KLJ)
+SPP = (BKS, PJM)
+GJB = (RVV, XPG)
+SSK = (FXF, BTN)
+PVH = (MXT, JDF)
+XVN = (FQN, KRV)
+LFJ = (BSX, THL)
+VNH = (KGN, QHD)
+HLR = (FMK, LCD)
+KBL = (JTL, PFD)
+BTM = (TLX, RQG)
+DPB = (PST, DVS)
+LTS = (FQC, PLV)
+RQG = (CVD, XQH)
+PBR = (LNN, TJT)
+CLB = (MFG, BPS)
+XFM = (RMH, XDJ)
+CJR = (MJQ, MVB)
+VTN = (BVL, RQS)
+VBG = (QDH, CST)
+GMR = (HVJ, DKF)
+KHG = (BXJ, DTM)
+GDD = (CLF, GBS)
+QTR = (QKK, MDD)
+VCL = (MFS, MFC)
+TBV = (VQC, VSX)
+BCQ = (JCV, JGX)
+NGC = (VHT, BSP)
+GJF = (HLR, VLL)
+FGD = (NPX, BHV)
+RGS = (PQT, FJD)
+VXJ = (PBF, GXR)
+FJR = (SJH, FQT)
+VXF = (CLC, NSB)
+HCF = (GPC, NQB)
+DTK = (RLG, GCM)
+MRB = (XMC, MNX)
+MFX = (QSC, GLK)
+GMX = (VXK, FSF)
+BDT = (LFS, RTB)
+JRN = (VHQ, JGB)
+SHJ = (KLR, VTD)
+TCL = (HRL, SPS)
+CPT = (DTK, JTV)
+VPM = (TFH, RRM)
+DQP = (RMD, KVX)
+CJF = (VQG, PVR)
+PBH = (GDV, TVB)
+LXC = (QLG, TCX)
+FHQ = (GMR, TRF)
+BMP = (XVM, NTM)
+XHK = (NTM, XVM)
+NQP = (LVX, DDF)
+TVP = (GMC, HJN)
+XFS = (LNH, RPP)
+RGM = (RHX, HGG)
+NQC = (VNH, BFS)
+GXC = (RBV, NJD)
+XQR = (NSH, STD)
+BTT = (QNN, DPQ)
+PFP = (CHS, JNV)
+QKT = (SVH, JPC)
+QCC = (DHL, XFS)
+LTN = (LDF, FHF)
+CMR = (GMJ, NJG)
+DGF = (XQQ, XQQ)
+MTX = (DST, BJZ)
+QSJ = (GTR, NXD)
+DFP = (HJR, SCN)
+MNJ = (FCJ, KGR)
+XSH = (QST, STX)
+VHP = (KXL, TBV)
+DGS = (KQP, DKN)
+HPL = (LJC, RFS)
+DTS = (RDG, PBT)
+VJK = (JTX, DMR)
+CLM = (LDG, QRH)
+QFK = (SDM, VTH)
+HGG = (CDL, RGD)
diff --git a/day8/uppga.c b/day8/uppga.c
@@ -0,0 +1,28 @@
+#include "common.h"
+
+int main(int argc, char **argv) {
+ char **lines;
+ size_t nlines = readlines(&lines, "input");
+
+ char *instructions = lines[0];
+ uint64_t lefts[ZZZ + 1];
+ uint64_t rights[ZZZ + 1];
+
+ read_graph(lefts, rights, lines, nlines);
+
+ uint64_t n = AAA;
+ uint64_t count = 0;
+ while (n != ZZZ) {
+ if (*instructions == 'L')
+ n = lefts[n];
+ else if (*instructions == 'R')
+ n = rights[n];
+ count++;
+
+ instructions++;
+ if (*instructions != 'R' && *instructions != 'L')
+ instructions = lines[0];
+ }
+
+ printf("%llu\n", count);
+}
diff --git a/day8/uppgb.c b/day8/uppgb.c
@@ -0,0 +1,122 @@
+#include "common.h"
+
+#define ZZZ 17575
+#define AAA 0
+
+static inline stack_u64 read_starts(char **lines, size_t nlines) {
+ size_t i;
+ stack_u64 r;
+ stack_u64_init(&r);
+
+ for (i = 2; i < nlines; i++) {
+ if (lines[i][2] == 'A') {
+ stack_u64_push(&r, chrs_to_node(lines[i]));
+ }
+ }
+
+ return r;
+}
+
+// positition = (value, ins) where 0 <= ins < #instructions
+typedef struct {
+ uint64_t v;
+ size_t ins;
+} pos_t;
+
+typedef struct {
+ uint64_t *ls;
+ uint64_t *rs;
+
+ char *ins;
+ size_t nins;
+} gr_t;
+
+static inline pos_t stepf(pos_t x, gr_t *g) {
+ pos_t r;
+ r.ins = (x.ins + 1) % g->nins;
+ if (g->ins[x.ins] == 'L') {
+ r.v = g->ls[x.v];
+ } else {
+ r.v = g->rs[x.v];
+ }
+
+ return r;
+}
+
+static inline void floyd(stack_u64 *mus, stack_u64 *lams, pos_t s, gr_t *g) {
+ pos_t tortoise = stepf(s, g);
+ pos_t hare = stepf(tortoise, g);
+
+ while (tortoise.v != hare.v || tortoise.ins != hare.ins) {
+ tortoise = stepf(tortoise, g);
+ hare = stepf(stepf(hare, g), g);
+ }
+
+ uint64_t mu = 0;
+ tortoise = s;
+ while (tortoise.v != hare.v || tortoise.ins != hare.ins) {
+ tortoise = stepf(tortoise, g);
+ hare = stepf(hare, g);
+ mu++;
+ }
+
+ uint64_t lam = 1;
+ hare = stepf(tortoise, g);
+ while (tortoise.v != hare.v || tortoise.ins != hare.ins) {
+ hare = stepf(hare, g);
+ lam++;
+ }
+
+ stack_u64_push(mus, mu);
+ stack_u64_push(lams, lam);
+}
+
+static uint64_t lcm(stack_u64 *s) {
+ mpz_t l, t1;
+ mpz_inits(l, t1, NULL);
+ mpz_set_ui(l, s->data[0]);
+
+ size_t i;
+ for (i = 1; i < s->nmemb; i++) {
+ mpz_set_ui(t1, s->data[i]);
+ mpz_lcm(l, l, t1);
+ }
+
+ uint64_t r = mpz_get_ui(l);
+
+ mpz_clears(l, t1, NULL);
+
+ return r;
+}
+
+int main(int argc, char **argv) {
+ size_t i, nins = 0;
+ char **lines;
+ size_t nlines = readlines(&lines, "input");
+
+ char *instructions = lines[0];
+ while (instructions[nins] == 'R' || instructions[nins] == 'L') {
+ nins++;
+ }
+
+ uint64_t lefts[ZZZ + 1];
+ uint64_t rights[ZZZ + 1];
+ read_graph(lefts, rights, lines, nlines);
+
+ gr_t g = {lefts, rights, instructions, nins};
+
+ stack_u64 starts = read_starts(lines, nlines);
+ stack_u64 mus, lams;
+ stack_u64_init(&mus);
+ stack_u64_init(&lams);
+
+ for (i = 0; i < starts.nmemb; i++) {
+ pos_t first = {starts.data[i], 0};
+ floyd(&mus, &lams, first, &g);
+ }
+
+ uint64_t lcm_lam = lcm(&lams);
+ printf("%llu\n", lcm_lam);
+
+ stack_u64_clear(&starts);
+}
diff --git a/day9/Makefile b/day9/Makefile
@@ -0,0 +1,30 @@
+CC=clang
+CFLAGS+=-std=c99 -pedantic -Wall -Werror -Wstrict-prototypes
+CFLAGS+=-Wmissing-prototypes -Wmissing-declarations -Wshadow
+CFLAGS+=-Wpointer-arith -Wcast-qual -Wsign-compare
+CFLAGS+=-O2 -g
+CFLAGS+=-fstack-protector-all -Wtype-limits -fno-common
+CFLAGS+=-fno-builtin
+CFLAGS+=-I/usr/local/include
+CFLAGS+=-I../utils
+#LDFLAGS=
+
+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) $(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)
+
+utils:
+ make -C ../utils
+
+clean:
+ rm -rf common.o uppga uppgb
diff --git a/day9/common.c b/day9/common.c
@@ -0,0 +1,3 @@
+#include "common.h"
+
+size_t fn(char **lines, size_t nlines) { return 0; }
diff --git a/day9/common.h b/day9/common.h
@@ -0,0 +1,14 @@
+#ifndef COMMON_H_
+#define COMMON_H_
+
+#include <assert.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <reading.h>
+#include <stack_u64.h>
+
+size_t fn(char **lines, size_t nlines);
+
+#endif
diff --git a/day9/exinput b/day9/exinput
@@ -0,0 +1,3 @@
+0 3 6 9 12 15
+1 3 6 10 15 21
+10 13 16 21 30 45
diff --git a/day9/input b/day9/input
@@ -0,0 +1,200 @@
+26 35 42 63 136 327 729 1457 2648 4480 7229 11394 17952 28881 48234 84291 153739 289701 557511 1087187 2143197
+-6 -7 -7 -6 -4 -1 3 8 14 21 29 38 48 59 71 84 98 113 129 146 164
+10 21 39 71 124 205 321 479 686 949 1275 1671 2144 2701 3349 4095 4946 5909 6991 8199 9540
+17 36 64 110 196 368 721 1447 2915 5792 11214 21016 38030 66460 112343 184105 293221 454988 689420 1022274 1486216
+14 33 64 116 204 363 671 1289 2540 5066 10129 20190 40081 79524 158734 320937 659964 1379861 2920964 6221222 13247612
+10 17 41 95 198 375 657 1081 1690 2533 3665 5147 7046 9435 12393 16005 20362 25561 31705 38903 47270
+14 29 64 124 216 352 565 958 1808 3743 8000 16767 33646 64419 118683 213748 383770 699853 1311392 2526026 4956236
+19 30 47 86 178 369 720 1307 2221 3568 5469 8060 11492 15931 21558 28569 37175 47602 60091 74898 92294
+1 13 30 66 156 361 782 1589 3082 5828 10975 20973 41216 83707 175021 373168 802624 1726245 3691904 7830015 16453595
+7 6 12 33 86 197 399 741 1345 2591 5587 13218 32302 77760 180292 399922 849043 1730420 3398238 6454079 11895222
+20 40 66 104 168 288 538 1089 2290 4780 9636 18566 34162 60236 102272 168039 268424 418560 639342 959444 1417972
+4 1 8 49 171 457 1047 2169 4174 7572 13095 21883 36015 59804 102558 183893 343184 655371 1256114 2380229 4418451
+11 21 44 94 190 354 607 963 1421 1955 2502 2948 3112 2728 1425 -1295 -6081 -13759 -25360 -42150 -65662
+-5 2 24 67 140 257 432 667 941 1223 1565 2410 5431 15611 46111 129246 340658 851773 2042419 4740096 10722177
+30 42 54 78 144 309 666 1353 2562 4548 7638 12240 18852 28071 40602 57267 79014 106926 142230 186306 240696
+4 5 6 4 -2 -6 16 144 614 2030 5756 14577 33738 72479 146164 279025 507368 882763 1474194 2367290 3657486
+15 39 71 119 214 419 847 1704 3385 6680 13205 26287 52768 106695 216910 442638 905099 1850193 3769279 7624639 15257058
+3 12 37 84 157 259 396 590 917 1601 3217 7084 15961 35198 74558 151062 293511 549970 1000717 1781348 3124429
+30 52 78 111 156 226 363 678 1414 3032 6311 12445 23129 40681 68393 111605 180538 296816 506992 908439 1695878
+13 11 22 61 142 275 477 809 1456 2892 6241 14089 32266 73589 165430 364651 786707 1661933 3443480 7011621 14053570
+12 39 91 193 395 786 1514 2811 5024 8670 14583 24331 41297 73223 137768 274043 565775 1186884 2489910 5175384 10611406
+17 30 44 61 96 187 413 924 1999 4173 8512 17166 34394 68332 133865 257067 481789 879104 1560460 2695547 4536052
+4 11 19 37 82 184 404 887 1995 4606 10740 24810 56050 123161 263200 548769 1121742 2260137 4510825 8950315 17687738
+7 27 59 103 159 227 307 399 503 619 747 887 1039 1203 1379 1567 1767 1979 2203 2439 2687
+24 33 35 39 72 183 445 955 1832 3213 5247 8087 11880 16755 22809 30091 38584 48185 58683 69735 80840
+14 25 44 81 158 317 646 1349 2901 6354 13911 29992 63242 130402 263910 526903 1042536 2050026 4008556 7783136 14964330
+14 36 82 176 361 717 1400 2716 5251 10085 19128 35643 65091 116595 205685 359815 630008 1116030 2020826 3766194 7231721
+7 22 46 81 131 199 287 419 728 1675 4501 12052 30162 69830 150484 304688 584717 1071500 1886512 3207283 5287285
+0 13 51 141 338 752 1597 3285 6611 13106 25672 49656 94583 176907 324514 584721 1040090 1842598 3291085 6008902 11347440
+26 54 99 165 256 376 529 719 950 1226 1551 1929 2364 2860 3421 4051 4754 5534 6395 7341 8376
+5 8 30 96 252 576 1189 2266 4047 6848 11072 17220 25902 37848 53919 75118 102601 137688 181874 236840 304464
+18 30 38 43 47 60 122 355 1072 2987 7605 17945 39891 84713 173697 346423 675094 1288516 2410936 4423047 7955159
+15 33 70 148 318 690 1491 3159 6476 12736 23937 42981 73861 121799 193252 295586 435973 618611 838592 1069506 1239992
+12 25 44 83 177 411 974 2247 4940 10314 20568 39558 74189 137162 252394 465548 863972 1613295 3022404 5655077 10515841
+17 23 28 32 35 37 38 38 37 35 32 28 23 17 10 2 -7 -17 -28 -40 -53
+20 27 34 41 48 55 62 69 76 83 90 97 104 111 118 125 132 139 146 153 160
+14 28 63 140 289 549 968 1603 2520 3794 5509 7758 10643 14275 18774 24269 30898 38808 48155 59104 71829
+11 13 25 60 131 258 496 1006 2196 4970 11163 24360 51603 107183 221143 457846 954845 2000571 4182761 8660420 17643527
+1 12 46 110 209 345 517 731 1033 1584 2809 5682 12277 26869 58216 124413 263297 554524 1165328 2442470 5090777
+1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
+10 19 28 36 37 21 -18 -55 28 563 2326 6990 18036 42542 94505 200604 409561 806558 1534779 2827723 5059814
+8 31 67 121 207 352 604 1053 1886 3529 6995 14671 31953 70390 153340 325587 668932 1326467 2539083 4698765 8424403
+15 39 77 136 230 387 668 1209 2294 4459 8612 16133 28911 49357 80812 129945 215765 396795 842423 2002558 4981136
+8 4 -7 -26 -38 11 245 898 2373 5351 11022 21596 41452 79760 156506 316211 658402 1402950 3024695 6519782 13912298
+24 49 97 177 299 483 776 1277 2170 3765 6547 11233 18837 30743 48786 75341 113420 166777 240021 338737 469615
+-5 -4 3 23 81 241 651 1635 3864 8647 18392 37296 72332 134610 241198 417498 700281 1141494 1812961 2812109 4268859
+13 24 37 60 120 280 664 1498 3179 6388 12267 22684 40614 70668 119806 198274 320809 508160 788977 1202124 1799476
+-8 1 27 85 201 414 780 1377 2310 3715 5761 8649 12607 17880 24714 33333 43908 56517 71095 87373 104805
+4 10 26 58 117 232 475 1002 2120 4392 8797 16987 31757 58013 104866 190153 350020 658890 1270556 2501848 5000829
+5 23 60 133 271 521 957 1692 2895 4833 8000 13465 23669 44023 85797 170932 339537 660931 1249132 2283653 4036307
+-6 0 21 76 210 510 1137 2387 4793 9279 17376 31509 55363 94335 156078 251142 393716 602474 901527 1321482 1900608
+7 26 69 161 350 715 1369 2453 4123 6547 9953 14802 22202 34730 57889 102496 188375 349816 643357 1158551 2032494
+8 24 59 124 241 451 822 1457 2502 4154 6669 10370 15655 23005 32992 46287 63668 86028 114383 149880 193805
+14 25 29 28 36 87 252 670 1597 3476 7030 13379 24181 41796 69471 111543 173656 262987 388475 561046 793826
+13 30 69 137 253 466 879 1679 3173 5830 10329 17613 28949 45994 70867 106227 155357 222254 311725 429489 582285
+19 26 27 20 5 -1 63 341 1111 2848 6299 12570 23225 40397 66911 106419 163547 244054 355003 504944 704109
+11 27 63 139 287 567 1091 2060 3840 7143 13442 25839 50726 100735 199668 390336 746521 1390611 2518849 4436587 7606449
+8 16 24 32 40 48 56 64 72 80 88 96 104 112 120 128 136 144 152 160 168
+24 40 58 74 78 56 3 -38 120 1023 4036 12295 32615 79211 180836 394437 831547 1710256 3459759 6934492 13857367
+21 45 80 133 233 459 998 2243 4936 10358 20569 38708 69378 119166 197385 317176 497175 764035 1156198 1729439 2564855
+-6 4 24 55 102 175 297 527 1012 2103 4618 10422 23632 52956 115951 246348 506054 1004014 1924812 3570721 6421890
+5 14 25 41 81 201 538 1392 3361 7544 15827 31267 58589 104811 180012 298258 478701 746866 1136141 1689485 2461369
+8 15 20 23 24 23 20 15 8 -1 -12 -25 -40 -57 -76 -97 -120 -145 -172 -201 -232
+13 20 30 48 76 118 195 384 904 2280 5634 13208 29381 62826 131291 272156 564999 1177756 2456894 5095984 10438354
+27 53 96 159 255 426 783 1588 3411 7409 15783 32472 64154 121681 222249 393008 677615 1148649 1931134 3246025 5487861
+27 51 87 147 252 443 811 1568 3204 6815 14760 31931 68124 142316 290137 576563 1116981 2111495 3899953 7049103 12489112
+15 38 65 106 199 432 972 2103 4287 8284 15397 27949 50166 89761 160728 288225 517106 927093 1660904 2979519 5376696
+0 6 31 85 194 412 837 1643 3145 5918 10995 20188 36667 66241 120629 226030 444760 927057 2029015 4569804 10373398
+19 26 33 40 47 54 61 68 75 82 89 96 103 110 117 124 131 138 145 152 159
+10 25 53 115 238 467 889 1678 3189 6155 12074 23913 47303 92453 177072 330656 600572 1060453 1821507 3047439 4973788
+-5 6 42 116 241 430 696 1052 1511 2086 2790 3636 4637 5806 7156 8700 10451 12422 14626 17076 19785
+13 40 92 178 320 570 1025 1832 3175 5243 8195 12175 17526 25612 41304 79628 181985 452774 1136694 2772588 6484284
+19 23 26 28 29 29 28 26 23 19 14 8 1 -7 -16 -26 -37 -49 -62 -76 -91
+17 28 51 84 122 162 210 294 504 1118 2937 8043 21309 53122 123918 271257 560267 1098336 2054903 3687062 6371412
+20 28 35 44 76 178 438 1031 2334 5162 11191 23648 48362 95284 180598 329559 580208 988128 1632419 2623084 4110032
+5 20 47 86 137 200 275 362 461 572 695 830 977 1136 1307 1490 1685 1892 2111 2342 2585
+26 38 56 87 148 291 641 1446 3149 6514 12872 24600 46007 84877 155011 280219 500340 880014 1521096 2579789 4289782
+10 18 29 45 77 160 369 829 1716 3258 5769 9790 16486 28609 52706 104067 217586 470910 1031969 2252631 4845759
+-1 10 31 62 103 154 215 286 367 458 559 670 791 922 1063 1214 1375 1546 1727 1918 2119
+8 12 20 49 121 260 489 827 1286 1868 2562 3341 4159 4948 5615 6039 6068 5516 4160 1737 -2059
+0 -4 -4 15 71 192 450 1034 2366 5263 11181 22696 44675 87230 172812 352167 738124 1573554 3362222 7111453 14767575
+19 37 73 130 204 280 340 404 636 1566 4512 12341 30798 70777 152136 310006 605061 1139971 2085359 3720200 6494028
+2 5 28 82 185 374 731 1434 2842 5621 10916 20572 37405 65522 110687 180728 285978 439741 658772 963758 1379785
+27 49 80 126 197 310 504 885 1731 3696 8158 17757 37162 74103 140767 255956 449312 771177 1316772 2284435 4111174
+-9 -14 -19 -24 -29 -34 -39 -44 -49 -54 -59 -64 -69 -74 -79 -84 -89 -94 -99 -104 -109
+6 15 27 46 76 121 185 272 386 531 711 930 1192 1501 1861 2276 2750 3287 3891 4566 5316
+10 9 8 12 42 163 524 1407 3284 6886 13297 24100 41622 69352 112641 179837 284062 445903 697366 1087532 1690458
+0 9 24 44 68 105 193 433 1055 2544 5865 12837 26717 53066 100980 184780 326266 557651 925302 1494426 2354850
+10 12 10 4 -6 -20 -38 -60 -86 -116 -150 -188 -230 -276 -326 -380 -438 -500 -566 -636 -710
+8 20 45 89 168 331 691 1470 3073 6209 12068 22530 40306 68775 111098 168065 234382 294482 323003 304787 309948
+24 49 89 155 273 496 928 1779 3491 7003 14260 29127 58966 117310 228381 434731 810146 1481285 2663507 4719187 8250799
+19 33 62 128 264 514 933 1587 2553 3919 5784 8258 11462 15528 20599 26829 34383 43437 54178 66804 81524
+8 22 53 122 270 578 1193 2355 4413 7810 13019 20456 30543 44436 66599 111605 219725 490109 1149268 2691985 6174015
+26 50 82 123 185 303 566 1175 2531 5351 10805 20662 37428 64454 105987 167132 253688 371816 527492 725693 969259
+14 35 80 158 278 449 680 980 1358 1823 2384 3050 3830 4733 5768 6944 8270 9755 11408 13238 15254
+11 11 15 23 35 51 71 95 123 155 191 231 275 323 375 431 491 555 623 695 771
+6 16 24 35 58 96 141 187 289 723 2341 7266 20135 50173 114468 242916 485416 922018 1676862 2936893 4976496
+11 20 49 110 227 453 898 1768 3424 6485 12017 21877 39339 70262 125339 224493 405397 739562 1361669 2521064 4668871
+20 37 80 158 285 497 885 1648 3160 6035 11176 19837 33870 56674 96069 171621 331201 685379 1474871 3198556 6854496
+4 6 20 55 138 338 805 1841 4037 8544 17608 35600 70923 139390 269951 514014 960066 1755866 3141164 5494709 9400256
+8 13 34 90 208 430 841 1627 3186 6356 12910 26629 55545 116404 243087 501667 1015960 2008922 3867653 7245316 13228060
+3 16 37 69 124 232 465 1001 2269 5236 11921 26249 55390 111764 215933 400645 716343 1238504 2077229 3389565 5395104
+24 45 85 166 322 598 1063 1847 3218 5732 10517 19791 37764 72135 136467 253806 462004 821311 1424917 2413252 3992990
+7 24 56 109 189 302 454 651 899 1204 1572 2009 2521 3114 3794 4567 5439 6416 7504 8709 10037
+6 6 15 43 91 159 276 558 1303 3152 7405 16728 36804 80099 174024 377639 814012 1729858 3600691 7309097 14436681
+14 20 37 71 127 210 320 440 518 446 41 -965 -2917 -6200 -11160 -17968 -26410 -35584 -43483 -46441 -38417
+12 17 16 12 25 120 460 1409 3724 8883 19602 40622 79965 151215 278256 505768 922388 1709889 3242580 6278524 12310953
+9 9 10 7 -6 -23 -1 179 775 2311 5872 13776 30987 67865 145228 303374 617945 1227749 2383562 4533485 8470988
+9 11 14 19 43 131 362 843 1689 2997 4835 7291 10709 16508 29705 65926 169073 452107 1184316 2966327 7062159
+4 19 44 77 112 138 134 62 -137 -530 -1130 -1722 -1448 2152 15406 53958 155715 410547 1025294 2459060 5690975
+17 19 21 23 25 27 29 31 33 35 37 39 41 43 45 47 49 51 53 55 57
+28 38 41 31 8 1 117 624 2070 5435 12324 25277 48475 89589 164469 308195 599485 1212145 2520288 5309464 11194667
+1 4 2 -6 -13 14 174 709 2139 5482 12592 26654 52881 99464 178832 309285 517069 838968 1325494 2044762 3087143
+-1 15 45 97 186 335 592 1078 2095 4347 9373 20396 44024 93710 196770 408372 838760 1704980 3427198 6805400 13340371
+24 49 98 179 297 454 662 979 1576 2850 5634 11665 24741 53576 118484 266044 599328 1336819 2921754 6216539 12835689
+21 43 91 177 313 527 903 1662 3307 6861 14233 28753 55923 104437 187529 324714 543993 884599 1400367 2163817 3271045
+10 20 48 110 232 449 817 1461 2691 5227 10583 21669 43679 85342 160622 290962 508176 858102 1405138 2237792 3475386
+11 35 84 169 305 523 890 1537 2706 4864 9012 17463 35603 75523 162993 350202 738357 1517321 3035288 5922273 11310317
+5 16 36 79 164 317 575 988 1620 2577 4149 7249 14465 32206 74610 170076 371463 771142 1522162 2866763 5173298
+23 47 91 180 355 676 1237 2209 3932 7082 12944 23827 43662 78829 139264 239902 402517 658025 1049321 1634726 2492125
+15 23 27 34 62 157 432 1136 2766 6255 13310 27042 53131 101922 192141 357660 660775 1220785 2279451 4353200 8580138
+22 35 50 71 109 182 315 540 896 1429 2192 3245 4655 6496 8849 11802 15450 19895 25246 31619 39137
+19 46 99 184 301 445 609 789 991 1240 1591 2142 3049 4543 6949 10707 16395 24754 36715 53428 76293
+16 35 78 161 304 532 886 1455 2451 4374 8370 17012 36007 77877 169678 368610 792378 1676029 3474614 7042651 13938682
+11 21 37 74 161 344 684 1257 2179 3705 6498 12267 25210 55211 124765 283528 637855 1408801 3042715 6416976 13214939
+28 50 82 125 194 336 661 1391 2939 6053 12112 23759 46217 89871 175017 340071 654974 1241980 2306406 4180161 7380828
+16 33 52 76 116 194 346 625 1104 1879 3072 4834 7348 10832 15542 21775 29872 40221 53260 69480 89428
+13 19 43 102 215 403 689 1098 1657 2395 3343 4534 6003 7787 9925 12458 15429 18883 22867 27430 32623
+23 28 25 23 41 115 318 793 1799 3774 7427 13883 24921 43365 73712 123109 202823 330384 532621 849855 1341561
+8 13 31 81 190 392 739 1348 2529 5075 10857 23969 52827 113862 237783 479848 936198 1769113 3245075 5790809 10074060
+5 -1 -3 1 24 102 309 788 1831 4088 9089 20476 46745 107008 242462 538106 1162045 2433793 4938737 9713831 18540218
+23 36 67 128 238 432 765 1304 2096 3100 4082 4498 3433 -276 -7530 -17782 -26795 -22876 18957 145468 436960
+19 19 10 -13 -55 -121 -216 -345 -513 -725 -986 -1301 -1675 -2113 -2620 -3201 -3861 -4605 -5438 -6365 -7391
+13 22 35 63 127 273 594 1257 2533 4828 8713 14951 24519 38623 58704 86433 123693 172546 235183 313855 410783
+15 29 62 138 301 623 1211 2210 3808 6273 10109 16538 28739 54658 112833 243745 531201 1142472 2405599 4965114 10110423
+22 31 40 45 47 68 173 508 1375 3376 7669 16390 33306 64775 121100 218375 380932 644509 1060270 1699819 2661361
+16 37 69 115 199 383 781 1560 2922 5084 8336 13405 22681 43553 96491 233174 574927 1390866 3252030 7329342 15962906
+25 37 46 52 55 55 52 46 37 25 10 -8 -29 -53 -80 -110 -143 -179 -218 -260 -305
+-2 -1 16 58 135 261 456 747 1168 1759 2564 3628 4993 6693 8748 11157 13890 16879 20008 23102 25915
+7 17 54 130 269 530 1052 2143 4445 9217 18788 37242 71407 132230 236630 409931 688987 1126121 1794010 2791658 4251609
+15 31 72 160 334 671 1314 2518 4741 8835 16445 30812 58307 111210 212522 404027 759535 1406459 2560962 4585380 8082232
+24 33 42 51 60 69 78 87 96 105 114 123 132 141 150 159 168 177 186 195 204
+-5 -7 8 61 189 455 970 1944 3787 7293 13979 26755 51348 99453 195748 393249 805935 1675617 3503846 7302341 15051147
+11 20 46 108 230 441 775 1271 1973 2930 4196 5830 7896 10463 13605 17401 21935 27296 33578 40880 49306
+11 12 23 66 175 396 787 1418 2371 3740 5631 8162 11463 15676 20955 27466 35387 44908 56231 69570 85151
+15 22 38 68 118 206 383 768 1612 3433 7323 15646 33567 72250 155262 330921 695341 1434220 2896652 5722340 11055780
+3 7 20 59 150 322 611 1085 1914 3548 7156 15669 36147 84904 198134 453125 1009261 2185081 4599544 9425143 18831724
+5 15 27 42 71 139 295 632 1326 2724 5557 11438 23947 50845 108404 229791 481678 998568 2056522 4234421 8765038
+30 44 56 72 112 216 447 889 1638 2784 4382 6410 8712 10924 12381 12003 8158 -1500 -20220 -52372 -103696
+16 22 30 43 71 138 296 646 1378 2880 6037 12959 28588 64067 143715 319587 702164 1525018 3279356 6987931 14747917
+5 -1 -10 -24 -33 3 180 683 1836 4211 8897 18122 36552 73767 148641 296637 581375 1112247 2070344 3745532 6588173
+-5 3 30 90 209 447 946 2018 4291 8943 18077 35324 66803 122611 219053 381840 650467 1083915 1767680 2821894 4409941
+1 -6 -22 -51 -92 -122 -67 239 1107 3058 6900 13817 25470 44110 72703 115067 176021 261546 378958 537093 746504
+19 35 71 138 255 454 787 1341 2267 3829 6479 10964 18471 30816 50683 81919 129891 201911 307735 460142 675599
+5 1 -4 -15 -36 -60 -48 122 773 2679 7552 18927 43690 94632 194650 383626 729701 1347765 2429692 4293397 7461472
+22 47 84 133 194 267 352 449 558 679 812 957 1114 1283 1464 1657 1862 2079 2308 2549 2802
+27 39 50 67 106 190 350 637 1153 2109 3918 7331 13624 24844 44122 76061 127207 206611 326490 502995 757094
+21 36 62 113 217 419 794 1493 2869 5767 12110 25974 55446 115785 234945 463719 895201 1702826 3214226 6051331 11387971
+-4 11 40 84 152 276 534 1089 2268 4728 9788 20048 40471 80195 155561 295458 551743 1021562 1897525 3580679 6928437
+-3 -5 -7 -9 -11 -13 -15 -17 -19 -21 -23 -25 -27 -29 -31 -33 -35 -37 -39 -41 -43
+21 43 73 123 229 467 976 1988 3865 7143 12583 21229 34473 54127 82502 122494 177677 252403 351909 482431 651325
+19 29 34 46 94 224 497 985 1765 2911 4484 6520 9016 11914 15083 18299 21223 23377 24118 22610 17794
+8 20 32 44 56 68 80 92 104 116 128 140 152 164 176 188 200 212 224 236 248
+13 9 14 36 82 168 347 777 1871 4603 11095 25687 56799 120029 243083 473279 888469 1612225 2833960 4834202 8014380
+25 52 95 155 233 330 447 585 745 928 1135 1367 1625 1910 2223 2565 2937 3340 3775 4243 4745
+3 -1 -2 20 104 313 751 1601 3198 6178 11813 22782 44894 90788 187635 392864 825918 1731880 3607877 7451423 15241457
+11 18 34 74 172 382 776 1446 2531 4313 7458 13519 25868 51283 102484 201989 387747 721100 1297730 2262360 3828100
+8 9 20 59 166 424 993 2158 4401 8543 16094 30140 57443 113004 229225 473103 976710 1988685 3957728 7663297 14414036
+8 17 43 97 193 355 637 1160 2170 4121 7787 14407 25867 44923 75469 122854 194252 299089 449531 661037 952981
+5 18 52 121 242 433 719 1158 1897 3263 5891 10909 20287 37707 70876 137305 277557 583511 1255976 2720254 5860036
+26 48 79 117 160 206 253 299 342 380 411 433 444 442 425 391 338 264 167 45 -104
+4 20 64 149 286 484 750 1089 1504 1996 2564 3205 3914 4684 5506 6369 7260 8164 9064 9941 10774
+5 3 -2 -7 4 66 232 572 1184 2228 3986 6935 11795 19479 30826 45940 62887 75417 69278 16573 -132522
+29 46 64 77 76 47 -27 -150 -260 -81 1250 6043 19894 55385 139172 325018 716889 1508424 3047842 5940189 11200546
+7 31 76 154 286 522 977 1884 3677 7145 13741 26179 49495 92794 172036 314672 568255 1018307 1827378 3319972 6160648
+19 43 90 171 309 555 1000 1776 3052 5057 8209 13520 23625 45116 93448 202656 443653 957187 2010888 4094557 8074321
+14 31 63 137 309 692 1505 3161 6436 12799 25035 48359 92299 173720 321469 583243 1035418 1796727 3046839 5051069 8192641
+-7 -9 1 45 169 453 1023 2063 3818 6573 10587 15954 22359 28711 32700 30500 17219 -10581 -47711 -63885 29897
+5 8 18 46 107 216 385 636 1070 2070 4761 11892 29330 68346 148806 303230 581419 1054940 1820164 2997730 4725213
+0 12 32 64 133 307 740 1752 3974 8606 17870 35802 69654 132452 247836 459451 849236 1572432 2922448 5446084 10138507
+15 22 48 120 277 570 1062 1828 2955 4542 6700 9552 13233 17890 23682 30780 39367 49638 61800 76072 92685
+-1 8 36 92 185 324 518 776 1107 1520 2024 2628 3341 4172 5130 6224 7463 8856 10412 12140 14049
+24 54 114 233 454 838 1483 2582 4571 8460 16502 33454 68859 141115 284789 564103 1098634 2113702 4040682 7716703 14777228
+20 25 26 22 13 13 87 421 1430 3916 9320 20183 41055 80282 153373 289016 539288 996203 1817478 3265284 5762801
+9 14 30 68 146 310 661 1381 2749 5136 8966 14628 22322 31820 42121 50977 54265 45178 13206 -57124 -187782
+15 29 57 109 202 360 614 1002 1569 2367 3455 4899 6772 9154 12132 15800 20259 25617 31989 39497 48270
+1 -3 -11 -24 -42 -62 -67 -1 281 1125 3361 9019 23021 56870 136134 314735 700845 1501645 3097193 6156590 11811100
+15 40 76 138 251 454 820 1509 2883 5740 11784 24555 51208 105772 214907 427910 834275 1595448 3004280 5598992 10382837
+9 21 53 124 274 582 1207 2466 4963 9783 18765 34868 62644 108832 183087 298858 474429 734137 1109781 1642236 2383286
+5 8 7 2 -3 0 23 82 197 392 695 1138 1757 2592 3687 5090 6853 9032 11687 14882 18685
+17 32 48 73 137 316 778 1868 4250 9118 18486 35601 65661 117400 207006 367840 673662 1291711 2598975 5427196 11561076
+2 8 10 15 40 116 298 695 1555 3470 7810 17562 38853 83592 173896 349294 678160 1275444 2329586 4142553 7188278
+10 19 34 65 132 270 540 1046 1958 3541 6190 10471 17168 27336 42360 64020 94562 136775 194074 270589 371260
+10 18 18 9 -7 -25 -37 -32 4 88 240 483 843 1349 2033 2930 4078 5518 7294 9453 12045
+12 28 55 106 203 370 630 1008 1533 2219 2990 3512 2955 -59 -6445 -12294 4101 115235 521500 1722951 4891122
+7 11 18 46 125 297 616 1148 1971 3175 4862 7146 10153 14021 18900 24952 32351 41283 51946 64550 79317
+-4 2 13 29 50 76 107 143 184 230 281 337 398 464 535 611 692 778 869 965 1066
+1 1 3 6 16 56 181 502 1224 2706 5573 10986 21362 42224 86628 185139 407435 908045 2021984 4462911 9729426
+18 33 64 121 214 363 613 1050 1822 3197 5745 10819 21640 45488 97833 209864 442106 909229 1825714 3590277 6941170
+5 18 44 95 192 363 652 1159 2143 4239 8878 19090 41095 87619 185057 389110 818618 1727421 3653857 7725842 16273119
diff --git a/day9/uppga.c b/day9/uppga.c
@@ -0,0 +1,69 @@
+#include "common.h"
+
+#define MAX_LINE 256
+
+static size_t readline_i64s(int64_t *out, const size_t max, char *line) {
+ char *cp = line;
+ size_t i = 0;
+
+ while ((cp = sread_next_i64(&out[i], cp)) != NULL) {
+ i++;
+ if (i >= max)
+ break;
+ }
+
+ return i;
+}
+
+static int allzeros(int64_t *x, size_t n) {
+ size_t i;
+ for (i = 0; i < n; i++) {
+ if (x[i] != 0)
+ return 0;
+ }
+ return 1;
+}
+
+int main(int argc, char **argv) {
+ char **lines;
+ size_t nlines = readlines(&lines, "input");
+ size_t i, j, k;
+
+ int64_t ln[MAX_LINE];
+ size_t nln;
+
+ int64_t summarum = 0;
+ for (i = 0; i < nlines; i++) {
+ nln = readline_i64s(ln, MAX_LINE, lines[i]);
+ int64_t *diffs = malloc((nln + 1) * (nln + 1) * sizeof(*diffs));
+
+ // row 0 is just input
+ for (j = 0; j < nln; j++)
+ diffs[j] = ln[j];
+
+ j = 0;
+ size_t cnln = nln;
+ while (!allzeros(&diffs[j * (nln + 1)], cnln)) {
+ j++;
+ cnln--;
+ for (k = 0; k < cnln; k++) {
+ diffs[j * (nln + 1) + k] =
+ diffs[(j - 1) * (nln + 1) + k + 1] - diffs[(j - 1) * (nln + 1) + k];
+ }
+ }
+
+ // goin' back up
+ diffs[j * (nln + 1) + cnln] = 0;
+ while (cnln < nln) {
+ j--;
+ cnln++;
+ diffs[j * (nln + 1) + cnln] = diffs[(j + 1) * (nln + 1) + cnln - 1] +
+ diffs[j * (nln + 1) + cnln - 1];
+ }
+ summarum += diffs[j * (nln + 1) + cnln];
+
+ free(diffs);
+ }
+
+ printf("%lld\n", summarum);
+}
diff --git a/day9/uppgb.c b/day9/uppgb.c
@@ -0,0 +1,69 @@
+#include "common.h"
+
+#define MAX_LINE 256
+
+static size_t readline_i64s(int64_t *out, const size_t max, char *line) {
+ char *cp = line;
+ size_t i = 0;
+
+ while ((cp = sread_next_i64(&out[i], cp)) != NULL) {
+ i++;
+ if (i >= max)
+ break;
+ }
+
+ return i;
+}
+
+static int allzeros(int64_t *x, size_t n) {
+ size_t i;
+ for (i = 0; i < n; i++) {
+ if (x[i] != 0)
+ return 0;
+ }
+ return 1;
+}
+
+int main(int argc, char **argv) {
+ char **lines;
+ size_t nlines = readlines(&lines, "input");
+ size_t i, j, k;
+ int64_t ln[MAX_LINE];
+ size_t nln;
+
+ int64_t summarum = 0;
+ for (i = 0; i < nlines; i++) {
+ nln = readline_i64s(ln, MAX_LINE, lines[i]);
+
+ int64_t *diffs = malloc((nln + 1) * (nln + 1) * sizeof(*diffs));
+
+ // row 0 is just input
+ for (j = 0; j < nln; j++)
+ diffs[j] = ln[j];
+
+ j = 0;
+ size_t cnln = nln;
+ while (!allzeros(&diffs[j * (nln + 1)], cnln)) {
+ j++;
+ cnln--;
+ for (k = 0; k < cnln; k++) {
+ diffs[j * (nln + 1) + k] =
+ diffs[(j - 1) * (nln + 1) + k + 1] - diffs[(j - 1) * (nln + 1) + k];
+ }
+ }
+
+ // goin' back up
+ diffs[j * (nln + 1) + cnln] = 0;
+ while (cnln < nln) {
+ j--;
+ cnln++;
+ diffs[j * (nln + 1) + cnln] =
+ diffs[j * (nln + 1)] - diffs[(j + 1) * (nln + 1) + cnln - 1];
+ }
+ summarum += diffs[j * (nln + 1) + cnln];
+
+ free(diffs);
+ }
+
+ printf("%lld\n", summarum);
+}
diff --git a/template/Makefile b/template/Makefile
@@ -0,0 +1,30 @@
+CC=clang
+CFLAGS+=-std=c99 -pedantic -Wall -Werror -Wstrict-prototypes
+CFLAGS+=-Wmissing-prototypes -Wmissing-declarations -Wshadow
+CFLAGS+=-Wpointer-arith -Wcast-qual -Wsign-compare
+CFLAGS+=-O2 -g
+CFLAGS+=-fstack-protector-all -Wtype-limits -fno-common
+CFLAGS+=-fno-builtin
+CFLAGS+=-I/usr/local/include
+CFLAGS+=-I../utils
+#LDFLAGS=
+
+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) $(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)
+
+utils:
+ make -C ../utils
+
+clean:
+ rm -rf common.o uppga uppgb
diff --git a/template/common.c b/template/common.c
@@ -0,0 +1,3 @@
+#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,13 @@
+#ifndef COMMON_H_
+#define COMMON_H_
+
+#include <assert.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.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,7 @@
+#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,7 @@
+#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,19 @@
+CC=clang
+CFLAGS+=-std=c99 -pedantic -Wall -Werror -Wstrict-prototypes
+CFLAGS+=-Wmissing-prototypes -Wmissing-declarations -Wshadow
+CFLAGS+=-Wpointer-arith -Wcast-qual -Wsign-compare
+CFLAGS+=-O2 -g
+CFLAGS+=-fstack-protector-all -Wtype-limits -fno-common
+CFLAGS+=-fno-builtin
+CFLAGS+=-I/usr/local/include
+#LDFLAGS=
+
+OBJS=reading.o stack_u64.o stack_str.o sd.o stack_sd.o ht.o smallset.o set_u64.o fheap.o set_u64p.o wdg.o graph.o dg.o dict.o
+
+all: $(OBJS)
+
+.c.o:
+ $(CC) $(CFLAGS) -c $<
+
+clean:
+ rm -rf $(OBJS)
diff --git a/utils/dg.c b/utils/dg.c
@@ -0,0 +1,21 @@
+#include "dg.h"
+
+void dg_init(dg_t *g, const size_t n) {
+ g->n = n;
+ g->nbrs = malloc(n * sizeof(*(g->nbrs)));
+
+ size_t i;
+ for (i = 0; i < n; i++)
+ stack_u64_init(&g->nbrs[i]);
+}
+
+void dg_clear(dg_t *g) {
+ size_t i;
+ for (i = 0; i < g->n; i++)
+ stack_u64_clear(&g->nbrs[i]);
+ free(g->nbrs);
+}
+
+void dg_add_edge(dg_t *g, const size_t v, const size_t w) {
+ stack_u64_push(&g->nbrs[v], w);
+}
diff --git a/utils/dg.h b/utils/dg.h
@@ -0,0 +1,15 @@
+#ifndef DG_H
+#define DG_H
+
+#include "stack_u64.h"
+
+typedef struct {
+ size_t n;
+ stack_u64 *nbrs;
+} dg_t;
+
+void dg_init(dg_t *g, const size_t n);
+void dg_clear(dg_t *g);
+void dg_add_edge(dg_t *g, const size_t v, const size_t w);
+
+#endif
diff --git a/utils/dict.c b/utils/dict.c
@@ -0,0 +1,111 @@
+#include "dict.h"
+
+/*
+static inline void stack_ptr_init(stack_ptr *d) {
+ d->nmemb = 0;
+ d->alloc = DICT_DEFAULT_STACK_SIZE;
+
+ d->data = calloc(d->alloc, sizeof(*(d->data)));
+}
+*/
+
+static inline void stack_ptr_init_size(stack_ptr *d, const size_t alloc) {
+ d->nmemb = 0;
+ d->alloc = alloc;
+
+ d->data = calloc(d->alloc, sizeof(*(d->data)));
+}
+
+static inline void stack_ptr_clear(stack_ptr *d) {
+ d->nmemb = 0;
+ free(d->data);
+ d->data = NULL;
+}
+
+static inline void stack_ptr_push(stack_ptr *d, void *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++;
+}
+
+/*
+static inline void* stack_ptr_get(const stack_ptr *d, const size_t i) {
+ return d->data[i];
+}
+
+
+static inline void* stack_ptr_getlast(const stack_ptr *d) {
+ return stack_ptr_get(d, d->nmemb - 1);
+}
+
+
+static inline void* stack_ptr_pop(stack_ptr *d) {
+ if (d->nmemb == 0)
+ return STACK_PTR_EMPTY_POP;
+ void* r = stack_ptr_getlast(d);
+ d->nmemb--;
+ return r;
+}
+*/
+
+void dict_init_size(dict_t *d, const size_t alloc) {
+ d->nalloc = alloc;
+ d->nelts = 0;
+ d->keys = calloc(d->nalloc, sizeof(*d->keys));
+ d->values = calloc(d->nalloc, sizeof(*d->values));
+
+ size_t i;
+ for (i = 0; i < d->nalloc; i++) {
+ stack_sd_init_size(&d->keys[i], DICT_DEFAULT_STACK_SIZE);
+ stack_ptr_init_size(&d->values[i], DICT_DEFAULT_STACK_SIZE);
+ }
+}
+
+void dict_init(dict_t *d) { dict_init_size(d, DICT_DEFAULT_SIZE); }
+
+void dict_clear(dict_t *d) {
+ size_t i;
+ for (i = 0; i < d->nalloc; i++) {
+ stack_sd_clear(&d->keys[i]);
+ stack_ptr_clear(&d->values[i]);
+ }
+
+ d->nalloc = 0;
+ d->nelts = 0;
+ free(d->keys);
+ free(d->values);
+ d->keys = NULL;
+ d->values = NULL;
+}
+
+void *dict_lookup(dict_t *d, sd k) {
+ uint64_t h = sd_hash(&k);
+ size_t i = h % d->nalloc;
+ int stack_idx = stack_sd_lookup(&d->keys[i], k);
+
+ if (stack_idx == STACK_SD_LOOKUP_NOT_FOUND) {
+ return NULL;
+ }
+
+ return (d->values[i]).data[stack_idx];
+}
+
+#include <stdio.h>
+
+void dict_insert(dict_t *d, sd k, void *value) {
+ uint64_t h = sd_hash(&k);
+ size_t i = h % d->nalloc;
+ int stack_idx = stack_sd_lookup(&d->keys[i], k);
+
+ if (stack_idx == STACK_SD_LOOKUP_NOT_FOUND) {
+ stack_sd_push(&(d->keys[i]), k);
+ stack_ptr_push(&(d->values[i]), value);
+ d->nelts++;
+ } else {
+ (d->values[i]).data[stack_idx] = value;
+ }
+}
diff --git a/utils/dict.h b/utils/dict.h
@@ -0,0 +1,33 @@
+#ifndef DICT_H
+#define DICT_H
+
+#include "stack_sd.h"
+
+#define DICT_DEFAULT_SIZE 255
+#define DICT_DEFAULT_STACK_SIZE 2
+#define STACK_PTR_EMPTY_POP (NULL)
+#define DICT_LOOKUP_NOT_FOUND (STACK_SD_LOOKUP_NOT_FOUND) // == -1
+
+typedef struct {
+ size_t nmemb;
+ size_t alloc;
+
+ void **data;
+} stack_ptr;
+
+typedef struct {
+ size_t nelts;
+ size_t nalloc;
+
+ stack_sd *keys;
+ stack_ptr *values;
+} dict_t;
+
+void dict_init_size(dict_t *d, const size_t alloc);
+void dict_init(dict_t *d);
+void dict_clear(dict_t *d);
+void *dict_lookup(dict_t *d, sd k);
+void dict_insert(dict_t *t, sd k, void *v);
+void print_dict(dict_t *d);
+
+#endif
diff --git a/utils/fheap.c b/utils/fheap.c
@@ -0,0 +1,249 @@
+#include "fheap.h"
+
+void fnode_init(fnode_t *node, const uint64_t value, void *data) {
+ node->children = NULL;
+ node->parent = NULL;
+ node->left = node;
+ node->right = node;
+ node->nchildren = 0;
+ node->marked = 0;
+
+ node->value = value;
+ node->data = data;
+}
+
+void fnode_clear(fnode_t *node) {
+ // clear children recursively
+ fnode_t *c, *d;
+ size_t n = node->nchildren;
+ c = node->children;
+ size_t i;
+ for (i = 0; i < n; i++) {
+ d = c->right;
+ fnode_clear(c);
+ c = d;
+ }
+
+ free(node);
+}
+
+void fheap_init(fheap_t *heap) {
+ heap->min = NULL;
+ heap->head = NULL;
+ heap->n = 0;
+}
+
+void fheap_clear(fheap_t *heap) {
+ fnode_t *c = heap->head;
+ fnode_t *d = c->right;
+
+ while (d != c) {
+ fnode_t *t = d->right;
+ fnode_clear(d);
+ d = t;
+ }
+ fnode_clear(c);
+
+ heap->min = NULL;
+ heap->head = NULL;
+ heap->n = 0;
+}
+
+static inline void insert_leftof(fnode_t *x, fnode_t *y) {
+ fnode_t *x_left = x->left;
+ x->left = y;
+ y->parent = x->parent;
+ y->right = x;
+ y->left = x_left;
+ x_left->right = y;
+}
+
+fnode_t *fheap_insert(fheap_t *heap, const uint64_t value, void *data) {
+ fnode_t *nnode = malloc(sizeof(*nnode));
+
+ fnode_init(nnode, value, data);
+
+ if (heap->min == NULL) {
+ heap->head = nnode;
+ heap->min = nnode;
+ } else {
+ insert_leftof(heap->head, nnode);
+ if (nnode->value < (heap->min)->value) {
+ heap->min = nnode;
+ }
+ }
+
+ heap->n++;
+
+ return nnode;
+}
+
+static inline void remove_node(fnode_t *x) {
+ (x->left)->right = x->right;
+ (x->right)->left = x->left;
+}
+
+static inline void fheap_link(fheap_t *heap, fnode_t *y, fnode_t *x) {
+ remove_node(y);
+ if (heap->head == y)
+ heap->head = y->right;
+ if (x->children != NULL) {
+ insert_leftof(x->children, y);
+ } else {
+ x->children = y;
+ y->parent = x;
+ y->left = y;
+ y->right = y;
+ x->nchildren = 0;
+ }
+ x->nchildren++;
+ y->marked = 0;
+}
+
+static inline void consolidate(fheap_t *heap) {
+ size_t i, deg;
+ fnode_t *a[heap->n];
+
+ for (i = 0; i < heap->n; i++)
+ a[i] = NULL;
+
+ fnode_t *c = heap->head;
+ fnode_t *head_list[heap->n];
+ size_t nheads = 0;
+ do {
+ head_list[nheads] = c;
+ nheads++;
+ c = c->right;
+ } while (c != heap->head);
+
+ size_t max_deg = 0;
+
+ fnode_t *x, *y;
+ for (i = 0; i < nheads; i++) {
+ c = head_list[i];
+
+ deg = c->nchildren;
+ x = c;
+ while (a[deg] != NULL) {
+ if (x->value > a[deg]->value) {
+ y = x;
+ x = a[deg];
+ } else {
+ y = a[deg];
+ }
+
+ fheap_link(heap, y, x);
+
+ a[deg] = NULL;
+ deg++;
+ }
+
+ a[deg] = x;
+
+ if (deg > max_deg)
+ max_deg = deg;
+ }
+
+ heap->head = NULL;
+ heap->min = NULL;
+ for (i = 0; i < max_deg + 1; i++) {
+ if (a[i] != NULL) {
+ if (heap->head == NULL) {
+ heap->head = a[i];
+ heap->min = a[i];
+ a[i]->left = a[i];
+ a[i]->right = a[i];
+ } else {
+ insert_leftof(heap->head, a[i]);
+ if (a[i]->value < (heap->min)->value)
+ heap->min = a[i];
+ }
+ }
+ }
+}
+
+fnode_t *fheap_extract_min_node(fheap_t *heap) {
+ fnode_t *z = heap->min;
+ fnode_t *c, *d;
+ if (z != NULL) {
+ if (z->nchildren > 0) {
+ c = z->children;
+ do {
+ d = c->right;
+ c->parent = NULL;
+ insert_leftof(heap->head, c);
+ c = d;
+ } while (c != z->children);
+ z->children = NULL;
+ }
+
+ remove_node(z);
+
+ if (z == z->right) {
+ heap->min = NULL;
+ heap->head = NULL;
+ } else {
+ heap->min = z->right;
+ if (heap->head == z)
+ heap->head = z->right;
+ consolidate(heap);
+ }
+
+ heap->n--;
+ }
+
+ return z;
+}
+
+uint64_t fheap_extract_min(void **data, fheap_t *heap) {
+ fnode_t *z = fheap_extract_min_node(heap);
+
+ uint64_t value = z->value;
+ *data = z->data;
+
+ z->nchildren = 0;
+ z->children = NULL;
+ fnode_clear(z);
+
+ return value;
+}
+
+static inline void fheap_cut(fheap_t *heap, fnode_t *x, fnode_t *y) {
+ remove_node(x);
+ if (y->children == x) {
+ if (x->right == x) {
+ y->children = NULL;
+ } else {
+ y->children = x->right;
+ }
+ }
+ y->nchildren--;
+
+ insert_leftof(heap->head, x);
+ x->parent = NULL;
+ x->marked = 0;
+}
+
+static void fheap_cascading_cut(fheap_t *heap, fnode_t *y) {
+ fnode_t *z = y->parent;
+ if (z != NULL) {
+ if (y->marked == 0) {
+ y->marked = 1;
+ } else {
+ fheap_cut(heap, y, z);
+ fheap_cascading_cut(heap, z);
+ }
+ }
+}
+
+void fheap_decrease_value(fheap_t *heap, fnode_t *node, const uint64_t value) {
+ node->value = value;
+ fnode_t *y = node->parent;
+ if (y != NULL && node->value < y->value) {
+ fheap_cut(heap, node, y);
+ fheap_cascading_cut(heap, y);
+ }
+
+ if (node->value < (heap->min)->value)
+ heap->min = node;
+}
diff --git a/utils/fheap.h b/utils/fheap.h
@@ -0,0 +1,40 @@
+#ifndef FHEAP_H
+#define FHEAP_H
+
+#include <assert.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+typedef struct fnode_struct {
+ uint64_t value;
+ void *data;
+
+ struct fnode_struct *parent;
+ struct fnode_struct *children;
+ size_t nchildren;
+ uint64_t marked;
+
+ struct fnode_struct *left;
+ struct fnode_struct *right;
+} fnode_t;
+
+typedef struct {
+ size_t n;
+ fnode_t *min;
+ fnode_t *head;
+} fheap_t;
+
+void fnode_init(fnode_t *node, const uint64_t value, void *data);
+void fnode_clear(fnode_t *node);
+
+void fheap_init(fheap_t *heap);
+void fheap_clear(fheap_t *heap);
+
+fnode_t *fheap_insert(fheap_t *heap, const uint64_t value, void *data);
+fnode_t *fheap_extract_min_node(fheap_t *heap);
+uint64_t fheap_extract_min(void **data, fheap_t *heap);
+
+void fheap_decrease_value(fheap_t *heap, fnode_t *node, const uint64_t value);
+
+#endif
diff --git a/utils/graph.c b/utils/graph.c
@@ -0,0 +1,22 @@
+#include "graph.h"
+
+void graph_init(graph_t *g, const size_t n) {
+ g->n = n;
+ g->nbrs = malloc(n * sizeof(*(g->nbrs)));
+
+ size_t i;
+ for (i = 0; i < n; i++)
+ stack_u64_init(&g->nbrs[i]);
+}
+
+void graph_clear(graph_t *g) {
+ size_t i;
+ for (i = 0; i < g->n; i++)
+ stack_u64_clear(&g->nbrs[i]);
+ free(g->nbrs);
+}
+
+void graph_add_edge(graph_t *g, const size_t v, const size_t w) {
+ stack_u64_push(&g->nbrs[v], w);
+ stack_u64_push(&g->nbrs[w], v);
+}
diff --git a/utils/graph.h b/utils/graph.h
@@ -0,0 +1,15 @@
+#ifndef GRAPH_H
+#define GRAPH_H
+
+#include "stack_u64.h"
+
+typedef struct {
+ size_t n;
+ stack_u64 *nbrs;
+} graph_t;
+
+void graph_init(graph_t *g, const size_t n);
+void graph_clear(graph_t *g);
+void graph_add_edge(graph_t *g, const size_t v, const size_t w);
+
+#endif
diff --git a/utils/ht.c b/utils/ht.c
@@ -0,0 +1,40 @@
+#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/play/Makefile b/utils/play/Makefile
@@ -0,0 +1,30 @@
+CC=clang
+CFLAGS+=-std=c99 -pedantic -Wall -Werror -Wstrict-prototypes
+CFLAGS+=-Wmissing-prototypes -Wmissing-declarations -Wshadow
+CFLAGS+=-Wpointer-arith -Wcast-qual -Wsign-compare
+CFLAGS+=-O2 -g
+CFLAGS+=-fstack-protector-all -Wtype-limits -fno-common
+CFLAGS+=-fno-builtin
+CFLAGS+=-I/usr/local/include
+LDFLAGS=-lcunit -L/usr/local/lib
+
+OBJS=\
+ ../reading.o \
+ ../stack_u64.o \
+ ../wdg.o \
+ ../fheap.o
+
+all: utils tests
+
+utils:
+ make -C ../
+
+tests: tests.c $(TEST_OBJS)
+ $(CC) $(CFLAGS) $(LDFLAGS) -o tests tests.c $(OBJS)
+ ./tests
+
+.c.o:
+ $(CC) $(CFLAGS) -c $<
+
+clean:
+ rm -rf tests $(TEST_OBJS)
diff --git a/utils/play/tests.c b/utils/play/tests.c
@@ -0,0 +1,38 @@
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "../fheap.h"
+
+int main() {
+ fheap_t heap;
+
+ fheap_init(&heap);
+
+ uint64_t data[4] = {1, 2, 3, 4};
+ uint64_t ddata;
+
+ fheap_insert(&heap, 3, &(data[0]));
+ fheap_insert(&heap, 7, &(data[1]));
+ fheap_insert(&heap, 13, &(data[2]));
+ fheap_insert(&heap, 0, &(data[3]));
+
+ fheap_print(&heap);
+
+ void *pdata;
+ ddata = fheap_extract_min(&pdata, &heap);
+ printf("[+] extracted (%llu) with value %llu\n", *(uint64_t *)pdata, ddata);
+ fheap_print(&heap);
+
+ ddata = fheap_extract_min(&pdata, &heap);
+ printf("[+] extracted (%llu) with value %llu\n", *(uint64_t *)pdata, ddata);
+ fheap_print(&heap);
+
+ ddata = fheap_extract_min(&pdata, &heap);
+ printf("[+] extracted (%llu) with value %llu\n", *(uint64_t *)pdata, ddata);
+ fheap_print(&heap);
+
+ ddata = fheap_extract_min(&pdata, &heap);
+ printf("[+] extracted (%llu) with value %llu\n", *(uint64_t *)pdata, ddata);
+ fheap_print(&heap);
+}
diff --git a/utils/reading.c b/utils/reading.c
@@ -0,0 +1,158 @@
+#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;
+}
+
+char *sread_next_i64(int64_t *n, char *s) {
+ char *fc = s;
+
+ // skip to the next numerival char or -
+ while (*fc != '\0') {
+ if (('0' <= *fc && *fc <= '9') || *fc == '-')
+ break;
+ fc++;
+ }
+ if (*fc == '\0')
+ return NULL;
+
+ // -1 if starts with '-', otherwise +1
+ int64_t sign = 1;
+ if (*fc == '-') {
+ sign = -1;
+ fc++;
+ // if no following digit this is interpreted as -0 == 0.
+ if (*fc < '0' || *fc > '9') {
+ *n = 0;
+ if (*fc == '\0')
+ return NULL;
+ return fc;
+ }
+ }
+
+ // read an unsigned int, starts with digit
+ *n = (int64_t)(*fc - '0');
+ fc++;
+ while (*fc != EOF) {
+ if ('0' <= *fc && *fc <= '9') {
+ *n = (*n) * 10L + (int64_t)(*fc - '0');
+ } else {
+ break;
+ }
+ fc++;
+ }
+ // apply sign
+ *n *= sign;
+
+ if (*fc == '\0')
+ return NULL;
+
+ return fc;
+}
diff --git a/utils/reading.h b/utils/reading.h
@@ -0,0 +1,82 @@
+#ifndef READING_H
+#define READING_H
+
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.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);
+
+/**
+ * Read the next int64_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 int64_t. Substrings '-' that are not followed
+ * by a digit are interpreted as 0.
+ *
+ * @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_i64(int64_t *n, char *s);
+
+#endif
diff --git a/utils/sd.c b/utils/sd.c
@@ -0,0 +1,60 @@
+#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; }
diff --git a/utils/sd.h b/utils/sd.h
@@ -0,0 +1,103 @@
+#ifndef SD_H
+#define SD_H
+
+#include <stdint.h>
+#include <stdlib.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
diff --git a/utils/set_u64.c b/utils/set_u64.c
@@ -0,0 +1,70 @@
+#include "set_u64.h"
+
+void set_u64_init_size(set_u64_t *s, const size_t size) {
+ size_t i;
+ s->nalloc = size;
+ s->nelts = 0;
+
+ s->head = malloc((s->nalloc) * sizeof(*(s->head)));
+
+ for (i = 0; i < s->nalloc; i++)
+ LIST_INIT(&(s->head[i]));
+}
+
+void set_u64_init(set_u64_t *s) { set_u64_init_size(s, SET_U64_DEFAULT_SIZE); }
+
+void set_u64_clear(set_u64_t *s) {
+ size_t i;
+ struct list_entry *n1;
+
+ for (i = 0; i < s->nalloc; i++) {
+ while (!LIST_EMPTY(&(s->head[i]))) {
+ n1 = LIST_FIRST(&(s->head[i]));
+ LIST_REMOVE(n1, entries);
+ free(n1);
+ }
+ }
+
+ free(s->head);
+ s->head = NULL;
+ s->nalloc = 0;
+ s->nelts = 0;
+}
+
+static inline size_t u64_hash(const uint64_t c) { return (size_t)c; }
+
+static inline le_t *list_lookup(struct listhead h, uint64_t v) {
+ le_t *np;
+ LIST_FOREACH(np, &h, entries) {
+ if (np->value == v)
+ return np;
+ }
+
+ return NULL;
+}
+
+size_t set_u64_lookup(le_t *r, set_u64_t *s, uint64_t v) {
+ size_t i = u64_hash(v) % s->nalloc;
+ le_t *elt = list_lookup(s->head[i], v);
+
+ if (elt != NULL) {
+ *r = *elt;
+ return i;
+ }
+
+ return SIZE_MAX;
+}
+
+int set_u64_insert(set_u64_t *s, uint64_t v) {
+ size_t i = u64_hash(v) % s->nalloc;
+
+ if (list_lookup(s->head[i], v) == NULL) {
+ le_t *new = malloc(sizeof(*new));
+ new->value = v;
+ LIST_INSERT_HEAD(&(s->head[i]), new, entries);
+ s->nelts++;
+ return 1;
+ }
+
+ return 0;
+}
diff --git a/utils/set_u64.h b/utils/set_u64.h
@@ -0,0 +1,28 @@
+#ifndef SET_U64_H
+#define SET_U64_H
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <sys/queue.h>
+
+#define SET_U64_DEFAULT_SIZE (255)
+
+typedef struct list_entry {
+ uint64_t value;
+ LIST_ENTRY(list_entry) entries;
+} le_t;
+
+typedef struct {
+ size_t nelts;
+ size_t nalloc;
+
+ LIST_HEAD(listhead, list_entry) * head;
+} set_u64_t;
+
+void set_u64_init_size(set_u64_t *s, const size_t size);
+void set_u64_init(set_u64_t *s);
+void set_u64_clear(set_u64_t *s);
+size_t set_u64_lookup(le_t *r, set_u64_t *s, uint64_t v);
+int set_u64_insert(set_u64_t *s, uint64_t v);
+
+#endif
diff --git a/utils/set_u64p.c b/utils/set_u64p.c
@@ -0,0 +1,75 @@
+#include "set_u64p.h"
+
+void set_u64p_init_size(set_u64p_t *s, const size_t size) {
+ size_t i;
+ s->nalloc = size;
+ s->nelts = 0;
+
+ s->head = malloc((s->nalloc) * sizeof(*(s->head)));
+
+ for (i = 0; i < s->nalloc; i++)
+ LIST_INIT(&(s->head[i]));
+}
+
+void set_u64p_init(set_u64p_t *s) {
+ set_u64p_init_size(s, SET_U64_DEFAULT_SIZE);
+}
+
+void set_u64p_clear(set_u64p_t *s) {
+ size_t i;
+ struct list_entry *n1;
+
+ for (i = 0; i < s->nalloc; i++) {
+ while (!LIST_EMPTY(&(s->head[i]))) {
+ n1 = LIST_FIRST(&(s->head[i]));
+ LIST_REMOVE(n1, entries);
+ free(n1);
+ }
+ }
+
+ free(s->head);
+ s->head = NULL;
+ s->nalloc = 0;
+ s->nelts = 0;
+}
+
+static inline size_t u64p_hash(const uint64_t *pair) {
+ return (size_t)(pair[0] ^ pair[1]);
+}
+
+static inline le_t *list_lookup(struct lh_u64p h, uint64_t *pair) {
+ le_t *np;
+ LIST_FOREACH(np, &h, entries) {
+ if (np->v[0] == pair[0] && np->v[1] == pair[1])
+ return np;
+ }
+
+ return NULL;
+}
+
+size_t set_u64p_lookup(le_t *r, set_u64p_t *s, uint64_t *pair) {
+ size_t i = u64p_hash(pair) % s->nalloc;
+ le_t *elt = list_lookup(s->head[i], pair);
+
+ if (elt != NULL) {
+ *r = *elt;
+ return i;
+ }
+
+ return SIZE_MAX;
+}
+
+int set_u64p_insert(set_u64p_t *s, uint64_t *pair) {
+ size_t i = u64p_hash(pair) % s->nalloc;
+
+ if (list_lookup(s->head[i], pair) == NULL) {
+ le_t *new = malloc(sizeof(*new));
+ new->v[0] = pair[0];
+ new->v[1] = pair[1];
+ LIST_INSERT_HEAD(&(s->head[i]), new, entries);
+ s->nelts++;
+ return 1;
+ }
+
+ return 0;
+}
diff --git a/utils/set_u64p.h b/utils/set_u64p.h
@@ -0,0 +1,28 @@
+#ifndef SET_U64P_H
+#define SET_U64P_H
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <sys/queue.h>
+
+#define SET_U64_DEFAULT_SIZE (255)
+
+typedef struct list_entry {
+ uint64_t v[2];
+ LIST_ENTRY(list_entry) entries;
+} le_t;
+
+typedef struct {
+ size_t nelts;
+ size_t nalloc;
+
+ LIST_HEAD(lh_u64p, list_entry) * head;
+} set_u64p_t;
+
+void set_u64p_init_size(set_u64p_t *s, const size_t size);
+void set_u64p_init(set_u64p_t *s);
+void set_u64p_clear(set_u64p_t *s);
+size_t set_u64p_lookup(le_t *r, set_u64p_t *s, uint64_t *pair);
+int set_u64p_insert(set_u64p_t *s, uint64_t *pair);
+
+#endif
diff --git a/utils/smallset.c b/utils/smallset.c
@@ -0,0 +1,100 @@
+#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_minus(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] - (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) - 8; 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,132 @@
+/**
+ * Implementation of "small sets" (subsets of [n], where n is not big).
+ */
+#ifndef SMALLSET_H_
+#define SMALLSET_H_
+
+#include <assert.h>
+#include <stdint.h>
+#include <stdio.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);
+
+/**
+ * Compute the set subtraction 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 difference
+ * @param a pointer to set to subtract from
+ * @param b pointer to set to subtract
+ */
+void smallset_minus(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,53 @@
+#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) {
+ size_t 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 "sd.h"
+#include <stdint.h>
+#include <stdlib.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,38 @@
+#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;
+}
diff --git a/utils/stack_str.h b/utils/stack_str.h
@@ -0,0 +1,70 @@
+#ifndef STACK_STR_H
+#define STACK_STR_H
+
+#include <stdint.h>
+#include <stdlib.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
diff --git a/utils/stack_u64.c b/utils/stack_u64.c
@@ -0,0 +1,40 @@
+#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;
+}
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 <stdint.h>
+#include <stdlib.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
diff --git a/utils/test/Makefile b/utils/test/Makefile
@@ -0,0 +1,43 @@
+CC=clang
+CFLAGS+=-std=c99 -pedantic -Wall -Werror -Wstrict-prototypes
+CFLAGS+=-Wmissing-prototypes -Wmissing-declarations -Wshadow
+CFLAGS+=-Wpointer-arith -Wcast-qual -Wsign-compare
+CFLAGS+=-O2 -g
+CFLAGS+=-fstack-protector-all -Wtype-limits -fno-common
+CFLAGS+=-fno-builtin
+CFLAGS+=-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 \
+ test_set_u64.o
+OBJS=\
+ ../reading.o \
+ ../stack_u64.o \
+ ../stack_str.o \
+ ../sd.o \
+ ../smallset.o \
+ ../stack_sd.o \
+ ../ht.o \
+ ../set_u64.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 "../ht.h"
+#include <CUnit/Basic.h>
+
+void test_ht_init(void);
+void test_ht_lookup(void);
+void test_ht_insert(void);
+
+#endif
diff --git a/utils/test/test_reading.c b/utils/test/test_reading.c
@@ -0,0 +1,61 @@
+#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);
+void test_reading_readlines(void);
+void test_reading_read_next_u64(void);
+void test_reading_sread_next_u64(void);
+
+#endif
diff --git a/utils/test/test_sd.c b/utils/test/test_sd.c
@@ -0,0 +1,93 @@
+#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 "../sd.h"
+#include <CUnit/Basic.h>
+
+void test_sd_init(void);
+void test_sd_cmp(void);
+void test_sd_hash(void);
+void test_sd_conv_u64(void);
+void test_sd_get_str(void);
+
+#endif
diff --git a/utils/test/test_set_u64.c b/utils/test/test_set_u64.c
@@ -0,0 +1,19 @@
+#include "test_set_u64.h"
+
+void test_set_u64_init() {
+ set_u64_t s;
+
+ set_u64_init(&s);
+ CU_ASSERT(s.nelts == 0);
+ CU_ASSERT(s.nalloc == SET_U64_DEFAULT_SIZE);
+ CU_ASSERT(LIST_EMPTY(&(s.head[0])));
+
+ set_u64_clear(&s);
+
+ set_u64_init_size(&s, 23);
+ CU_ASSERT(s.nelts == 0);
+ CU_ASSERT(s.nalloc == 23);
+ CU_ASSERT(LIST_EMPTY(&(s.head[0])));
+
+ set_u64_clear(&s);
+}
diff --git a/utils/test/test_set_u64.h b/utils/test/test_set_u64.h
@@ -0,0 +1,9 @@
+#ifndef TEST_SET_U64_H
+#define TEST_SET_U64_H
+
+#include "../set_u64.h"
+#include <CUnit/Basic.h>
+
+void test_set_u64_init(void);
+
+#endif
diff --git a/utils/test/test_smallset.c b/utils/test/test_smallset.c
@@ -0,0 +1,207 @@
+#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_minus() {
+ 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_minus(&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,17 @@
+#ifndef TEST_SMALLSET_H
+#define TEST_SMALLSET_H
+
+#include "../smallset.h"
+#include <CUnit/Basic.h>
+
+void test_smallset_init(void);
+void test_smallset_insert(void);
+void test_smallset_lookup(void);
+void test_smallset_intersection(void);
+void test_smallset_minus(void);
+void test_smallset_tonstr(void);
+void test_smallset_getone(void);
+void test_smallset_empty(void);
+void test_smallset_cardinality(void);
+
+#endif
diff --git a/utils/test/test_stack_sd.c b/utils/test/test_stack_sd.c
@@ -0,0 +1,140 @@
+#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 "../stack_sd.h"
+#include <CUnit/Basic.h>
+
+void test_stack_sd_init(void);
+void test_stack_sd_push(void);
+void test_stack_sd_get(void);
+void test_stack_sd_getlast(void);
+void test_stack_sd_pop(void);
+void test_stack_sd_lookup(void);
+
+#endif
diff --git a/utils/test/test_stack_str.c b/utils/test/test_stack_str.c
@@ -0,0 +1,74 @@
+#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 "../stack_str.h"
+#include <CUnit/Basic.h>
+
+void test_stack_str_init(void);
+void test_stack_str_push(void);
+void test_stack_str_get_getlast(void);
+void test_stack_str_pop(void);
+
+#endif
diff --git a/utils/test/test_stack_u64.c b/utils/test/test_stack_u64.c
@@ -0,0 +1,68 @@
+#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 "../stack_u64.h"
+#include <CUnit/Basic.h>
+
+void test_stack_u64_init(void);
+void test_stack_u64_push(void);
+void test_stack_u64_get_getlast(void);
+void test_stack_u64_pop(void);
+
+#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,92 @@
+#include <CUnit/Basic.h>
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "test_ht.h"
+#include "test_reading.h"
+#include "test_sd.h"
+#include "test_set_u64.h"
+#include "test_smallset.h"
+#include "test_stack_sd.h"
+#include "test_stack_str.h"
+#include "test_stack_u64.h"
+
+static 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);
+}
+
+static 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 - minus()", test_smallset_minus);
+ 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);
+
+ add_test(s_all, "set_u64 - init()", test_set_u64_init);
+
+ /* 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();
+}
diff --git a/utils/wdg.c b/utils/wdg.c
@@ -0,0 +1,75 @@
+#include "wdg.h"
+
+void wdg_init(wdg_t *g, const size_t n) {
+ g->n = n;
+ g->nbrs = malloc(n * sizeof(*(g->nbrs)));
+ g->weight = malloc(n * sizeof(*(g->weight)));
+
+ size_t i;
+ for (i = 0; i < n; i++) {
+ stack_u64_init(&g->nbrs[i]);
+ stack_u64_init(&g->weight[i]);
+ }
+}
+
+void wdg_clear(wdg_t *g) {
+ size_t i;
+ for (i = 0; i < g->n; i++) {
+ stack_u64_clear(&g->nbrs[i]);
+ stack_u64_clear(&g->nbrs[i]);
+ }
+ free(g->nbrs);
+ free(g->weight);
+}
+
+void wdg_add_edge(wdg_t *g, const size_t v, const size_t w, uint64_t weight) {
+ stack_u64_push(&g->nbrs[v], w);
+ stack_u64_push(&g->weight[v], weight);
+}
+
+uint64_t wdg_dijkstra(wdg_t *g, const size_t source, const size_t target) {
+ size_t i;
+ uint64_t dist[g->n];
+ dist[source] = 0;
+ size_t prev[g->n];
+
+ fheap_t q;
+ fheap_init(&q);
+
+ size_t vertices[g->n];
+ fnode_t *qvertex[g->n];
+
+ for (i = 0; i < g->n; i++) {
+ vertices[i] = i;
+ if (i != source) {
+ dist[i] = UINT64_MAX;
+ prev[i] = SIZE_MAX;
+ }
+
+ qvertex[i] = fheap_insert(&q, dist[i], &(vertices[i]));
+ }
+
+ void *up;
+ size_t u, v;
+ uint64_t alt;
+ while (q.n > 0) {
+ size_t value = fheap_extract_min(&up, &q);
+ u = *(size_t *)up;
+ if (u == target)
+ break;
+ if (value == UINT64_MAX)
+ break;
+
+ for (i = 0; i < (g->nbrs[u]).nmemb; i++) {
+ v = (g->nbrs[u]).data[i];
+ alt = dist[u] + (g->weight[u]).data[i];
+ if (alt < dist[v]) {
+ dist[v] = alt;
+ prev[v] = u;
+ fheap_decrease_value(&q, qvertex[v], alt);
+ }
+ }
+ }
+
+ return dist[target];
+}
diff --git a/utils/wdg.h b/utils/wdg.h
@@ -0,0 +1,18 @@
+#ifndef WDG_H
+#define WDG_H
+
+#include "fheap.h"
+#include "stack_u64.h"
+
+typedef struct {
+ size_t n;
+ stack_u64 *nbrs;
+ stack_u64 *weight;
+} wdg_t;
+
+void wdg_init(wdg_t *g, const size_t n);
+void wdg_clear(wdg_t *g);
+void wdg_add_edge(wdg_t *g, const size_t v, const size_t w, uint64_t weight);
+uint64_t wdg_dijkstra(wdg_t *g, const size_t source, const size_t target);
+
+#endif