├── .gitignore ├── day-12 ├── small.txt ├── Makefile ├── input.txt └── 1_2.c ├── day-14 ├── small.txt ├── Makefile ├── anim.c └── 1_2.c ├── day-15 ├── Makefile ├── small.txt ├── input.txt └── prog.c ├── day-16 ├── Makefile ├── aoc.h ├── input.txt └── prog.c ├── day-18 ├── Makefile ├── small.txt ├── aoc.h └── prog.c ├── day-10 ├── Makefile ├── input.txt └── 1_2.c ├── day-9 ├── Makefile └── 1_2.c ├── day-5 ├── Makefile ├── adlist.h ├── 12.c ├── input.txt └── adlist.c ├── day-6 ├── Makefile ├── 1_2.c └── input.txt ├── day-7 ├── Makefile ├── 1_2.c └── input.txt ├── day-8 ├── Makefile ├── 1_2.c └── input.txt ├── day-13 ├── Makefile ├── small.txt └── 1_2.c ├── day-1 ├── Makefile ├── 1.c └── 2.c ├── day-2 ├── Makefile ├── 1.c └── 2.c ├── day-3 ├── Makefile ├── 1.c ├── 2.c └── input.txt ├── day-4 ├── Makefile ├── 1.c └── 2.c ├── day-11 ├── Makefile ├── input2.txt ├── input.txt ├── 1.c └── 2.c └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | a.out 2 | part-* 3 | *.dSYM 4 | prog 5 | -------------------------------------------------------------------------------- /day-12/small.txt: -------------------------------------------------------------------------------- 1 | Sabqponm 2 | abcryxxl 3 | accszExk 4 | acctuvwj 5 | abdefghi 6 | -------------------------------------------------------------------------------- /day-14/small.txt: -------------------------------------------------------------------------------- 1 | 498,4 -> 498,6 -> 496,6 2 | 503,4 -> 502,4 -> 502,9 -> 494,9 3 | -------------------------------------------------------------------------------- /day-15/Makefile: -------------------------------------------------------------------------------- 1 | all: prog 2 | 3 | prog: prog.c 4 | $(CC) prog.c -Wall -W -pedantic -O2 -o prog 5 | 6 | clean: 7 | rm -rf prog 8 | -------------------------------------------------------------------------------- /day-16/Makefile: -------------------------------------------------------------------------------- 1 | all: prog 2 | 3 | prog: prog.c 4 | $(CC) prog.c -g -ggdb -Wall -W -pedantic -O2 -o prog 5 | 6 | clean: 7 | rm -rf prog 8 | -------------------------------------------------------------------------------- /day-18/Makefile: -------------------------------------------------------------------------------- 1 | all: prog 2 | 3 | prog: prog.c 4 | $(CC) prog.c -g -ggdb -Wall -W -pedantic -O2 -o prog 5 | 6 | clean: 7 | rm -rf prog 8 | -------------------------------------------------------------------------------- /day-10/Makefile: -------------------------------------------------------------------------------- 1 | all: part-1_2 2 | 3 | part-1_2: 1_2.c 4 | $(CC) 1_2.c -Wall -W -pedantic -O2 -o part-1_2 5 | 6 | clean: 7 | rm -rf part-1_2 8 | -------------------------------------------------------------------------------- /day-9/Makefile: -------------------------------------------------------------------------------- 1 | all: part-1_2 2 | 3 | part-1_2: 1_2.c 4 | $(CC) 1_2.c -Wall -W -pedantic -O2 -o part-1_2 5 | 6 | clean: 7 | rm -rf part-1_2 8 | -------------------------------------------------------------------------------- /day-12/Makefile: -------------------------------------------------------------------------------- 1 | all: part-1 part-2 2 | 3 | part-1: 1_2.c 4 | $(CC) 1_2.c -Wall -W -pedantic -O2 -o part-1_2 5 | 6 | clean: 7 | rm -rf part-1_2 8 | -------------------------------------------------------------------------------- /day-5/Makefile: -------------------------------------------------------------------------------- 1 | all: part-12 2 | 3 | part-12: 12.c 4 | $(CC) 12.c adlist.c -Wall -W -pedantic -O2 -o part-12 5 | 6 | clean: 7 | rm -rf part-12 8 | -------------------------------------------------------------------------------- /day-6/Makefile: -------------------------------------------------------------------------------- 1 | all: part-1 part-2 2 | 3 | part-1: 1_2.c 4 | $(CC) 1_2.c -Wall -W -pedantic -O2 -o part-1_2 5 | 6 | clean: 7 | rm -rf part-1_2 8 | -------------------------------------------------------------------------------- /day-7/Makefile: -------------------------------------------------------------------------------- 1 | all: part-1 part-2 2 | 3 | part-1: 1_2.c 4 | $(CC) 1_2.c -Wall -W -pedantic -O2 -o part-1_2 5 | 6 | clean: 7 | rm -rf part-1_2 8 | -------------------------------------------------------------------------------- /day-8/Makefile: -------------------------------------------------------------------------------- 1 | all: part-1 part-2 2 | 3 | part-1: 1_2.c 4 | $(CC) 1_2.c -Wall -W -pedantic -O2 -o part-1_2 5 | 6 | clean: 7 | rm -rf part-1_2 8 | -------------------------------------------------------------------------------- /day-13/Makefile: -------------------------------------------------------------------------------- 1 | all: part-1 part-2 2 | 3 | part-1: 1_2.c 4 | $(CC) -g -ggdb 1_2.c -Wall -W -pedantic -O2 -o part-1_2 5 | 6 | clean: 7 | rm -rf part-1_2 8 | -------------------------------------------------------------------------------- /day-18/small.txt: -------------------------------------------------------------------------------- 1 | 2,2,2 2 | 1,2,2 3 | 3,2,2 4 | 2,1,2 5 | 2,3,2 6 | 2,2,1 7 | 2,2,3 8 | 2,2,4 9 | 2,2,6 10 | 1,2,5 11 | 3,2,5 12 | 2,1,5 13 | 2,3,5 14 | -------------------------------------------------------------------------------- /day-1/Makefile: -------------------------------------------------------------------------------- 1 | all: part-1 part-2 2 | 3 | part-1: 1.c 4 | $(CC) 1.c -Wall -W -pedantic -O2 -o part-1 5 | 6 | part-2: 2.c 7 | $(CC) 2.c -Wall -W -pedantic -O2 -o part-2 8 | 9 | clean: 10 | rm -rf part-1 part-2 11 | -------------------------------------------------------------------------------- /day-2/Makefile: -------------------------------------------------------------------------------- 1 | all: part-1 part-2 2 | 3 | part-1: 1.c 4 | $(CC) 1.c -Wall -W -pedantic -O2 -o part-1 5 | 6 | part-2: 2.c 7 | $(CC) 2.c -Wall -W -pedantic -O2 -o part-2 8 | 9 | clean: 10 | rm -rf part-1 part-2 11 | -------------------------------------------------------------------------------- /day-3/Makefile: -------------------------------------------------------------------------------- 1 | all: part-1 part-2 2 | 3 | part-1: 1.c 4 | $(CC) 1.c -Wall -W -pedantic -O2 -o part-1 5 | 6 | part-2: 2.c 7 | $(CC) 2.c -Wall -W -pedantic -O2 -o part-2 8 | 9 | clean: 10 | rm -rf part-1 part-2 11 | -------------------------------------------------------------------------------- /day-4/Makefile: -------------------------------------------------------------------------------- 1 | all: part-1 part-2 2 | 3 | part-1: 1.c 4 | $(CC) 1.c -Wall -W -pedantic -O2 -o part-1 5 | 6 | part-2: 2.c 7 | $(CC) 2.c -Wall -W -pedantic -O2 -o part-2 8 | 9 | clean: 10 | rm -rf part-1 part-2 11 | -------------------------------------------------------------------------------- /day-11/Makefile: -------------------------------------------------------------------------------- 1 | all: part-1 part-2 2 | 3 | part-1: 1.c 4 | $(CC) 1.c -Wall -W -pedantic -O2 -o part-1 5 | 6 | part-2: 2.c 7 | $(CC) 2.c -Wall -W -pedantic -O2 -o part-2 8 | 9 | clean: 10 | rm -rf part-1 part-2 11 | -------------------------------------------------------------------------------- /day-14/Makefile: -------------------------------------------------------------------------------- 1 | all: part-1 anim 2 | 3 | part-1: 1_2.c 4 | $(CC) 1_2.c -g -ggdb -Wall -W -pedantic -O2 -o part-1_2 5 | 6 | anim: anim.c 7 | $(CC) anim.c -g -ggdb -Wall -W -pedantic -O2 -o anim 8 | 9 | clean: 10 | rm -rf part-1_2 anim 11 | rm -rf *.dSYM 12 | -------------------------------------------------------------------------------- /day-13/small.txt: -------------------------------------------------------------------------------- 1 | [1,1,3,1,1] 2 | [1,1,5,1,1] 3 | 4 | [[1],[2,3,4]] 5 | [[1],4] 6 | 7 | [9] 8 | [[8,7,6]] 9 | 10 | [[4,4],4,4] 11 | [[4,4],4,4,4] 12 | 13 | [7,7,7,7] 14 | [7,7,7] 15 | 16 | [] 17 | [3] 18 | 19 | [[[]]] 20 | [[]] 21 | 22 | [1,[2,[3,[4,[5,6,7]]]],8,9] 23 | [1,[2,[3,[4,[5,6,0]]]],8,9] 24 | -------------------------------------------------------------------------------- /day-16/aoc.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | /* Wrappers crashing on out of memory. */ 5 | void *xalloc(size_t size) { 6 | void *p = malloc(size); 7 | if (!p) { 8 | fprintf(stderr,"Out of memory allocating %zu bytes\n", size); 9 | exit(1); 10 | } 11 | return p; 12 | } 13 | 14 | void *xrealloc(void *ptr, size_t size) { 15 | void *p = realloc(ptr,size); 16 | if (!p) { 17 | fprintf(stderr,"Out of memory allocating %zu bytes\n", size); 18 | exit(1); 19 | } 20 | return p; 21 | } 22 | -------------------------------------------------------------------------------- /day-18/aoc.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | /* Wrappers crashing on out of memory. */ 5 | void *xalloc(size_t size) { 6 | void *p = malloc(size); 7 | if (!p) { 8 | fprintf(stderr,"Out of memory allocating %zu bytes\n", size); 9 | exit(1); 10 | } 11 | return p; 12 | } 13 | 14 | void *xrealloc(void *ptr, size_t size) { 15 | void *p = realloc(ptr,size); 16 | if (!p) { 17 | fprintf(stderr,"Out of memory allocating %zu bytes\n", size); 18 | exit(1); 19 | } 20 | return p; 21 | } 22 | -------------------------------------------------------------------------------- /day-1/1.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main(void) { 5 | char buf[64]; 6 | long max = 0, sum = 0; 7 | while(fgets(buf,sizeof(buf),stdin) != NULL) { 8 | if (buf[0] == '\n' || buf[0] == '\r') { 9 | /* We are done with this Elf. Check if it is the winner. */ 10 | if (sum > max) max = sum; 11 | sum = 0; 12 | continue; 13 | } 14 | 15 | /* Sum this mean calories to the current Elf total calories. */ 16 | sum += strtol(buf,NULL,10); 17 | } 18 | printf("Elf with more cals has %ld cals.\n", max); 19 | return 0; 20 | } 21 | -------------------------------------------------------------------------------- /day-11/input2.txt: -------------------------------------------------------------------------------- 1 | Monkey 0: 2 | Starting items: 79, 98 3 | Operation: new = old * 19 4 | Test: divisible by 23 5 | If true: throw to monkey 2 6 | If false: throw to monkey 3 7 | 8 | Monkey 1: 9 | Starting items: 54, 65, 75, 74 10 | Operation: new = old + 6 11 | Test: divisible by 19 12 | If true: throw to monkey 2 13 | If false: throw to monkey 0 14 | 15 | Monkey 2: 16 | Starting items: 79, 60, 97 17 | Operation: new = old * old 18 | Test: divisible by 13 19 | If true: throw to monkey 1 20 | If false: throw to monkey 3 21 | 22 | Monkey 3: 23 | Starting items: 74 24 | Operation: new = old + 3 25 | Test: divisible by 17 26 | If true: throw to monkey 0 27 | If false: throw to monkey 1 28 | -------------------------------------------------------------------------------- /day-15/small.txt: -------------------------------------------------------------------------------- 1 | Sensor at x=2, y=18: closest beacon is at x=-2, y=15 2 | Sensor at x=9, y=16: closest beacon is at x=10, y=16 3 | Sensor at x=13, y=2: closest beacon is at x=15, y=3 4 | Sensor at x=12, y=14: closest beacon is at x=10, y=16 5 | Sensor at x=10, y=20: closest beacon is at x=10, y=16 6 | Sensor at x=14, y=17: closest beacon is at x=10, y=16 7 | Sensor at x=8, y=7: closest beacon is at x=2, y=10 8 | Sensor at x=2, y=0: closest beacon is at x=2, y=10 9 | Sensor at x=0, y=11: closest beacon is at x=2, y=10 10 | Sensor at x=20, y=14: closest beacon is at x=25, y=17 11 | Sensor at x=17, y=20: closest beacon is at x=21, y=22 12 | Sensor at x=16, y=7: closest beacon is at x=15, y=3 13 | Sensor at x=14, y=3: closest beacon is at x=15, y=3 14 | Sensor at x=20, y=1: closest beacon is at x=15, y=3 15 | -------------------------------------------------------------------------------- /day-1/2.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | /* Take a list of the 'n' top scores observed. */ 5 | void updateNMax(long *max, int n, long sum) { 6 | for (int j = 0; j < n; j++) { 7 | if (sum <= max[j]) continue; 8 | /* Move all the lower-rank scores one position down and update. */ 9 | for (int k = n-1; k > j; k--) max[k] = max[k-1]; 10 | max[j] = sum; 11 | break; 12 | } 13 | } 14 | 15 | int main(void) { 16 | char buf[64]; 17 | long max[3] = {0}, sum = 0; 18 | while(fgets(buf,sizeof(buf),stdin) != NULL) { 19 | if (buf[0] == '\n' || buf[0] == '\r') { 20 | /* We are done with this Elf. Update the top three scores. */ 21 | updateNMax(max,3,sum); 22 | sum = 0; 23 | continue; 24 | } 25 | 26 | /* Sum this meal calories to the current Elf total calories. */ 27 | sum += strtol(buf,NULL,10); 28 | } 29 | printf("Top three Elfs with more cals have %ld cals.\n", 30 | max[0]+max[1]+max[2]); 31 | return 0; 32 | } 33 | -------------------------------------------------------------------------------- /day-2/1.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | /* Given a game with me using shape 'me' and the opponent using 5 | * shape 'opp' (both 'A','B' or 'C') return the total score. */ 6 | int gameScore(int me, int opp) { 7 | /* Normalize shapes to 0-2: 8 | * 0 = Rock, 1 = Paper, 2 = Scissor. */ 9 | int m = me-'A'; 10 | int o = opp-'A'; 11 | 12 | /* Each entry scoremap[m][o] represents the outcome of the game in 13 | * form of a lookup table. */ 14 | int scoremap[3][3] = { 15 | {1+3, 1+0, 1+6}, 16 | {2+6, 2+3, 2+0}, 17 | {3+0, 3+6, 3+3} 18 | }; 19 | 20 | return scoremap[m][o]; 21 | } 22 | 23 | int main(void) { 24 | char buf[64]; 25 | 26 | FILE *fp = fopen("input.txt","r"); 27 | if (fp == NULL) { 28 | perror("Opening input file"); 29 | exit(1); 30 | } 31 | 32 | long score = 0; 33 | while(fgets(buf,sizeof(buf),fp) != NULL) { 34 | int opp = buf[0]; /* Opponent move. */ 35 | int me = buf[2]-'X'+'A'; /* My move (normalize to A,B,C). */ 36 | score += gameScore(me,opp); 37 | } 38 | fclose(fp); 39 | printf("%ld\n", score); 40 | return 0; 41 | } 42 | -------------------------------------------------------------------------------- /day-11/input.txt: -------------------------------------------------------------------------------- 1 | Monkey 0: 2 | Starting items: 59, 65, 86, 56, 74, 57, 56 3 | Operation: new = old * 17 4 | Test: divisible by 3 5 | If true: throw to monkey 3 6 | If false: throw to monkey 6 7 | 8 | Monkey 1: 9 | Starting items: 63, 83, 50, 63, 56 10 | Operation: new = old + 2 11 | Test: divisible by 13 12 | If true: throw to monkey 3 13 | If false: throw to monkey 0 14 | 15 | Monkey 2: 16 | Starting items: 93, 79, 74, 55 17 | Operation: new = old + 1 18 | Test: divisible by 2 19 | If true: throw to monkey 0 20 | If false: throw to monkey 1 21 | 22 | Monkey 3: 23 | Starting items: 86, 61, 67, 88, 94, 69, 56, 91 24 | Operation: new = old + 7 25 | Test: divisible by 11 26 | If true: throw to monkey 6 27 | If false: throw to monkey 7 28 | 29 | Monkey 4: 30 | Starting items: 76, 50, 51 31 | Operation: new = old * old 32 | Test: divisible by 19 33 | If true: throw to monkey 2 34 | If false: throw to monkey 5 35 | 36 | Monkey 5: 37 | Starting items: 77, 76 38 | Operation: new = old + 8 39 | Test: divisible by 17 40 | If true: throw to monkey 2 41 | If false: throw to monkey 1 42 | 43 | Monkey 6: 44 | Starting items: 74 45 | Operation: new = old * 2 46 | Test: divisible by 5 47 | If true: throw to monkey 4 48 | If false: throw to monkey 7 49 | 50 | Monkey 7: 51 | Starting items: 86, 85, 52, 86, 91, 95 52 | Operation: new = old + 6 53 | Test: divisible by 7 54 | If true: throw to monkey 4 55 | If false: throw to monkey 5 56 | -------------------------------------------------------------------------------- /day-3/1.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | int main(void) { 7 | char buf[64]; 8 | 9 | FILE *fp = fopen("input.txt","r"); 10 | if (fp == NULL) { 11 | perror("Opening input file"); 12 | exit(1); 13 | } 14 | 15 | long total_priority = 0; 16 | while(fgets(buf,sizeof(buf),fp) != NULL) { 17 | size_t l = strlen(buf); 18 | if (l < 2) continue; 19 | buf[l-1] = 0; l--; /* Remove newline at the end. */ 20 | 21 | assert(l%2 == 0); /* Specification of input says so. */ 22 | 23 | /* Scan the whole string left-to-right, populating an 'seen-item' 24 | * table for each item. However after the second half is reached 25 | * we detect already seen items. */ 26 | unsigned char seen[53] = {0}; 27 | for (size_t j = 0; j < l; j++) { 28 | int p; /* the current char priority. */ 29 | if (buf[j] >= 'a' && buf[j] <= 'z') 30 | p = buf[j]-'a'+1; 31 | else 32 | p = buf[j]-'A'+27; 33 | 34 | if (j == l/2) printf("|"); /* Mark second part of backpack. */ 35 | printf("%c", buf[j]); 36 | 37 | if (j < l/2) { 38 | seen[p] = 1; 39 | } else { 40 | if (seen[p]) { 41 | printf(" <-"); 42 | total_priority += p; 43 | break; /* Go to next backpack. */ 44 | } 45 | } 46 | } 47 | printf("\n"); 48 | } 49 | fclose(fp); 50 | printf("%ld\n", total_priority); 51 | return 0; 52 | } 53 | -------------------------------------------------------------------------------- /day-10/input.txt: -------------------------------------------------------------------------------- 1 | noop 2 | addx 5 3 | noop 4 | noop 5 | noop 6 | addx 1 7 | addx 2 8 | addx 5 9 | addx 2 10 | addx 5 11 | noop 12 | noop 13 | noop 14 | noop 15 | noop 16 | addx -12 17 | addx 18 18 | addx -1 19 | noop 20 | addx 3 21 | addx 5 22 | addx -5 23 | addx 7 24 | noop 25 | addx -36 26 | addx 18 27 | addx -16 28 | noop 29 | noop 30 | noop 31 | addx 5 32 | addx 2 33 | addx 5 34 | addx 2 35 | addx 13 36 | addx -6 37 | addx -4 38 | addx 5 39 | addx 2 40 | addx 4 41 | addx -3 42 | addx 2 43 | noop 44 | addx 3 45 | addx 2 46 | addx 5 47 | addx -40 48 | addx 25 49 | addx -22 50 | addx 25 51 | addx -21 52 | addx 5 53 | addx 3 54 | noop 55 | addx 2 56 | addx 19 57 | addx -10 58 | addx -4 59 | noop 60 | addx -4 61 | addx 7 62 | noop 63 | addx 3 64 | addx 2 65 | addx 5 66 | addx 2 67 | addx -26 68 | addx 27 69 | addx -36 70 | noop 71 | noop 72 | noop 73 | noop 74 | addx 4 75 | addx 6 76 | noop 77 | addx 12 78 | addx -11 79 | addx 2 80 | noop 81 | noop 82 | noop 83 | addx 5 84 | addx 5 85 | addx 2 86 | noop 87 | noop 88 | addx 1 89 | addx 2 90 | addx 5 91 | addx 2 92 | addx 1 93 | noop 94 | noop 95 | addx -38 96 | noop 97 | addx 9 98 | addx -4 99 | noop 100 | noop 101 | addx 7 102 | addx 10 103 | addx -9 104 | addx 2 105 | noop 106 | addx -9 107 | addx 14 108 | addx 5 109 | addx 2 110 | addx -24 111 | addx 25 112 | addx 2 113 | addx 5 114 | addx 2 115 | addx -30 116 | addx 31 117 | addx -38 118 | addx 7 119 | noop 120 | noop 121 | noop 122 | addx 1 123 | addx 21 124 | addx -16 125 | addx 8 126 | addx -4 127 | addx 2 128 | addx 3 129 | noop 130 | noop 131 | addx 5 132 | addx -2 133 | addx 5 134 | addx 3 135 | addx -1 136 | addx -1 137 | addx 4 138 | addx 5 139 | addx -38 140 | noop 141 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Just a couple of Advent of Code puzzles solved in C. When possible I try to use non obvious ways to solve the puzzle, to make things more creative: 2 | 3 | * Day 1 makes use of a simple streaming algorithm to retain top-N max entries. 4 | * Day 2 turns the logic of Rock, Paper, Scissor into a simple equation modulo N. 5 | * Day 3 makes use of bitmaps. 6 | * Day 4 shows abstracting with C structures. 7 | * Day 5 shows linked lists are useful. 8 | * Day 6 will solve in `O(N)` instead of `O(N*M)`. 9 | * Day 7 uses recursion and building ad-hoc data structures. 10 | * Day 8 walks data structures using a velocity vector. 11 | * Day 9 has nothing special. Just plain C code to simulate the rope. 12 | * Day 10 Simple but fun. Nothing special. Hints at cycles-exact emulation. 13 | * Day 11 Is an example of how you should not do parsing, assuming tons of stuff about your input. The program uses the LCM to avoid overflow. Yet I had to change int to long, and I did it brutally in `2.c`, with vim search and replace. 14 | * Day 12 implements the worst queue you'll ever see. 15 | * Day 13 uses a recursive parser that generates nested objects. 16 | * Day 14 makes AOC a bit boring. Maybe the last I'll do? Note that here it was not needed to simulate every sand grain again, ad I did. It is possible to remember the last position of the previous sand grain before it rested and continue from there. But the execution time would not change *practically*, the problem is too small. 17 | * Day 15 must show, otherwise no way to solve part 2, that it is possible to get smart when the search space is huge. 18 | * Day 16 Worst solution so far (back home saturday night, half drunk, can't do better than that): shows how a terrible heuristic can help you brute-force the solution. Warning: the program is quite broken and works for sure only on my `input.txt`, that you can find inside the directory. 19 | * Day 17 Skipped Tetris because of boredom & weekend. 20 | * Day 18 3D flood filling with recursive flood() function. 21 | -------------------------------------------------------------------------------- /day-10/1_2.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | int main(void) { 7 | int X = 1; /* X register. */ 8 | int cc = 0; /* Clock cycle. */ 9 | int signal_sum = 0; /* Puzzle 1 question. */ 10 | 11 | char buf[1024]; 12 | while(fgets(buf,sizeof(buf),stdin) != NULL) { 13 | /* Skip empty lines. */ 14 | size_t l = strlen(buf); 15 | if (l <= 1) continue; 16 | 17 | /* Strip newline. */ 18 | if (buf[l-1] == '\n') { 19 | buf[l-1] = 0; 20 | l--; 21 | } 22 | 23 | /* Parse instruction. */ 24 | char *p = strchr(buf,' '); /* Will be NULL for NOP. */ 25 | 26 | /* Check how many cycles this instruction 27 | * requires to execute. */ 28 | int wait = 1; /* Default: take 1 clock cycle. */ 29 | switch(buf[0]) { 30 | case 'a': wait = 2; break; /* ADD takes 2 cycles. */ 31 | } 32 | 33 | do { 34 | cc++; /* Start of this cycle. */ 35 | wait--; 36 | 37 | /* Draw CRT image. */ 38 | int hpos = (cc-1) % 40; /* Current horizonal position. */ 39 | int pixel = abs(X-hpos) < 2 ? '#' : '.'; 40 | printf("%c", pixel); 41 | if ((cc % 40) == 0) printf("\n"); 42 | 43 | /* We are in the DURING clock cycle "cc" */ 44 | if (((cc+20) % 40) == 0) { 45 | // printf("During cycle %d, X=%d\n", cc, X); 46 | signal_sum += cc*X; 47 | } 48 | } while(wait > 0); 49 | 50 | switch(buf[0]) { 51 | case 'n': /* NOP */ 52 | break; 53 | case 'a': /* ADD */ 54 | assert(p != NULL); 55 | X += atoi(p); 56 | break; 57 | default: assert(1 != 1); break; /* Shold never happen. */ 58 | } 59 | 60 | /* We are in the AFTER clock cycle "cc" */ 61 | } 62 | printf("Signal sum (puzzle 1): %d\n", signal_sum); 63 | } 64 | -------------------------------------------------------------------------------- /day-4/1.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #define min(a,b) ((a)<(b) ? (a):(b)) 7 | #define max(a,b) ((a)>(b) ? (a):(b)) 8 | 9 | /* Define the range data type. */ 10 | typedef struct { 11 | int start; 12 | int end; 13 | } range; 14 | 15 | range rangeNew(int s, int e) { 16 | range r = {s,e}; 17 | return r; 18 | } 19 | 20 | int rangeLen(range r) { 21 | return r.end-r.start; 22 | } 23 | 24 | range rangeOverlap(range a, range b) { 25 | return rangeNew(max(a.start,b.start),min(a.end,b.end)); 26 | } 27 | 28 | /* We expect the range to be in the form -. 29 | * Return 0 on parse error, otherwise 1 is returned. */ 30 | int parseRange(const char *s, range *r) { 31 | char buf[64]; 32 | size_t len = strlen(s); 33 | if (len < 2 || len+1 > sizeof(buf)) return 0; 34 | memcpy(buf,s,len+1); 35 | if (buf[len-1] == '\n') buf[len-1] = 0; /* newline -> nulterm. */ 36 | 37 | /* Split the two parts. */ 38 | char *p = strchr(buf,'-'); 39 | if (!p) return 0; 40 | *p = 0; 41 | p++; /* Seek the second number. */ 42 | r->start = atoi(buf); /* Assume input is sane here. */ 43 | r->end = atoi(p); /* Assume input is sane here. */ 44 | return 1; 45 | } 46 | 47 | int main(void) { 48 | char buf[64]; 49 | 50 | FILE *fp = fopen("input.txt","r"); 51 | if (fp == NULL) { 52 | perror("Opening input file"); 53 | exit(1); 54 | } 55 | 56 | long full_overlaps = 0; 57 | while(fgets(buf,sizeof(buf),fp) != NULL) { 58 | char *p = strchr(buf,','); 59 | if (!p) continue; 60 | *p = 0; 61 | p++; /* Seek second range. */ 62 | 63 | range a,b; 64 | parseRange(buf,&a); 65 | parseRange(p,&b); 66 | range overlap = rangeOverlap(a,b); 67 | if (rangeLen(overlap) == rangeLen(a) || 68 | rangeLen(overlap) == rangeLen(b)) 69 | { 70 | full_overlaps++; 71 | } 72 | } 73 | fclose(fp); 74 | printf("%ld\n", full_overlaps); 75 | return 0; 76 | } 77 | -------------------------------------------------------------------------------- /day-15/input.txt: -------------------------------------------------------------------------------- 1 | Sensor at x=3797530, y=3451192: closest beacon is at x=3316341, y=3328308 2 | Sensor at x=3779164, y=33938: closest beacon is at x=4608350, y=708806 3 | Sensor at x=1331810, y=3260896: closest beacon is at x=2075597, y=3280016 4 | Sensor at x=393374, y=696899: closest beacon is at x=2021690, y=453306 5 | Sensor at x=2928048, y=923094: closest beacon is at x=2021690, y=453306 6 | Sensor at x=2386726, y=3645023: closest beacon is at x=2075597, y=3280016 7 | Sensor at x=1900159, y=2381031: closest beacon is at x=1649961, y=2000000 8 | Sensor at x=2601378, y=2979844: closest beacon is at x=2218962, y=2701963 9 | Sensor at x=2254818, y=32199: closest beacon is at x=2021690, y=453306 10 | Sensor at x=2689643, y=375840: closest beacon is at x=2021690, y=453306 11 | Sensor at x=909141, y=2842547: closest beacon is at x=2218962, y=2701963 12 | Sensor at x=3915731, y=2454320: closest beacon is at x=4268501, y=1853073 13 | Sensor at x=1693574, y=1344104: closest beacon is at x=1649961, y=2000000 14 | Sensor at x=1760260, y=3297662: closest beacon is at x=2075597, y=3280016 15 | Sensor at x=1909567, y=3990737: closest beacon is at x=2075597, y=3280016 16 | Sensor at x=2097863, y=3179766: closest beacon is at x=2075597, y=3280016 17 | Sensor at x=3100489, y=3623847: closest beacon is at x=3104748, y=4102403 18 | Sensor at x=2746023, y=2432826: closest beacon is at x=2218962, y=2701963 19 | Sensor at x=3031245, y=3031354: closest beacon is at x=3316341, y=3328308 20 | Sensor at x=277094, y=1999350: closest beacon is at x=1649961, y=2000000 21 | Sensor at x=1763269, y=126349: closest beacon is at x=2021690, y=453306 22 | Sensor at x=3287624, y=2695420: closest beacon is at x=3316341, y=3328308 23 | Sensor at x=2371102, y=1745103: closest beacon is at x=1649961, y=2000000 24 | Sensor at x=3553438, y=1563379: closest beacon is at x=4268501, y=1853073 25 | Sensor at x=1529129, y=2735122: closest beacon is at x=2218962, y=2701963 26 | Sensor at x=2826220, y=3958350: closest beacon is at x=3104748, y=4102403 27 | Sensor at x=3999334, y=3912693: closest beacon is at x=3104748, y=4102403 28 | Sensor at x=240430, y=3829436: closest beacon is at x=-742036, y=3963149 29 | Sensor at x=3455748, y=3814861: closest beacon is at x=3316341, y=3328308 30 | -------------------------------------------------------------------------------- /day-3/2.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | /* Highlight in this implementation: 7 | * 8 | * - Use of a bitmap to save memory when the information to retain 9 | * is small. 10 | * - Avoid using a new loop to scan for in-all-three-backpacks item: 11 | * we can detect it ASAP once the byte value is 7 (all bits set). 12 | */ 13 | 14 | int main(void) { 15 | char buf[64]; 16 | 17 | FILE *fp = fopen("input.txt","r"); 18 | if (fp == NULL) { 19 | perror("Opening input file"); 20 | exit(1); 21 | } 22 | 23 | long total_priority = 0; 24 | long line_number = 0; 25 | unsigned char seen[53] = {0}; /* Array used to remember seen items. */ 26 | while(fgets(buf,sizeof(buf),fp) != NULL) { 27 | line_number++; 28 | int elf_id = line_number % 3; /* Elf in the group: 0, 1, or 2. */ 29 | 30 | size_t l = strlen(buf); 31 | if (l < 2) continue; 32 | buf[l-1] = 0; l--; /* Remove newline at the end. */ 33 | assert(l%2 == 0); /* Specification of input says so. */ 34 | 35 | /* For each elf of a group of three (elf_id = 0, 1, 2), scan 36 | * the backpack content. What we do here is to use each item 37 | * of the array as a bitmap. So we set bit 0 for elf_id 0, and 38 | * so forth. */ 39 | for (size_t j = 0; j < l; j++) { 40 | int p; /* the current char priority. */ 41 | if (buf[j] >= 'a' && buf[j] <= 'z') 42 | p = buf[j]-'a'+1; 43 | else 44 | p = buf[j]-'A'+27; 45 | 46 | seen[p] |= 1 << elf_id; 47 | 48 | /* All the three bits set? Common item found. Note how 49 | * we can stop ASAP without ending the scan and without 50 | * using a new loop to scan again. Also the loop is guaranteed 51 | * to found the common item when we are at the third elf 52 | * of the group. */ 53 | if (seen[p] == 7) { 54 | total_priority += p; 55 | memset(seen,0,sizeof(seen)); /* Reset state. */ 56 | break; 57 | } 58 | } 59 | } 60 | fclose(fp); 61 | printf("%ld\n", total_priority); 62 | return 0; 63 | } 64 | -------------------------------------------------------------------------------- /day-4/2.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #define min(a,b) ((a)<(b) ? (a):(b)) 7 | #define max(a,b) ((a)>(b) ? (a):(b)) 8 | 9 | /* Define the range data type. */ 10 | typedef struct { 11 | int start; 12 | int end; 13 | } range; 14 | 15 | range rangeNew(int s, int e) { 16 | range r = {s,e}; 17 | return r; 18 | } 19 | 20 | int rangeLen(range r) { 21 | return r.end-r.start; 22 | } 23 | 24 | range rangeOverlap(range a, range b) { 25 | return rangeNew(max(a.start,b.start),min(a.end,b.end)); 26 | } 27 | 28 | /* We expect the range to be in the form -. 29 | * Return 0 on parse error, otherwise 1 is returned. */ 30 | int parseRange(const char *s, range *r) { 31 | char buf[64]; 32 | size_t len = strlen(s); 33 | if (len < 2 || len+1 > sizeof(buf)) return 0; 34 | memcpy(buf,s,len+1); 35 | if (buf[len-1] == '\n') buf[len-1] = 0; /* newline -> nulterm. */ 36 | 37 | /* Split the two parts. */ 38 | char *p = strchr(buf,'-'); 39 | if (!p) return 0; 40 | *p = 0; 41 | p++; /* Seek the second number. */ 42 | r->start = atoi(buf); /* Assume input is sane here. */ 43 | r->end = atoi(p); /* Assume input is sane here. */ 44 | return 1; 45 | } 46 | 47 | int main(void) { 48 | char buf[64]; 49 | 50 | FILE *fp = fopen("input.txt","r"); 51 | if (fp == NULL) { 52 | perror("Opening input file"); 53 | exit(1); 54 | } 55 | 56 | long overlaps = 0; 57 | while(fgets(buf,sizeof(buf),fp) != NULL) { 58 | char *p = strchr(buf,','); 59 | if (!p) continue; 60 | *p = 0; 61 | p++; /* Seek second range. */ 62 | 63 | range a,b; 64 | parseRange(buf,&a); 65 | parseRange(p,&b); 66 | range overlap = rangeOverlap(a,b); 67 | /* Why >= 0 instead of > 0? Because the ranges in the puzzle 68 | * are discrete, so 2-4, 4-6 are consireding overlapping while 69 | * if you imagine them in the numbers line, they have a point in 70 | * common but no overlap. To account for it, we just need to 71 | * consider "touching" ranges as overlapping. */ 72 | if (rangeLen(overlap) >= 0) overlaps++; 73 | } 74 | fclose(fp); 75 | printf("%ld\n", overlaps); 76 | return 0; 77 | } 78 | -------------------------------------------------------------------------------- /day-6/1_2.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define PREFIX_LEN 4 /* Use 14 for part 2. */ 4 | 5 | /* Usage: cat input.txt | ./part1_2 */ 6 | int main(void) { 7 | /* Here we want to detect a prefix of len PREFIX_LEN where each 8 | * symbol is different. If at every position we check for the 9 | * condition, the work we do is proportional to O(N*M), where N 10 | * is the total number of characters in the sequence and M the 11 | * length of the prefix we are searching. That is not great if M 12 | * is big. We want to solve the puzzle in O(N): 13 | * 14 | * First we need a table where we remember how many times we 15 | * saw each symbol in the last M symbols processed. */ 16 | 17 | int ftable[256] = {0}; /* Frequency table. */ 18 | int dupcount = 0; /* Track how many symbols in the table have a frequency 19 | greater than 1, in a given moment. */ 20 | 21 | /* We also need to remember at which position on the stream we are, 22 | * since we need to report the first time we saw M different symbols. */ 23 | long index = 0; 24 | 25 | /* This approach gives us another key advantage: we can process the 26 | * stream one symbol each time. However we need to remember the latest 27 | * M characters even with this algorithm: there is to update the table 28 | * removing the symbols that are now out of the window. */ 29 | int c; /* Current symbol. */ 30 | char mem[PREFIX_LEN]; 31 | while((c = getc(stdin)) != EOF) { 32 | int f = ++ftable[c]; 33 | 34 | /* Update the table of duplicated chars after seeing this 35 | * character. */ 36 | if (f == 2) dupcount++; 37 | index++; 38 | 39 | /* Also undo the effect of the first character that went 40 | * out of the window of the prefix len. */ 41 | if (index > PREFIX_LEN) { 42 | int oldidx = index-PREFIX_LEN; 43 | int oldc = mem[oldidx % PREFIX_LEN]; 44 | int f = --ftable[oldc]; 45 | if (f == 1) dupcount--; 46 | } 47 | 48 | mem[index % PREFIX_LEN] = c; /* Populate memory of past symbols. */ 49 | 50 | /* Check if we found a window with zero duplicated symbols. */ 51 | if (index >= PREFIX_LEN && dupcount == 0) break; 52 | } 53 | printf("%ld\n", index); 54 | return 0; 55 | } 56 | -------------------------------------------------------------------------------- /day-2/2.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | /* HIGHLIGHTS 5 | * ========== 6 | * 7 | * 1. The program shows that gameScore() of puzzle 3 was at the right 8 | * level of abstraction. We are able to reuse it. 9 | * 2. Use a functional approach to leave the logic identical but call 10 | * the nested function selectMove() to obtain one of the arguments 11 | * of gameScore(). 12 | * 3. Avoiding of a lookup table by discovering the mathematical rule that 13 | * allows us to immediately select what shape to reply for the desired 14 | * outcome. 15 | */ 16 | 17 | /* Given a game with me using shape 'me' and the opponent using 18 | * shape 'opp' (both 'A','B' or 'C') return the total score. */ 19 | int gameScore(int me, int opp) { 20 | /* Normalize shapes to 0-2: 21 | * 0 = Rock, 1 = Paper, 2 = Scissor. */ 22 | int m = me-'A'; 23 | int o = opp-'A'; 24 | 25 | /* Each entry scoremap[m][o] represents the outcome of the game in 26 | * form of a lookup table. */ 27 | int scoremap[3][3] = { 28 | {1+3, 1+0, 1+6}, 29 | {2+6, 2+3, 2+0}, 30 | {3+0, 3+6, 3+3} 31 | }; 32 | 33 | return scoremap[m][o]; 34 | } 35 | 36 | /* Given an outcome (X = lose, Y = draw, Z = win) and the opponent 37 | * move, select the move to do in order to reach the desired outcome. */ 38 | int selectMove(int opp, int outcome) { 39 | int out = outcome-'X'; /* 0 = Lose, 1 = Draw, 2 = Win. */ 40 | opp -= 'A'; /* 0 = Rock, 1 = Paper, 2 = Scissor. */ 41 | 42 | /* If you think at the sequence [Rock, Paper, Scissor], if you want 43 | * to lose against one of those, you have to pick the shape that 44 | * is two places foward (for exaple for Rock is Scissor), if you 45 | * want to draw the shape after three positions, that is the same 46 | * shape your opponent is using, and finally you to win you want 47 | * to chose the next one (that is the same as the shape after four 48 | * positions, since we rotate). 49 | * 50 | * Now given that the outcome is 0, 1, 2, we can summarize the above 51 | * into the following: */ 52 | return 'A'+((opp+2+out)%3); 53 | } 54 | 55 | int main(void) { 56 | char buf[64]; 57 | 58 | FILE *fp = fopen("input.txt","r"); 59 | if (fp == NULL) { 60 | perror("Opening input file"); 61 | exit(1); 62 | } 63 | 64 | long score = 0; 65 | while(fgets(buf,sizeof(buf),fp) != NULL) { 66 | int opp = buf[0]; /* Opponent move. */ 67 | int outcome = buf[2]; /* How the game should end. */ 68 | score += gameScore(selectMove(opp,outcome),opp); 69 | } 70 | fclose(fp); 71 | printf("%ld\n", score); 72 | return 0; 73 | } 74 | -------------------------------------------------------------------------------- /day-16/input.txt: -------------------------------------------------------------------------------- 1 | Valve RU has flow rate=0; tunnels lead to valves YH, ID 2 | Valve QK has flow rate=24; tunnels lead to valves PQ, PP 3 | Valve RP has flow rate=11; tunnels lead to valves RM, BA, RI, EM 4 | Valve BX has flow rate=0; tunnels lead to valves ZX, VK 5 | Valve JL has flow rate=0; tunnels lead to valves ID, LC 6 | Valve DC has flow rate=25; tunnel leads to valve ST 7 | Valve HX has flow rate=0; tunnels lead to valves DH, FE 8 | Valve KJ has flow rate=0; tunnels lead to valves ZK, XN 9 | Valve EM has flow rate=0; tunnels lead to valves AW, RP 10 | Valve XN has flow rate=7; tunnels lead to valves LH, KJ, KU, AO 11 | Valve DH has flow rate=9; tunnels lead to valves SY, CC, QL, LH, HX 12 | Valve LH has flow rate=0; tunnels lead to valves XN, DH 13 | Valve PP has flow rate=0; tunnels lead to valves QK, TA 14 | Valve AO has flow rate=0; tunnels lead to valves AA, XN 15 | Valve SY has flow rate=0; tunnels lead to valves DH, AA 16 | Valve MZ has flow rate=0; tunnels lead to valves JT, PF 17 | Valve AA has flow rate=0; tunnels lead to valves JN, UN, WG, SY, AO 18 | Valve RM has flow rate=0; tunnels lead to valves XL, RP 19 | Valve BA has flow rate=0; tunnels lead to valves RP, YP 20 | Valve AD has flow rate=12; tunnels lead to valves LK, ZX, AW 21 | Valve ZN has flow rate=0; tunnels lead to valves EQ, HL 22 | Valve EX has flow rate=18; tunnel leads to valve RB 23 | Valve CR has flow rate=0; tunnels lead to valves TA, ST 24 | Valve WG has flow rate=0; tunnels lead to valves AA, TA 25 | Valve UN has flow rate=0; tunnels lead to valves WK, AA 26 | Valve VE has flow rate=0; tunnels lead to valves JA, KW 27 | Valve JA has flow rate=19; tunnels lead to valves PQ, VE 28 | Valve AW has flow rate=0; tunnels lead to valves AD, EM 29 | Valve XL has flow rate=0; tunnels lead to valves RM, PF 30 | Valve OD has flow rate=0; tunnels lead to valves VK, RI 31 | Valve FE has flow rate=0; tunnels lead to valves JT, HX 32 | Valve PQ has flow rate=0; tunnels lead to valves JA, QK 33 | Valve RB has flow rate=0; tunnels lead to valves CC, EX 34 | Valve JT has flow rate=3; tunnels lead to valves RF, MZ, ZK, FE, DD 35 | Valve YP has flow rate=0; tunnels lead to valves ID, BA 36 | Valve ID has flow rate=14; tunnels lead to valves JL, RU, YP 37 | Valve YH has flow rate=0; tunnels lead to valves RU, VK 38 | Valve TA has flow rate=21; tunnels lead to valves WG, KU, PP, RF, CR 39 | Valve LK has flow rate=0; tunnels lead to valves PF, AD 40 | Valve DD has flow rate=0; tunnels lead to valves JN, JT 41 | Valve HL has flow rate=0; tunnels lead to valves ZN, DW 42 | Valve VK has flow rate=22; tunnels lead to valves OD, KW, BX, YH 43 | Valve RF has flow rate=0; tunnels lead to valves JT, TA 44 | Valve CC has flow rate=0; tunnels lead to valves RB, DH 45 | Valve KW has flow rate=0; tunnels lead to valves VE, VK 46 | Valve PF has flow rate=10; tunnels lead to valves WK, MZ, QL, XL, LK 47 | Valve ZX has flow rate=0; tunnels lead to valves AD, BX 48 | Valve JN has flow rate=0; tunnels lead to valves DD, AA 49 | Valve ST has flow rate=0; tunnels lead to valves CR, DC 50 | Valve WK has flow rate=0; tunnels lead to valves PF, UN 51 | Valve DW has flow rate=13; tunnels lead to valves LC, HL 52 | Valve ZK has flow rate=0; tunnels lead to valves KJ, JT 53 | Valve QL has flow rate=0; tunnels lead to valves DH, PF 54 | Valve RI has flow rate=0; tunnels lead to valves OD, RP 55 | Valve EQ has flow rate=23; tunnel leads to valve ZN 56 | Valve LC has flow rate=0; tunnels lead to valves JL, DW 57 | Valve KU has flow rate=0; tunnels lead to valves XN, TA 58 | -------------------------------------------------------------------------------- /day-6/input.txt: -------------------------------------------------------------------------------- 1 | mzrzqrzqrrmcmgmrggvjvcczbczccdwdcwcpwwclwwbttdntnsnllpggqhgqgzqggvjjjfqfhhbbvzvmzvvfccnznwntnptpgpcplpwwvgvzvvcgvvbcvcqqhnqqbsbdsbbbgtgvtgvtgvvrfvvjbjcbcchnhrhvvrmmwzwzmwmggjwwwwzrrmbmbmbrrdjrjfrrrmrffzgghtggwddtllhchdhsshjjwfwsfssnbbnjncczsczzvpvssljsjgsjgjcgjggspsfsfhfppsqqzlzjllblsldsldlndnhnffflwfwmwssvzzvqzzblzbbmrrfnrrqnnhfnnhphbhrrlvrlvrvcrrltrtmrrcscchdhqhfffrddzsszwwrbrfftddbwwtdtnndrrghgcgfgrglllcdcsswvwsvszsddjwdwwcvwvmvhhlqlddbhbrrnddpqpttrtctmcmjjtvjjfvvlcldltdtdqdllnrncrnrznzfnfsfnndqqbhhlnhhhsmhhfghgppflllrhhvdddvrvnrnpplwplldttswsbwwtbbvwbwnnhcczmczmczclcttwcchllmsmbbrvbbsjsswbwwbtwtgtrgtrgrnggqwgwmwrmrqmmghhtbbrppjmpppjtjtffvqvbbwsspzsstlstltrrtmtrmrzmmgqqgmmpzmpzpmmgnnrjjgrjjhgjjsccjllwzzsddznnrsrttdllcnntvnttqjjqljqqwlqlmmfdfttzzvgvtvjjwvwsvvhbhrbhbwbzbppbplphpjpzppljjnttnvnggqbqffqgqrrjwjcjllcblbqqglqgqjqrrffjqqqcvqccgrgqgrqrnqqhphccvwwsgspprmprrwdrwrdwdrwrwswbsbcctscttwvvvstvthtrhhddtppgwwqpwwzpzgzszgzvggzqqmbqqrqsrqrmmjjfggztzdzvvqdqzddrrnmmtccsstdsdrrmrnnzzpggbmbqbcbzczppbjbssfzfcfvcvlclgcglcgllvclcwwwpmwwjrrgtrtfrrnznssvvrjvrjrgjrrcsrrstrsrhrpplfljjwrwbbffdpfpzffrhhjrjdrrgpggbhhschcdcdcqcnncjcvjcvjvbvcbvbssnhhsddclcrcrjrdrtdtqdqrddddlcdcttzzlslblbqqcmmdgmmsnmnmccqmmljjncnhnchcdchddwsdssdrsscfcnffcqfqtfqqjcjrrvbrvvhsvvlqlwwsccjbbgpgzgcgbgzgccpvcpvpddqrrqfqtqrqqcjjwvwttrwwblwlrwllnsshdhqdhqqjllzlflvlgllhnllstsbbdqqpnpwpmwwzhzvzcclcvcfvcvssdcdvdpphcphcppffndfnfmfbfwwgzwwwvhwwmcwwwtmtgtvggvbggzzthzzlbzbzmmhlllvgllmfmpmbbldbdnnzzjcctvvsdvssrpsslglqggcchvcvllzhhbcczjjgllvqlvlflglwwscctfcbmdjhgwtfhjrgvvvrmdcpsrtsnvhwnnznnnmrhcnlnmjvdbqztspwbdwlttdtwlwdvqjpgqdzbnssglqczqwvfgdlbdmsbbmggjdhddzvzlqhrggvvccmcmtqdmmpqvvstmqgvntdsmjbzbwstdrmjjmzfgmczjrftwrwnfbdmlddvzdfwwztldqfvdswfdwrfcgptmmjnzngwnflzlvtwpdsvllfwqjnjjjbfcwmgrvlhdvpgprnjthlqlbtlhflzwqjwtqtdzcvqbgtjlnmwchpjrgfndrnzwctjwvwsvflmgnqmplhhwljqcshqqldcnfrdbdcbslrtbnqrvhhjrddmjbtmcjzlqcdcqbfftsmpdpnfrjjwmdpmrvjjmppbnmcbvnzbphjcjlldnpdcwsqfgpmbszvjbpzngvncbfncpmghfrsssrnbbmhnjjvgmjzwtwlpszphgwvtjzdsmvvhnrplmnrllvqvphtbbrnlwmffdmmbhvzfcnbnlbspfwbcbjwgpnbsfpfbdqbnpfcqpngfqwlwcgrzlvfqgfsbppgmfzgjdntdvzvzclbrfwpqmvgmtmppsjzjhqbgjnntdnwvwljndqbtfgrjcfnlpsgsmbdljdzqfclgwhdgndzwbcthmrgzcjbhrrltlsznbsvswtsjbhwqzwchwzbtqmnrqfrzspwrqwwqwvczmntwggltjmvwdftplrgtrltmpvvgslvhctnwwcgtblmqtnsmqdgcbvzlcbrrsstzgzrgzgtmqtvsnzqqwlfgrjbdsvpdjpgmmczddbptwvpthvdjvrpqsbbgctrpqsdnczzbttdrbflrllrnvjswslnghdqfqlnbcctwbnpvspfmrcnprpjzgwsdwlszzpdcgvzjsjtdgjnpwgtqmvsmsvzddcmfwtqjghrrrmvcjbccgrngcvvfvrrmmqmzsvhdqsfqpqnnhhpffrtblnzhwqmsgvvzvgpbczsznzlnvsgjjzqbpjmvpjzqqpzpvplwsvgtwvrhlvggrpvztvchbcwflwhwmvdslvhsgpcqhdhcpvclgmzdngsmbplzrqgwflltzgsglflhqhpnnfszvtgprqhnjlrvwfsjfpcjzbznsprtldvwjlnhqsdlfnwtlpzldfpnjpnnqfgqqrjrnszznlrjgwwlnbbznzcshtfqcprphgsldtgzzgqjvmjrtfhmgptrnqzmtfclqwgprvjptntgwhbqwhdjcfjtrmdwbslhqwgtcqwhjhhmltrlsqbvzqsjqsczvsqlsjdgmnjnpvmmwbsfnfnshmlrdgslbfrnhmdgcjgsqgwlbmlhhnfmcfnswmwgrzmpdmtrcmwgjlgrhzchmhmbjgjrfgdvplvngjnfdrscwqtnsspdszznnnjrdmvwbvnzmmddbcvsphfqsbcmfmfgrcdfjptzqfsjsmjtbswtqzvtfpwbvqsgjzftfssdmcngtgbfmrrsjtllnpsztvgbpgpcrmqsgvcjrpprhqzjwlcdjpvgrqtjcglwnvzvqtncmndzbgpgfbprpqqjfbnzhfzlfrgnfnbpjfrbtjgrgvmczthqsbfplnzvhqjmrrssnzjdhfvlngwptzzdshzhzfpzhmrcjmdvlnlqtsnlbhqgplsltgznshthcwnpzpcgjjwhjstfcdtmmnvbgqzrjpsqwlmlbjnqtrfmbrdsbdlrrwqqvzdnmzhzvrhdftzldzjrtfgzlrwczbzzzqtthdcjtqpcfdwpqlzqmrnsnhwbzhjnqjzgfdcdcrqsjfhpjcdtwnvwzzbwfgdzcmmfvdvdpjsltcrbfqczvvbjscptjsvzndgwhzfjcqljndrcqzhssnqtmjmwjrsqdpqnhwsntqnmrwhvsnvrvpvwbndpmgsnchtnzpjgshcvjgwlwdhqbqhvcwqmwllhcgvbslqvwgswvnsqvvcphbglrvlsczcscznlwzrvjptmbmrgjlhvbrlghcwjdqjlgrcbrhfmbcwgclqzllqtmshbjnhwpgsgtljbwhgcsznvslmglcnmmgjlsptgdqlbtclfbfvjpmqgwwbcvwtdhgjlpvgggjjvmltdgzjdsvtswgblgfcvdvtwrrfljtqjhdflhbtwmcdqpmdqrtjsvdhzstfnqjrzztnwslvwtvgvzfqlzfrhnthjfpvmwmdgrtzhbtwdfscdpwmwwrhgbmqrdftvjvrgzhbpqtqvvlwbmbvlszzqjwhtvwnsjcdcgdlwlrtvjsdqzngcdtpvsddsbqbhtrrpwqdhvdmnnncgccszqtbcgwbdbwrnwrhpwprslbmhrmwpmqzvssfzvrmwrmrzmhrcwvbdtvdflgmrghqngwsgrnctsnhpnmcmfmrtszttqtvvlhdjgplvgnjrtgnfgmdtvwzmzbtzvmhdvpcjqvgpsmdcfrbmqbrlsnccldrfdldqfnsfzznqtvsgwbljgrvbdmggdmhvvdzjfllzwzpddcnvrfggsddqmczfnnfvrwsmvfctctjqdrhvlntflccqgzg 2 | -------------------------------------------------------------------------------- /day-5/adlist.h: -------------------------------------------------------------------------------- 1 | /* adlist.h - A generic doubly linked list implementation 2 | * 3 | * Copyright (c) 2006-2012, Salvatore Sanfilippo 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions are met: 8 | * 9 | * * Redistributions of source code must retain the above copyright notice, 10 | * this list of conditions and the following disclaimer. 11 | * * Redistributions in binary form must reproduce the above copyright 12 | * notice, this list of conditions and the following disclaimer in the 13 | * documentation and/or other materials provided with the distribution. 14 | * * Neither the name of Redis nor the names of its contributors may be used 15 | * to endorse or promote products derived from this software without 16 | * specific prior written permission. 17 | * 18 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 22 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | * POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | 31 | #ifndef __ADLIST_H__ 32 | #define __ADLIST_H__ 33 | 34 | /* Node, List, and Iterator are the only data structures used currently. */ 35 | 36 | typedef struct listNode { 37 | struct listNode *prev; 38 | struct listNode *next; 39 | void *value; 40 | } listNode; 41 | 42 | typedef struct listIter { 43 | listNode *next; 44 | int direction; 45 | } listIter; 46 | 47 | typedef struct list { 48 | listNode *head; 49 | listNode *tail; 50 | void *(*dup)(void *ptr); 51 | void (*free)(void *ptr); 52 | int (*match)(void *ptr, void *key); 53 | unsigned long len; 54 | } list; 55 | 56 | /* Functions implemented as macros */ 57 | #define listLength(l) ((l)->len) 58 | #define listFirst(l) ((l)->head) 59 | #define listLast(l) ((l)->tail) 60 | #define listPrevNode(n) ((n)->prev) 61 | #define listNextNode(n) ((n)->next) 62 | #define listNodeValue(n) ((n)->value) 63 | 64 | #define listSetDupMethod(l,m) ((l)->dup = (m)) 65 | #define listSetFreeMethod(l,m) ((l)->free = (m)) 66 | #define listSetMatchMethod(l,m) ((l)->match = (m)) 67 | 68 | #define listGetDupMethod(l) ((l)->dup) 69 | #define listGetFreeMethod(l) ((l)->free) 70 | #define listGetMatchMethod(l) ((l)->match) 71 | 72 | /* Prototypes */ 73 | list *listCreate(void); 74 | void listRelease(list *list); 75 | void listEmpty(list *list); 76 | list *listAddNodeHead(list *list, void *value); 77 | list *listAddNodeTail(list *list, void *value); 78 | list *listInsertNode(list *list, listNode *old_node, void *value, int after); 79 | void listDelNode(list *list, listNode *node); 80 | listIter *listGetIterator(list *list, int direction); 81 | listNode *listNext(listIter *iter); 82 | void listReleaseIterator(listIter *iter); 83 | list *listDup(list *orig); 84 | listNode *listSearchKey(list *list, void *key); 85 | listNode *listIndex(list *list, long index); 86 | void listRewind(list *list, listIter *li); 87 | void listRewindTail(list *list, listIter *li); 88 | void listRotateTailToHead(list *list); 89 | void listRotateHeadToTail(list *list); 90 | void listJoin(list *l, list *o); 91 | void listInitNode(listNode *node, void *value); 92 | void listLinkNodeHead(list *list, listNode *node); 93 | void listUnlinkNode(list *list, listNode *node); 94 | 95 | /* Directions for iterators */ 96 | #define AL_START_HEAD 0 97 | #define AL_START_TAIL 1 98 | 99 | #endif /* __ADLIST_H__ */ 100 | -------------------------------------------------------------------------------- /day-5/12.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "adlist.h" 7 | 8 | #define MAXSTACKS 9 9 | 10 | /* Cratemover model (part 1 and part 2 of the puzzle) */ 11 | #define CRATEMOVER9000 0 12 | #define CRATEMOVER9001 1 13 | 14 | /* Show the current stacks content. */ 15 | void printStacks(list **stacks, int count) { 16 | for (int j = 0; j < count; j++) { 17 | printf("%d: ", j+1); 18 | listIter *li = listGetIterator(stacks[j],AL_START_HEAD); 19 | listNode *node; 20 | while ((node = listNext(li)) != NULL) { 21 | printf("[%c]", (char)(unsigned long)(void*)listNodeValue(node)); 22 | } 23 | listReleaseIterator(li); 24 | printf("\n"); 25 | } 26 | } 27 | 28 | /* Given MAXSTACKS stacks and the string describing the move operation 29 | * to do in the form move from to perform the 30 | * operation. From/to are 1-based. */ 31 | void makeMove(list **stacks, char *buf, int model) { 32 | int count, from, to; 33 | size_t len = strlen(buf); 34 | char *p; 35 | 36 | if (len < 4) return; /* Trivial sanity check. */ 37 | if (buf[len-1] == '\n') buf[len-1] = '\0'; 38 | /* Seek "to" */ 39 | p = strchr(buf,'t'); if (!p) return; 40 | p[-1] = 0; /* nullterm "from" */ 41 | to = atoi(p+3); /* Parse "to" */ 42 | /* Seek "from" */ 43 | p = strchr(buf,'f'); if (!p) return; 44 | p[-1] = 0; /* nullterm "move" */ 45 | from = atoi(p+5); /* Parse "from" */ 46 | count = atoi(buf+5); /* Parse "move" */ 47 | 48 | /* Bound checking. */ 49 | if (to < 1 || to > 9 || 50 | from < 1 || from > 9 || 51 | count < 1) return; 52 | 53 | from--, to--; 54 | list *lfrom = stacks[from]; 55 | list *lto = stacks[to]; 56 | list *ltmp = listCreate(); /* Used only for 9001 model. */ 57 | 58 | /* Common code between 9000 and 9001 model. */ 59 | for (int j = 0; j < count; j++) { 60 | listNode *ln = listIndex(lfrom,-1); 61 | if (ln == NULL) { 62 | printf("Not enough items to move. Exiting.\n"); 63 | exit(1); 64 | return; 65 | } 66 | void *value = listNodeValue(ln); 67 | listDelNode(lfrom,ln); 68 | listAddNodeTail(model == CRATEMOVER9000 ? lto : ltmp,value); 69 | } 70 | 71 | /* For cratemover9001, we simuate the behavior putting the items 72 | * in a temp list, and then moving back to the destination. This 73 | * way the order is retained. */ 74 | if (model == CRATEMOVER9001) { 75 | for (int j = 0; j < count; j++) { 76 | listNode *ln = listIndex(ltmp,-1); 77 | void *value = listNodeValue(ln); 78 | listDelNode(ltmp,ln); 79 | listAddNodeTail(lto,value); 80 | } 81 | } 82 | 83 | listRelease(ltmp); 84 | } 85 | 86 | int main(int argc, char **argv) { 87 | char buf[128]; 88 | int model = CRATEMOVER9000; 89 | 90 | /* Parse arguments to understand what model to use. */ 91 | if (argc == 2) { 92 | if (!strcmp(argv[1],"--9000")) { 93 | model = CRATEMOVER9000; 94 | } else if (!strcmp(argv[1],"--9001")) { 95 | model = CRATEMOVER9001; 96 | } else { 97 | printf("Usage: %s [--9000 | --9001]\n", argv[0]); 98 | exit(1); 99 | } 100 | } 101 | 102 | FILE *fp = fopen("input.txt","r"); 103 | if (fp == NULL) { 104 | perror("Opening input file"); 105 | exit(1); 106 | } 107 | 108 | list *stacks[MAXSTACKS]; 109 | for (int j = 0; j < MAXSTACKS; j++) 110 | stacks[j] = listCreate(); 111 | 112 | int loading_stage = 1; /* When 0 we are at moving stage. */ 113 | printf("Loading...\n"); 114 | while(fgets(buf,sizeof(buf),fp) != NULL) { 115 | 116 | /* Switch from loading to moving stage when the line is 117 | * " 1 2 3 ..." */ 118 | if (loading_stage && buf[1] == '1') { 119 | loading_stage = 0; 120 | printf("Switching to moving stage...\n"); 121 | continue; 122 | } 123 | 124 | if (loading_stage) { 125 | for (int j = 0; j < MAXSTACKS; j++) { 126 | int c = buf[1+j*4]; 127 | printf("%c",c); 128 | if (c >= 'A' && c <= 'Z') 129 | listAddNodeHead(stacks[j],(void*)(unsigned long)c); 130 | } 131 | printf("\n"); 132 | } else { 133 | /* Ignore lines not starting with "move" */ 134 | if (buf[0] != 'm') continue; 135 | makeMove(stacks,buf,model); 136 | } 137 | } 138 | printStacks(stacks,MAXSTACKS); 139 | 140 | /* Cleanup. */ 141 | for (int j = 0; j < MAXSTACKS; j++) 142 | listRelease(stacks[j]); 143 | fclose(fp); 144 | return 0; 145 | } 146 | -------------------------------------------------------------------------------- /day-18/prog.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include "aoc.h" 9 | 10 | #define SPACE_SIZE 30 11 | char Space[SPACE_SIZE][SPACE_SIZE][SPACE_SIZE] = {0}; 12 | 13 | /* All the possible direction of adjacent cubes. */ 14 | #define SPACE_DIRS 6 15 | struct { 16 | int x,y,z; 17 | } Dirs[6] = { 18 | /* Imagine to look at a cube in front of you. */ 19 | {1,0,0}, /* Cube on the right. */ 20 | {-1,0,0}, /* Cube on the left. */ 21 | {0,-1,0}, /* Cub on the top. */ 22 | {0,1,0}, /* Cube on the bottom. */ 23 | {0,0,-1}, /* Cube immediately nearest to us. */ 24 | {0,0,1}, /* Cube immediately after this cube. */ 25 | }; 26 | 27 | /* This will mark all the reachabel cubes of air in Space (not trapped 28 | * inside other cubes) with the value '2'. x,y,z is the starting position 29 | * of the flood. */ 30 | void flood(int x, int y, int z) { 31 | /* Non zero? Either already flood or solid. */ 32 | if (Space[x][y][z]) return; 33 | 34 | Space[x][y][z] = 2; 35 | /* Recursively flood all the adjacent cubes. */ 36 | for (int j = 0; j < SPACE_DIRS; j++) { 37 | int cx = x+Dirs[j].x; 38 | int cy = y+Dirs[j].y; 39 | int cz = z+Dirs[j].z; 40 | 41 | /* Skip out of bound coordinates. */ 42 | if (cx < 0 || cy < 0 || cz < 0 || 43 | cx >= SPACE_SIZE || 44 | cy >= SPACE_SIZE || 45 | cz >= SPACE_SIZE) continue; 46 | flood(cx,cy,cz); 47 | } 48 | } 49 | 50 | int main(int argc, char **argv) { 51 | FILE *fp = argc == 2 ? fopen(argv[1],"r") : stdin; 52 | if (!fp) { 53 | perror("fopen"); 54 | exit(1); 55 | } 56 | 57 | /* Input parsing. Boring but needed. */ 58 | char buf[256]; 59 | while(fgets(buf,sizeof(buf),fp) != NULL) { 60 | size_t l = strlen(buf); 61 | if (l <= 1) continue; 62 | if (buf[l-1] == '\n') { 63 | buf[l-1] = 0; 64 | l--; 65 | } 66 | 67 | int x,y,z; 68 | sscanf(buf,"%d,%d,%d",&x,&y,&z); 69 | Space[x][y][z] = 1; 70 | } 71 | if (argc == 2) fclose(fp); 72 | 73 | /* Part 1. */ 74 | 75 | /* Scan the space looking for cubes. */ 76 | int area = 0; 77 | for (int x = 0; x < SPACE_SIZE; x++) { 78 | for (int y = 0; y < SPACE_SIZE; y++) { 79 | for (int z = 0; z < SPACE_SIZE; z++) { 80 | if (Space[x][y][z]) { 81 | /* For each face check the adjacent space. */ 82 | for (int j = 0; j < SPACE_DIRS; j++) { 83 | int cx = x+Dirs[j].x; 84 | int cy = y+Dirs[j].y; 85 | int cz = z+Dirs[j].z; 86 | 87 | if (cx < 0 || cy < 0 || cz < 0 || 88 | cx >= SPACE_SIZE || 89 | cy >= SPACE_SIZE || 90 | cz >= SPACE_SIZE || 91 | Space[cx][cy][cz] == 0) 92 | { 93 | /* The adjacent position is free only if 94 | * it's outside our space coordinates or 95 | * if there is no cube. */ 96 | area++; 97 | } 98 | } 99 | } 100 | } 101 | } 102 | } 103 | printf("Puzzle 1: %d\n", area); 104 | 105 | flood(0,0,0); /* Mark all the reachable cubes of air with '2'. */ 106 | 107 | /* Count the area of all the faces touching unreachable by water. */ 108 | int trapped_area = 0; 109 | for (int x = 0; x < SPACE_SIZE; x++) { 110 | for (int y = 0; y < SPACE_SIZE; y++) { 111 | for (int z = 0; z < SPACE_SIZE; z++) { 112 | if (Space[x][y][z]) { 113 | /* For each face check the adjacent space. */ 114 | for (int j = 0; j < SPACE_DIRS; j++) { 115 | int cx = x+Dirs[j].x; 116 | int cy = y+Dirs[j].y; 117 | int cz = z+Dirs[j].z; 118 | 119 | if (cx < 0 || cy < 0 || cz < 0 || 120 | cx >= SPACE_SIZE || 121 | cy >= SPACE_SIZE || 122 | cz >= SPACE_SIZE) continue; 123 | 124 | if (Space[cx][cy][cz] == 0) { 125 | /* Free space marked by '2' is reachable by 126 | * wanter, Space with value of '1' is solid. */ 127 | trapped_area++; 128 | } 129 | } 130 | } 131 | } 132 | } 133 | } 134 | printf("Puzzle 2: %d\n", area - trapped_area); 135 | } 136 | -------------------------------------------------------------------------------- /day-11/1.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #define MAX_ITEMS 64 7 | typedef struct monkey { 8 | int items[MAX_ITEMS]; /* Items handled by this monkey. */ 9 | int numitems; /* Number of valid items in item[]. */ 10 | int activity; /* Number of inspected items. */ 11 | char expr[64]; /* Expression performed to obtain new worry level. */ 12 | int div; /* Divisibility test. */ 13 | int next[2]; /* Item goes to next[1] if divisibility test is true. 14 | Otherwise to next[0] if false. */ 15 | } monkey; 16 | 17 | /* Move the item with worry level 'item' to the specified monkey. */ 18 | void passItemToMonkey(monkey *m, int item) { 19 | assert(m->numitems+1 < MAX_ITEMS); 20 | m->items[m->numitems++] = item; 21 | } 22 | 23 | /* Evaluate a monkey expression in the form: "old [*+] [old|value]" and 24 | * return the result of the operation. */ 25 | int evalExpression(char *exp, int old) { 26 | assert(strlen(exp) > 4 && !memcmp(exp,"old ",4)); 27 | int mathop = exp[4]; 28 | int val = !strcmp(exp+6,"old") ? old : atoi(exp+6); 29 | switch(mathop) { 30 | case '*': old *= val; break; 31 | case '+': old += val; break; 32 | default: assert(1 != 1); break; 33 | } 34 | return old; 35 | } 36 | 37 | /* Perform a round as for Day 11 puzzle 1 description. */ 38 | void simulateRound(monkey *monkeys, int num) { 39 | for (int j = 0; j < num; j++) { 40 | monkey *m = monkeys+j; /* Current monkey. */ 41 | for (int k = 0; k < m->numitems; k++) { 42 | /* For each item... */ 43 | int old = m->items[k]; 44 | int new = evalExpression(m->expr,old); 45 | new /= 3; 46 | int isdiv = (new % m->div) == 0; 47 | passItemToMonkey(monkeys+m->next[isdiv],new); 48 | m->activity++; 49 | } 50 | m->numitems = 0; 51 | } 52 | } 53 | 54 | /* Show items of each monkey. */ 55 | void printMonkeys(monkey *monkeys, int num) { 56 | for (int j = 0; j < num; j++) { 57 | monkey *m = monkeys+j; /* Current monkey. */ 58 | printf("Monkey %d [inspected: %d]: ", j, m->activity); 59 | for (int k = 0; k < m->numitems; k++) 60 | printf("%d, ", m->items[k]); 61 | printf("\n"); 62 | } 63 | } 64 | 65 | /* qsort() helper. */ 66 | int qsort_cmp_int(const void *a, const void *b) { 67 | int *pa = (int*)a; 68 | int *pb = (int*)b; 69 | return *pb - *pa; 70 | } 71 | 72 | /* Get Puzzle 1 answer. Sort monkeys by activity, take the first two 73 | * activity levels, multiply. */ 74 | int getMonkeyBusiness(monkey *monkeys, int num) { 75 | int *act = malloc(num*sizeof(int)); 76 | assert(act != NULL); 77 | for (int j = 0; j < num; j++) act[j] = monkeys[j].activity; 78 | qsort(act,num,sizeof(int),qsort_cmp_int); 79 | int business = act[0]*act[1]; 80 | free(act); 81 | return business; 82 | } 83 | 84 | #define MAX_MONKEYS 8 85 | int main(void) { 86 | char buf[1024]; 87 | monkey monkeys[MAX_MONKEYS], *m = NULL; /* m points to current monkey. */ 88 | int mid = 0; /* ID of this monkey. */ 89 | while(fgets(buf,sizeof(buf),stdin) != NULL) { 90 | /* Skip empty lines. */ 91 | size_t l = strlen(buf); 92 | if (l <= 9) continue; 93 | 94 | /* Strip newline. */ 95 | if (buf[l-1] == '\n') { 96 | buf[l-1] = 0; 97 | l--; 98 | } 99 | 100 | /* Parse monkeys. */ 101 | if (buf[0] == 'M') { /* Monkey ID ... */ 102 | if (m != NULL) mid++; 103 | assert(mid < MAX_MONKEYS); 104 | m = &monkeys[mid]; 105 | m->numitems = 0; 106 | m->activity = 0; 107 | continue; 108 | } 109 | 110 | assert(m != NULL); 111 | if (buf[2] == 'S') { /* Starting items: ... */ 112 | assert(l > 16); 113 | char *p = strchr(buf+15,' '); 114 | assert(p != NULL); 115 | 116 | while(1) { 117 | char *c = strchr(p,','); 118 | if (c) *c = 0; 119 | passItemToMonkey(m,atoi(p+1)); 120 | if (c == NULL) break; /* End of items. */ 121 | p = c+1; 122 | } 123 | } else if (buf[2] == 'O') { /* Operation: ... */ 124 | assert(l > 20); 125 | strncpy(m->expr,buf+19,sizeof(m->expr)); 126 | } else if (buf[2] == 'T') { /* Test: ... */ 127 | assert (l > 21); 128 | m->div = atoi(buf+21); 129 | } else if (buf[4] == 'I') { /* If true/false ... */ 130 | char *p = strstr(buf,"to monkey"); 131 | assert(p != NULL); 132 | m->next[buf[7] == 'f' ? 0 : 1] = atoi(p+10); 133 | } else { 134 | printf("Can't parse: %s\n", buf); 135 | exit(1); 136 | } 137 | } 138 | 139 | printf("%d monkeys definitions loaded. Simulating...\n", mid+1); 140 | int rounds = 20; 141 | while(rounds--) simulateRound(monkeys,mid+1); 142 | printMonkeys(monkeys,mid+1); 143 | int business = getMonkeyBusiness(monkeys,mid+1); 144 | printf("Puzzle 1 monkeys business level: %d\n", business); 145 | } 146 | -------------------------------------------------------------------------------- /day-15/prog.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | typedef struct sensor { 7 | int x, y; /* Sensor position. */ 8 | int bx, by; /* Detected beacon position. */ 9 | int dist; /* Distance between sensor and detected beacon. */ 10 | } sensor; 11 | 12 | #define SENSORS_MAX 300 13 | 14 | /* Compute the Manhattan distance between two points. */ 15 | int mandistance(int x1, int y1, int x2, int y2) { 16 | return abs(x1-x2)+abs(y1-y2)+1; 17 | } 18 | 19 | /* Return the number of sensors that could potentially detect 20 | * a potential beacon at x,y. */ 21 | int coulddetect(sensor *sensors, int count, int x, int y) { 22 | int could_detect = 0; 23 | for (int j = 0; j < count; j++) { 24 | /* If this position is already the beam this sensor detected, 25 | * we can't count this position. */ 26 | if (sensors[j].bx == x && sensors[j].by == y) { 27 | could_detect = 0; 28 | break; 29 | } 30 | /* Are we in range? */ 31 | int d = mandistance(x,y,sensors[j].x,sensors[j].y); 32 | if (d <= sensors[j].dist) { 33 | could_detect++; 34 | continue; 35 | } 36 | } 37 | return could_detect; 38 | } 39 | 40 | int main(int argc, char **argv) { 41 | FILE *fp = argc == 2 ? fopen(argv[1],"r") : stdin; 42 | if (!fp) { 43 | perror("fopen"); 44 | exit(1); 45 | } 46 | 47 | int sid = 0; /* Sensor ID. */ 48 | sensor *sensors = malloc(sizeof(sensor)*SENSORS_MAX); 49 | if (!sensors) { 50 | perror("OOM"); 51 | exit(1); 52 | } 53 | 54 | char buf[256]; 55 | int minx = INT_MAX, maxx = INT_MIN, miny = INT_MAX, maxy = INT_MIN; 56 | int maxdist = 0; 57 | while(fgets(buf,sizeof(buf),fp) != NULL && sid < SENSORS_MAX) { 58 | size_t l = strlen(buf); 59 | if (l <= 1) continue; 60 | if (buf[l-1] == '\n') { 61 | buf[l-1] = 0; 62 | l--; 63 | } 64 | 65 | sensor *s = sensors+sid; 66 | sid++; 67 | 68 | sscanf(buf, 69 | "Sensor at x=%d, y=%d: closest beacon is at x=%d, y=%d", 70 | &s->x, &s->y, &s->bx, &s->by); 71 | s->dist = mandistance(s->x,s->y,s->bx,s->by); 72 | if (maxdist < s->dist) maxdist = s->dist; 73 | printf("Sensor at %d,%d distance %d\n", s->x, s->y, s->dist); 74 | 75 | /* Brutal if wall to store the min/max coordinates we 76 | * have seen. We want to have the boundaries of our world 77 | * in order to check only for positions that can be 78 | * within our ranges. */ 79 | if (s->x < minx) minx = s->x; 80 | if (s->x > maxx) maxx = s->x; 81 | if (s->y < miny) miny = s->y; 82 | if (s->y > maxy) maxy = s->y; 83 | if (s->bx < minx) minx = s->bx; 84 | if (s->bx > maxx) maxx = s->bx; 85 | if (s->by < miny) miny = s->by; 86 | if (s->by > maxy) maxy = s->by; 87 | } 88 | if (argc == 2) fclose(fp); 89 | printf("%d sensors read from file\n", sid); 90 | printf("World encosing box %d,%d - %d,%d\n", minx,miny,maxx,maxy); 91 | 92 | /* Puzzle 1. */ 93 | int y = 2000000; /* Use y = 10 for example small input. */ 94 | int cantbe = 0; /* Places where the missing beacon can't be. */ 95 | for (int x = minx-maxdist; x <= maxx+maxdist; x++) { 96 | /* For each x,y check if at least one beacon could detect 97 | * this point. */ 98 | int could_detect = coulddetect(sensors,sid,x,y); 99 | cantbe += could_detect != 0; 100 | } 101 | printf("%d\n", cantbe); 102 | 103 | /* Puzzle 2 want us to determine in which position the beacon could 104 | * be in the range 0 - 4000000. No way to do this by brute force... 105 | * however to be a single position among this space, and since we CAN'T 106 | * detect it, it must be near the edges of one of our sensors limits. 107 | * So we check near the limits of our sensors to find such a point. 108 | * 109 | * To navigate around the edges of a sensor is not hard. Consider this 110 | * sensor at sx,sy with detection range=3. If we start at any of the 111 | * corner points, we just have, for 3 times to do sx++, sy++ (or -- 112 | * depending on the direction), and we can navigate all the positions. 113 | * 114 | * # 115 | * ### 116 | * ##S## 117 | * ### 118 | * # 119 | */ 120 | for (int j = 0; j < sid; j++) { 121 | int x = sensors[j].x; 122 | int y = sensors[j].y; 123 | int dist = sensors[j].dist; 124 | 125 | /* Start at right edge. */ 126 | x += dist; 127 | struct { 128 | int dx, dy; 129 | } dir[4] = { 130 | {-1,-1}, 131 | {-1,1}, 132 | {1,1}, 133 | {1,-1} 134 | }; 135 | 136 | for (int k = 0; k < 4; k++) { 137 | for (int steps = 0; steps < dist; steps++) { 138 | if (coulddetect(sensors,sid,x,y) == 0 && 139 | x >= 0 && x <= 4000000 && 140 | y >= 0 && y <= 4000000) 141 | { 142 | printf("Puzzle 2: %d,%d\n", x,y); 143 | printf("Freq: %lld\n", (long long)4000000*x+y); 144 | return 0; 145 | } 146 | if (steps != dist-1) { 147 | x += dir[k].dx; 148 | y += dir[k].dy; 149 | } 150 | } 151 | } 152 | } 153 | return 0; 154 | } 155 | -------------------------------------------------------------------------------- /day-11/2.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | /* WARNING: for part 2, even after the LCM trick the computation 7 | * overflowed the 'int' type, so I brutally searched & replaced "int" 8 | * with "long" in this program, compared to 1.c. So types will be wild... */ 9 | 10 | #define MAX_ITEMS 64 11 | typedef struct monkey { 12 | long items[MAX_ITEMS]; /* Items handled by this monkey. */ 13 | long numitems; /* Number of valid items in item[]. */ 14 | long activity; /* Number of inspected items. */ 15 | char expr[64]; /* Expression performed to obtain new worry level. */ 16 | long div; /* Divisibility test. */ 17 | long next[2]; /* Item goes to next[1] if divisibility test is true. 18 | Otherwise to next[0] if false. */ 19 | } monkey; 20 | 21 | /* Move the item with worry level 'item' to the specified monkey. */ 22 | void passItemToMonkey(monkey *m, long item) { 23 | assert(m->numitems+1 < MAX_ITEMS); 24 | m->items[m->numitems++] = item; 25 | } 26 | 27 | /* Evaluate a monkey expression in the form: "old [*+] [old|value]" and 28 | * return the result of the operation. */ 29 | long evalExpression(char *exp, long old) { 30 | assert(strlen(exp) > 4 && !memcmp(exp,"old ",4)); 31 | long mathop = exp[4]; 32 | long val = !strcmp(exp+6,"old") ? old : atoi(exp+6); 33 | switch(mathop) { 34 | case '*': old *= val; break; 35 | case '+': old += val; break; 36 | default: assert(1 != 1); break; 37 | } 38 | return old; 39 | } 40 | 41 | /* Perform a round as for Day 11 puzzle 1 description. */ 42 | void simulateRound(monkey *monkeys, long num) { 43 | for (long j = 0; j < num; j++) { 44 | monkey *m = monkeys+j; /* Current monkey. */ 45 | for (long k = 0; k < m->numitems; k++) { 46 | /* For each item... */ 47 | long old = m->items[k]; 48 | long new = evalExpression(m->expr,old); 49 | /* In order to avoid overflows, we can use the trick 50 | * of performing the operation modulo LCM, but since all the 51 | * divisors are prime here, this is equivalent to just multiplying 52 | * all the divisors together. 53 | * 54 | * Note that even so it overflows a 32 bit integer, so we 55 | * need to resort to long. */ 56 | long modulo = 1; 57 | for (long i = 0; i < num; i++) modulo *= monkeys[i].div; 58 | new = new % modulo; 59 | long isdiv = (new % m->div) == 0; 60 | passItemToMonkey(monkeys+m->next[isdiv],new); 61 | m->activity++; 62 | } 63 | m->numitems = 0; 64 | } 65 | } 66 | 67 | /* Show items of each monkey. */ 68 | void printMonkeys(monkey *monkeys, long num) { 69 | for (long j = 0; j < num; j++) { 70 | monkey *m = monkeys+j; /* Current monkey. */ 71 | printf("Monkey %ld [inspected: %ld]: ", j, m->activity); 72 | for (long k = 0; k < m->numitems; k++) 73 | printf("%ld, ", m->items[k]); 74 | printf("\n"); 75 | } 76 | } 77 | 78 | /* qsort() helper. */ 79 | int qsort_cmp_int(const void *a, const void *b) { 80 | long *pa = (long*)a; 81 | long *pb = (long*)b; 82 | return (int)(*pb - *pa); 83 | } 84 | 85 | /* Get Puzzle 1 answer. Sort monkeys by activity, take the first two 86 | * activity levels, multiply. */ 87 | long getMonkeyBusiness(monkey *monkeys, long num) { 88 | long *act = malloc(num*sizeof(int)); 89 | assert(act != NULL); 90 | for (long j = 0; j < num; j++) act[j] = monkeys[j].activity; 91 | qsort(act,num,sizeof(long),qsort_cmp_int); 92 | long business = act[0]*act[1]; 93 | free(act); 94 | return business; 95 | } 96 | 97 | #define MAX_MONKEYS 8 98 | int main(void) { 99 | char buf[1024]; 100 | monkey monkeys[MAX_MONKEYS], *m = NULL; /* m points to current monkey. */ 101 | long mid = 0; /* ID of this monkey. */ 102 | while(fgets(buf,sizeof(buf),stdin) != NULL) { 103 | /* Skip empty lines. */ 104 | size_t l = strlen(buf); 105 | if (l <= 9) continue; 106 | 107 | /* Strip newline. */ 108 | if (buf[l-1] == '\n') { 109 | buf[l-1] = 0; 110 | l--; 111 | } 112 | 113 | /* Parse monkeys. */ 114 | if (buf[0] == 'M') { /* Monkey ID ... */ 115 | if (m != NULL) mid++; 116 | assert(mid < MAX_MONKEYS); 117 | m = &monkeys[mid]; 118 | m->numitems = 0; 119 | m->activity = 0; 120 | continue; 121 | } 122 | 123 | assert(m != NULL); 124 | if (buf[2] == 'S') { /* Starting items: ... */ 125 | assert(l > 16); 126 | char *p = strchr(buf+15,' '); 127 | assert(p != NULL); 128 | 129 | while(1) { 130 | char *c = strchr(p,','); 131 | if (c) *c = 0; 132 | passItemToMonkey(m,atoi(p+1)); 133 | if (c == NULL) break; /* End of items. */ 134 | p = c+1; 135 | } 136 | } else if (buf[2] == 'O') { /* Operation: ... */ 137 | assert(l > 20); 138 | strncpy(m->expr,buf+19,sizeof(m->expr)); 139 | } else if (buf[2] == 'T') { /* Test: ... */ 140 | assert (l > 21); 141 | m->div = atoi(buf+21); 142 | } else if (buf[4] == 'I') { /* If true/false ... */ 143 | char *p = strstr(buf,"to monkey"); 144 | assert(p != NULL); 145 | m->next[buf[7] == 'f' ? 0 : 1] = atoi(p+10); 146 | } else { 147 | printf("Can't parse: %s\n", buf); 148 | exit(1); 149 | } 150 | } 151 | 152 | printf("%ld monkeys definitions loaded. Simulating...\n", mid+1); 153 | long rounds = 10000; 154 | while(rounds--) simulateRound(monkeys,mid+1); 155 | printMonkeys(monkeys,mid+1); 156 | long business = getMonkeyBusiness(monkeys,mid+1); 157 | printf("Puzzle 2 monkeys business level: %ld\n", business); 158 | } 159 | -------------------------------------------------------------------------------- /day-7/1_2.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #define ELFDIR_NAME_MAX 64 6 | #define ELFDIR_SUB_MAX 16 7 | 8 | /* This describes every directory in our filesystem. */ 9 | typedef struct elfdir { 10 | char name[ELFDIR_NAME_MAX]; 11 | size_t size; /* Size excluding subdirs. */ 12 | size_t totalsize; /* Size including subdirs. */ 13 | int subdirs; /* Number of sub directories. */ 14 | struct elfdir *sub[ELFDIR_SUB_MAX]; /* Subdirectories pointers. */ 15 | struct elfdir *parent; /* Containing directory. NULL for / */ 16 | } elfdir; 17 | 18 | /* Allocate and initialize a new directory node. */ 19 | elfdir *makeElfdir(elfdir *parent, const char *name) { 20 | elfdir *ed = malloc(sizeof(*ed)); 21 | if (ed == NULL) return NULL; 22 | strncpy(ed->name,name,ELFDIR_NAME_MAX); 23 | ed->size = 0; 24 | ed->totalsize = 0; 25 | ed->subdirs = 0; 26 | ed->parent = parent; 27 | return ed; 28 | } 29 | 30 | /* Scan the console output at 'filename' to reconstruct the directory 31 | * tree. Return the parent directory. We assume that the file starts 32 | * with "cd /". Return the top-most level directory found. */ 33 | elfdir *readTree(const char *filename) { 34 | elfdir *root = NULL; /* Top most dir. */ 35 | elfdir *cd = NULL; /* Current dir. */ 36 | 37 | FILE *fp = fopen(filename,"r"); 38 | if (fp == NULL) { 39 | perror("Opening input file"); 40 | exit(1); 41 | } 42 | 43 | char buf[128]; 44 | while(fgets(buf,sizeof(buf),fp) != NULL) { 45 | size_t len = strlen(buf); 46 | if (len && buf[len-1] == '\n') buf[len-1] = 0; 47 | 48 | if (buf[0] == '$') { 49 | char *p = strchr(buf+2,' '); 50 | if (p == NULL) continue; 51 | *p = 0; 52 | char *cmd = buf+2; 53 | char *arg = p+1; 54 | 55 | if (!strcmp(cmd,"ls")) continue; /* Just scan the files. */ 56 | if (!strcmp(cmd,"cd")) { 57 | if (!strcmp(arg,"..")) { 58 | /* Go upper. */ 59 | if (!cd) continue; /* We don't know where we are... */ 60 | if (cd->parent == NULL) { 61 | /* Wait... we didn't knew there was a directory 62 | * at higher level. Does not happen in input, anyway. */ 63 | cd->parent = makeElfdir(NULL,"?"); 64 | root = cd->parent; 65 | } 66 | /* Again: does not happen in the input, but if we 67 | * believe this is the root dir, and we see "..", we 68 | * need to update our view of the tree. */ 69 | if (cd == root) root = cd->parent; 70 | 71 | cd->parent->totalsize += cd->totalsize; 72 | cd = cd->parent; /* Update the current dir. */ 73 | } else { 74 | /* Entering a subdir. Assume we enter the subdir 75 | * only once in the input. */ 76 | elfdir *newdir = makeElfdir(cd,arg); 77 | if (!root) root = newdir; 78 | /* Add this subdirectory to the current one. */ 79 | if (cd) cd->sub[cd->subdirs++] = newdir; 80 | cd = newdir; 81 | } 82 | } 83 | } else { 84 | char *p = strchr(buf,' '); 85 | if (p == NULL) continue; 86 | *p = 0; 87 | char *attr = buf; /* Attribute part. */ 88 | // char *name = p+1; /* Filename -- never used */ 89 | if (!strcmp(attr,"dir")) continue; /* zero size. */ 90 | 91 | /* If the input starts with $ ls and we don't know what 92 | * the current dir is, we don't handle that to avoid adding 93 | * too much complexity. Just discard such files. Does not 94 | * happen in the actual input. */ 95 | if (!cd) continue; 96 | size_t filesize = atoi(attr); 97 | cd->size += filesize; 98 | cd->totalsize += filesize; 99 | } 100 | } 101 | 102 | /* The current directory after seeing all the commands will be 103 | * some random one. We need to navigate up to the root to fix 104 | * the total size computation. */ 105 | while(cd != root) { 106 | cd->parent->totalsize += cd->totalsize; 107 | cd = cd->parent; 108 | } 109 | fclose(fp); 110 | return root; 111 | } 112 | 113 | /* Pretty print a given directory. */ 114 | void printDir(elfdir *ed, int level) { 115 | for (int k = 0; k < level*2; k++) printf(" "); 116 | printf("- %s (size %zu | total %zu)\n", ed->name, ed->size, ed->totalsize); 117 | } 118 | 119 | /* Pretty print the directory tree. */ 120 | void printTree(elfdir *root, int level) { 121 | if (level == 0) printDir(root,level); 122 | for (int j = 0; j < root->subdirs; j++) { 123 | printDir(root->sub[j], level+1); 124 | printTree(root->sub[j], level+1); 125 | } 126 | } 127 | 128 | /* Sum of total size of every dir <= 'upto' bytes. */ 129 | void findTotalUpTo(elfdir *root, size_t upto, size_t *sum) { 130 | for (int j = 0; j < root->subdirs; j++) { 131 | size_t size = root->sub[j]->totalsize; 132 | if (size <= upto) *sum += size; 133 | findTotalUpTo(root->sub[j], upto, sum); 134 | } 135 | } 136 | 137 | /* Find the size of the smallest directory that is at least 'minsize' 138 | * in size. */ 139 | void findSmallestUpTo(elfdir *root, size_t minsize, size_t *result) { 140 | for (int j = 0; j < root->subdirs; j++) { 141 | size_t size = root->sub[j]->totalsize; 142 | if (size >= minsize && (*result == 0 || *result > size)) 143 | *result = size; 144 | findSmallestUpTo(root->sub[j], minsize, result); 145 | } 146 | } 147 | 148 | int main(void) { 149 | elfdir *root = readTree("input.txt"); 150 | printTree(root,0); 151 | size_t part1 = 0; 152 | findTotalUpTo(root,100000,&part1); 153 | printf("part 1 answer: %zu\n", part1); 154 | 155 | size_t minsize = 30000000 - (70000000 - root->totalsize); 156 | size_t part2 = 0; 157 | findSmallestUpTo(root,minsize,&part2); 158 | printf("part 2 answer: %zu\n", part2); 159 | 160 | /* TODO reclaim memory from 'root' :D */ 161 | return 0; 162 | } 163 | -------------------------------------------------------------------------------- /day-12/input.txt: -------------------------------------------------------------------------------- 1 | abcccccccccccaaaaacccccccaaaaaaccccccccccccccccccccccccccccccccaaaaaaaaaaaaaacccccccccccccccccccaaaaaacccccccacccccccccaaccaaccccccccccccccccccccccccccccccaaaaaa 2 | abcccccccccccaaaaaaacccccaaaaaaccccccccaaccccccccccaaaaccccccccaaaaaaaaaaaaaccccccccccccccccccccaaaaaaccccaaaacccccccccaaaaaaccccccccccccccccccccccccccccccccaaaa 3 | abccccccccccaaaaaaaacccccaaaaaccccccccaaaacccccccccaaaacccccccccccaaaaaaacccccccccccccccccccccccaaaaacccccaaaaaaccccccccaaaaacccccccccccaaaccccccccccccccccccaaaa 4 | abccccccccccaaaaaaaaccccccaaaaacccccccaaaacccccccccaaaacccccaaaccccaaaaaaccccccccccccccccccccccccaaaaacccccaaaaacccccccaaaaaacccccccccccaaaacccccccccccccccccaaaa 5 | abccccccccccaaaaaaccccccccaaaaacccccccaaaaccccccccccaaacccccaaaaccaaaaaaaacccccccccccccccccccccccaaaaaccccaaaaacccccccaaaaaaaaccccccccccaaaaccaaccccccccccccaaaaa 6 | abcccccccccccccaaaccccccccccccccccccccccccccccccccccccccccccaaaaccaaaaaaaaccccccccccccccccccccccccccccccccaccaaccccaaaaaaaaaaacccccccccccaaaaaaccccccccccccccaccc 7 | abcacccccccccccccaaaccccccccccccccaaacccccccccccccccccccccccaaaccaaaacccaaacccccccccccccccccccccccaacccccccccccccccaaacccaaccccccccccccccaaaalllllccccccccccccccc 8 | abaacccccccccccccaaaaaacccccccccccaaaccccccccccccccccccccccccccccaaaccccaaaccccccccccccccccccccccaaccccccccccccccccaaaaaaaaccccccccccccccckklllllllccccaaaccccccc 9 | abaaaaacccccccccaaaaaaacccccccccaaaaaaaacccccaacccccccccccccccccccccccccaaaccccccccaacccccccccaaaaacaacaacaacccccaaaaaaaaccccccccccccaaakkkkllllllllcccaaaccccccc 10 | abaaaaaccccccccaaaaaaaacccccccccaaaaaaaacccccaaaaaacccccccccccccccccccccaaaccccccaaaacacccccccaaaaaaaacaaaaaccccaaaaaaaaaccccccccckkkkkkkkkklsssslllcccaaaaaacccc 11 | abaaaccccccccccaaaaaaacccccccccccaaaaacccccccaaaaaaccccccccccccccccccaaaaaaaaccccaaaaaacccccccccaaaaacaaaaacccccaaaaaaaacccaaaccjjkkkkkkkkkssssssslllcccaaaaacccc 12 | abaaaccccccccccccaaaaaacccccaacccaaaaaaccccaaaaaaaccaaaccccccccccccccaaaaaaaacccccaaaacccccccccaaaaaccaaaaaacccccccaaaaaaccaaaajjjjkkkkkkssssssssslllcddaaaaccccc 13 | abcaaacccccccccccaaaaaacaaacaacccaaaaaaccccaaaaaaaaaaaaaaccccccccccccccaaaaaccccccaaaaccccaaaaaaacaaacccaaaaaaacccaaaaaaaccaaajjjjrrrrrrssssuuuussqmmddddaaaccccc 14 | abccaacccccccccccaaccccccaaaaacccaaaccaccccaaaaaaaaaaaaaacccccccccccccaaaaaacccccaacaaccccaaaaacccaaccccacccaaaaaaaaaccaaccaaajjjrrrrrrrrssuuuuuvqqmmmdddaaaccccc 15 | abccccccccaaccccccccccccccaaaaaacccccccccccccaaaaaaaaaaaccccccccccccccaaaaaacccccccccccccaaaaaaccccccccccccaaaaaaaaaacccccccccjjjrrruuuuuuuuuuuvvqqmmmmddddaccccc 16 | abaacccccaaaaccccccccccccaaaaaaacccccccccccccaacccccaaaaacccccccccccccaccaaacccccccccccccaaaaaacccccccccccaaaaaaaaccccccccccccjjjrrruuuuuuuuxyyvvqqqmmmddddcccccc 17 | abaacccccaaaacccccccccccaaaaaaccccccccaaccccccccacccaaaaacccccccccccccccccccccccccccccccccaaaaacccccccccccaaaaaaacccccccccccccjjjrrttuxxxxuxxyyvvqqqqmmmmddddcccc 18 | abaacccccaaaacccccccccccaacaaacccccaaaaacccaaaaaaaccccccccccccccccccccccccccccccccccccccccaaacccccccccccccccaaaaaaccccccccccccjjjrrtttxxxxxxyyyvvqqqqqmmmmdddcccc 19 | abacccccccccccccccccccccccccaaccccccaaaaaccaaaaaaaccccccccaaccccccccccccccccccccccccccccccccccccccccccccccccaaaaaaccccccccccccjjjqrrttxxxxxxyyyvvvvqqqqmmmdddcccc 20 | abccccccccccccccccccccccccccccccccccaaaaaccaaaaaaacccccccaaaccccccccccaaaccccccccccccccccccaaaccccccccccccccaaccccccccccaaccccjjjqqqtttxxxxxyyyyyvvvqqqqmmmeeeccc 21 | SbaaccccccaccaaacccccccccccccccccccaaaaacccaaaaaaaaccccaaaaaaaacccccccaaacaaccccccccccccccaaaaaaccccccccccccccccccccccaaaaaaccciiiqqqttxxxxEzyyyyyvvvqqqnnneeeccc 22 | abaaccccccaaaaaaccccccccccccccccccccccaaccaaaaaaaaaacccaaaaaaaacccccaaaaaaaaccccccccccccccaaaaaaccccccccccccccccccccccaaaaaaccciiiqqtttxxxyyyyyyyvvvvqqqnnneeeccc 23 | abaaaaacccaaaaaaccccccccccccccccccccccccccaaaaaaaaaaccccaaaaaaccccccaaaaaaaaccccccccccccccaaaaaacccccccccccccccccccccccaaaaacciiiqqqttxxyyyyyyywvvvvrrrqnnneeeccc 24 | abaaaaacccaaaaaaaccccccccaaaccccccccccccccaacaaaccccccccaaaaaaccccccaaaaaaaccccccccccccccccaaaaaccccccccccccccccccccccaaaaaccciiiqqtttxxxyyyyywwwvrrrrrnnneeecccc 25 | abaaaccccaaaaaaaaccccccccaaaacccccccccccccccccaaccccccccaaaaaaccccccccaaaaaccccccccccccccccaacaaccccccccccccccccccccccaaaaaccciiqqqttxxxwwwwyyywwrrrrnnnnneeecccc 26 | abaaaccccaaaaaaaaccccccccaaaacccccaaaaacccccccaaccccccccaaccaacccccccaaacaaacccccccccccccccccccccccccccccccccccccccccccccccccciiqqqtttwwwwwwywwwrrrrnnnnneeeccccc 27 | abcaaaccccccaaaccccccccccaaaccccccaaaaacccccccccccccaaaaccccccccccccccaacccccccccccccccccccccccccccccccaaaacccccccccccccccccciiiqqqtttssssswwwwwrrrnnnneeeecccccc 28 | abccaaccccccaaaccccccccccccccccccaaaaaacccccccccccccaaaaccccccccccccccccccccccccccccccccccccccccccccccaaaaacccccccccccccccccciiiqqqqtssssssswwwwrronnnfeeeacccccc 29 | abcccccccccccccccccccccccccccccccaaaaaacccccccccccccaaaaccccccccccccccccccccccccccccccccccccccccccccccaaaaaaccccccccccccccccciiiiqqppssssssswwwwrroonfffeaacccccc 30 | abcccccccccccccccccccccccccccccccaaaaaacaaaccccccccccaacccccccccccccccccccccccccccccccccaaacccccccccccaaaaaaccccccccccccccccccihhpppppppppsssssrrroonfffaaaaacccc 31 | abcccccccccccccccccccccccccccccccccaacccaaaaacccccccccccccccccccccccccccccccccccccccccccaaaaaaccccccccaaaaaccccccccccccccccccchhhhppppppppppssssrooofffaaaaaacccc 32 | abccccccccaaaccccccccccccccccccccccccccaaaaacccccccccccccccccccccccccccccccccccccaccccaaaaaaaaccccccccccaaacccccccccccccccccccchhhhhhhhhpppposssoooofffaaaaaccccc 33 | abccccccccaaaacccccaaccccccccccccccccccaaaaaccccccccccccccccccccccccaaccccccccccaaccccaaaaaaaacccccccccccccccccccccccccccccccccchhhhhhhhhgppooooooofffaaaaacccccc 34 | abaaccccccaaaacccccaacaaccccccccccccccccaaaaacccccccccccccccaacaaccaaaaaaccccaaaaacaacaaaaaaacccccccccccccccccccccccccccccccccccccchhhhhhgggooooooffffaaaaaaccccc 35 | abaaacccccaaaacccccaaaaaccccccccccccccccaaccccccccccccccccccaaaaaccaaaaaaccccaaaaaaaacccaaaaaccccccccccccccccccccccccaaacaacccccccccccccgggggooooffffccccaacccccc 36 | abaaaccccccccccccaaaaaaccccaaccccccccccccccccccaaacccccccccccaaaaaaaaaaaacaacccaaaaaccccaacaaacccccccccccccccccccccccaaaaaaccccccccccccccaggggggggfffcccccccccccc 37 | abaaaccccccccccccaaaaaaaacaaaaccccccccaaaccccccaaaacccccccccaaaaaaaaaaaaaaaaccaaaaacccccaaaaaccccccccccccccaaccccccccaaaaaaccccccccccccccaagggggggfccccccccccccca 38 | abaacccccccccccccaccaaaaacaaaaccccccccaaaccccccaaaacccccccccaaaaccaaaaaaaaaaccaacaaaccccccaaaccccccccccccaaaaaacccccaaaaaaacccccccccccccaaaaccggggcccccccccccccaa 39 | abaacccccccccccccccaaacaccaaaacccccaaaaaaaaccccaaaccccccccccccaaccaaaaaaaacccccccaacccccaacaaaaacccccccccaaaaaacccccaaaaaaaaccccccccccccaaaccccccccccccccccaaacaa 40 | abcccccccccccccccccaaccccccccccccccaaaaaaaaccccccccccccccccccccaaaaaaaaaaaccccccccccccccaaaaaaaacccccccccaaaaaacccccaaaaaaaaccccccccccccacaccccccccccccccccaaaaaa 41 | abccccccccccccccccccccccccccccccccccaaaaaacccccccccccccccccccccaaaaaaaaaaaaccccccccccccccaaaaaaccccccccccaaaaaccccccccaaacccccccccccccccccccccccccccccccccccaaaaa 42 | -------------------------------------------------------------------------------- /day-9/1_2.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #define ELFDIR_NAME_MAX 64 7 | #define ELFDIR_SUB_MAX 16 8 | 9 | /* Our rope world. */ 10 | typedef struct world { 11 | int width; 12 | int height; 13 | int knots; /* Number of simulated knots, head included. */ 14 | int *kx; /* Knots x position. kx[0] is the head of the rope. */ 15 | int *ky; /* Knots y position. ky[0] is the head of the rope. */ 16 | char *visited; /* Positions visited by the tail. */ 17 | } world; 18 | 19 | /* Return the current map size, widht*height. */ 20 | int worldSize(world *w) { 21 | return w->width * w->height; 22 | } 23 | 24 | /* Mark the current tail (last knot) location as visited. */ 25 | void worldVisited(world *w) { 26 | int x = w->kx[w->knots-1]; 27 | int y = w->ky[w->knots-1]; 28 | if (x < 0 || x >= w->width || 29 | y < 0 || y >= w->height) 30 | { 31 | printf("World too small for this simulation!\n"); 32 | exit(1); 33 | } 34 | w->visited[x+y*w->width] = 1; 35 | } 36 | 37 | /* Return the number of places visited. */ 38 | int worldCountVisited(world *w) { 39 | int size = worldSize(w); 40 | int visited = 0; 41 | for (int j = 0; j < size; j++) visited += w->visited[j]; 42 | return visited; 43 | } 44 | 45 | /* Initialize a world structure. */ 46 | world *createWorld(int width, int height, int knots) { 47 | world *w = malloc(sizeof(*w)); 48 | if (!w) return NULL; 49 | w->width = width; 50 | w->height = height; 51 | w->knots = knots; 52 | w->visited = NULL; 53 | w->kx = w->ky = NULL; 54 | w->visited = malloc(worldSize(w)); 55 | w->kx = malloc(w->knots*sizeof(int)); 56 | w->ky = malloc(w->knots*sizeof(int)); 57 | if (!w->visited || !w->kx || !w->ky) { 58 | free(w); 59 | free(w->visited); 60 | free(w->kx); 61 | free(w->ky); 62 | return NULL; 63 | } 64 | 65 | /* Let's put the rope at the center. Head and all its knots start 66 | * at the same positon. */ 67 | for (int j = 0; j < knots; j++) { 68 | w->kx[j] = w->width/2; 69 | w->ky[j] = w->height/2; 70 | } 71 | memset(w->visited,0,worldSize(w)); 72 | worldVisited(w); /* Starting position is visited. */ 73 | return w; 74 | } 75 | 76 | /* Relase map memory. */ 77 | void freeWorld(world *w) { 78 | free(w->visited); 79 | free(w->kx); 80 | free(w->ky); 81 | free(w); 82 | } 83 | 84 | /* Print the current world. */ 85 | void printWorld(world *w) { 86 | for (int y = 0; y < w->height; y++) { 87 | for (int x = 0; x < w->width; x++) { 88 | int c = '.'; 89 | /* Scan each rope knot. Terribly inefficient but enough 90 | * for printing. Loop is reversed since we want 'H' to 91 | * cover the lower ranking nots and so forth. */ 92 | for (int j = w->knots-1; j >= 0; j--) { 93 | if (w->kx[j] == x && w->ky[j] == y) { 94 | c = j == 0 ? 'H' : '0'+j; 95 | } 96 | } 97 | printf("%c",c); 98 | } 99 | printf("\n"); 100 | } 101 | } 102 | 103 | /* Read the rope moves from file and simulate it. Return the world 104 | * state after the simulation took place. Return NULL on out of memory. 105 | * The 'size' parameters is used to select the world width and height: you 106 | * need enough space depending on the movements performed. */ 107 | world *simulateRope(FILE *fp, int size, int knots) { 108 | char buf[1024]; 109 | world *w = createWorld(size,size,knots); 110 | if (w == NULL) return NULL; 111 | while(fgets(buf,sizeof(buf),fp) != NULL) { 112 | /* Skip empty lines. */ 113 | size_t l = strlen(buf); 114 | if (l <= 1) continue; 115 | 116 | /* Strip newline. */ 117 | if (buf[l-1] == '\n') { 118 | buf[l-1] = 0; 119 | l--; 120 | } 121 | 122 | /* Parse movement. */ 123 | buf[1] = 0; 124 | int count = atoi(buf+2); 125 | int vx, vy; 126 | switch(buf[0]) { 127 | case 'R': vx = 1; vy = 0; break; 128 | case 'L': vx = -1; vy = 0; break; 129 | case 'U': vx = 0; vy = -1; break; 130 | case 'D': vx = 0; vy = 1; break; 131 | default: assert(1 != 1); break; /* Shold never happen. */ 132 | } 133 | 134 | /* Simulate moving N times in the specified direction. */ 135 | while(count--) { 136 | /* Move rope head. */ 137 | w->kx[0] += vx; 138 | w->ky[0] += vy; 139 | 140 | /* Recusively propagate the movement to the other 141 | * knots. */ 142 | for (int j = 0; j < knots-1; j++) { 143 | /* We call them Head X,Y and Tail X,Y (hx,hy,tx,ty). 144 | * But actually hx,hy represents the head and tx,ty the 145 | * first knot after the head in the first cycles, and then 146 | * the next pair and so forth. */ 147 | int *hx = w->kx+j; 148 | int *hy = w->ky+j; 149 | int *tx = w->kx+j+1; 150 | int *ty = w->ky+j+1; 151 | 152 | /* Calculate empty distance between head and tail. */ 153 | int dx = *hx - *tx; 154 | int dy = *hy - *ty; 155 | 156 | /* Apply distance to tail to make it follow. Note that as 157 | * long as delta is 1 or 0 we don't care: they are still 158 | * touching or overlapping. 159 | * 160 | * Note that when we perform the move, we aligh the tail 161 | * to the head in the other axis, as this is the rules 162 | * described in the Day 9 puzzle. */ 163 | if ((dx == 2 || dx == -2) && (dy == 2 || dy == -2)) { 164 | /* This movement was not cover in the first case 165 | * of two knots, puzzle 1. So apparently there is 166 | * also the rule that one knot can move aways two 167 | * positions both in x and y, as a result of the move 168 | * it did to follow other knots. In this case we just 169 | * move diagonally. Here the specification of the way 170 | * the rope moved was less than perfect. */ 171 | dx /= 2; 172 | dy /= 2; 173 | (*tx) += dx; 174 | (*ty) += dy; 175 | } else if (dx == 2) { 176 | (*tx)++; 177 | *ty = *hy; 178 | } else if (dx == -2) { 179 | (*tx)--; 180 | *ty = *hy; 181 | } else if (dy == 2) { 182 | (*ty)++; 183 | *tx = *hx; 184 | } else if (dy == -2) { 185 | (*ty)--; 186 | *tx = *hx; 187 | } else { 188 | /* Optimization: if the current knot didn't move, then 189 | * all the following will not move as well. */ 190 | break; 191 | } 192 | } 193 | worldVisited(w); 194 | 195 | # if 0 196 | /* Uncomment here if you want to actaully see what happens 197 | * step by step. However this does not make sense with the 198 | * default world size of 1000... */ 199 | printWorld(w); 200 | printf("\n"); 201 | #endif 202 | } 203 | } 204 | return w; 205 | } 206 | 207 | int main(int argc, char **argv) { 208 | const char *filename = (argc == 2) ? argv[1] : "input.txt"; 209 | FILE *fp = fopen(filename,"r"); 210 | if (fp == NULL) { 211 | perror("Opening input file"); 212 | exit(1); 213 | } 214 | 215 | world *w = simulateRope(fp,1000,10); 216 | printf("The tail visited %d places\n", worldCountVisited(w)); 217 | if (w == NULL) { 218 | printf("Out of memory reading map\n"); 219 | exit(1); 220 | } 221 | fclose(fp); 222 | freeWorld(w); 223 | return 0; 224 | } 225 | -------------------------------------------------------------------------------- /day-12/1_2.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #define ELFDIR_NAME_MAX 64 8 | #define ELFDIR_SUB_MAX 16 9 | 10 | /* Our map. */ 11 | typedef struct map { 12 | int width; 13 | int height; 14 | char *buf; /* Map data: width*height bytes of data. */ 15 | char *aux; /* Aux data, used for visualization in printMap() and more. */ 16 | int sx, sy; /* Start position. */ 17 | } map; 18 | 19 | /* Macros to set/get aux data. */ 20 | #define setAux(m,x,y,v) (m)->aux[(y)*m->width+(x)] = (v) 21 | #define getAux(m,x,y) (m)->aux[(y)*m->width+(x)] 22 | 23 | /* Initialize a map structure. */ 24 | void initMap(map *m) { 25 | m->width = 0; 26 | m->height = 0; 27 | m->buf = NULL; 28 | m->aux = NULL; 29 | m->sx = m->sy = 0; 30 | } 31 | 32 | /* Relase map memory. */ 33 | void freeMap(map *m) { 34 | free(m->buf); 35 | free(m->aux); 36 | free(m); 37 | } 38 | 39 | /* Return the current map size, widht*height. */ 40 | int mapSize(map *m) { 41 | return m->width * m->height; 42 | } 43 | 44 | /* Return the byte at x,y. Performs bound checking returning -1 45 | * for out of range areas. */ 46 | char mapGet(map *m, int x, int y) { 47 | int idx = m->width*y+x; 48 | if (x < 0 || x >= m->width || 49 | y < 0 || y >= m->height) return -1; 50 | return m->buf[idx]; 51 | } 52 | 53 | /* Find 'c' in the map. Return 1 if it was found, 0 otherwise. 54 | * The position is returned in *xp and *yp. */ 55 | int mapFind(map *m, int c, int *xp, int *yp) { 56 | /* Scan the map in a cache obvious way. However this function is not 57 | * speed critical for the search of the solution. */ 58 | for (int y = 0; y < m->height; y++) { 59 | for (int x = 0; x < m->width; x++) { 60 | if (mapGet(m,x,y) == c) { 61 | *xp = x; 62 | *yp = y; 63 | return 1; 64 | } 65 | } 66 | } 67 | return 0; 68 | } 69 | 70 | /* Read the map from the input file and return a map object, or NULL 71 | * on out of memory. */ 72 | map *readMapFromFile(FILE *fp) { 73 | map *m = malloc(sizeof(*m)); 74 | if (!m) return NULL; 75 | initMap(m); 76 | 77 | char buf[1024]; 78 | while(fgets(buf,sizeof(buf),fp) != NULL) { 79 | size_t l = strlen(buf); 80 | if (l <= 1) continue; 81 | if (buf[l-1] == '\n') { 82 | buf[l-1] = 0; 83 | l--; 84 | } 85 | 86 | /* The first line we see we can set the width of the 87 | * map. */ 88 | if (m->width == 0) { 89 | m->width = l; 90 | } else { 91 | /* We want the other lines be equally sized. */ 92 | assert(l == (size_t)m->width); 93 | } 94 | 95 | /* Make space and concat this new line. */ 96 | m->height++; 97 | char *newbuf = realloc(m->buf,mapSize(m)); 98 | if (newbuf == NULL) { 99 | freeMap(m); 100 | return NULL; /* Out of memory. */ 101 | } 102 | m->buf = newbuf; 103 | memcpy(m->buf+mapSize(m)-m->width,buf,l); 104 | } 105 | m->aux = malloc(mapSize(m)); 106 | if (!m->aux) { 107 | freeMap(m); 108 | return NULL; 109 | } 110 | mapFind(m,'S',&m->sx,&m->sy); /* Set the start location. */ 111 | return m; 112 | } 113 | 114 | /* Print the current map and aux value. cx,cy is 115 | * the current position we want to highlight. */ 116 | void printMap(map *m, int cx, int cy) { 117 | for (int y = 0; y < m->height; y++) { 118 | for (int x = 0; x < m->width; x++) { 119 | int h = m->buf[x+y*m->width]; /* Map elevation. */ 120 | int d = m->aux[x+y*m->width]; /* Current path direction. */ 121 | if (x == cx && y == cy) { 122 | printf("\033[32;1m%c\033[0m", h); 123 | } else { 124 | printf("%c", d ? d : h); 125 | } 126 | } 127 | printf("\n"); 128 | } 129 | } 130 | 131 | /* Find the shortest path to get from 'S' to 'E' in map 'map'. 132 | * x,y represent the current position we are at. The pointer 'p' 133 | * is the current path, and 'shortest' is updated every time we find 134 | * a path to 'E' that is shortest than the current value. 135 | * 136 | * If the goal wasn't found, -1 is returned. Otherwise the number 137 | * of steps required to reach it. */ 138 | int findShortestPath(map *m, int target, int invert) { 139 | static struct { /* Use static since this is constant AND we use 140 | deep recursion here. No good to put all this 141 | in the stack every time. */ 142 | int d, dx, dy; 143 | } dir[4] = { 144 | {'>', 1, 0}, 145 | {'<', -1, 0}, 146 | {'^', 0, -1}, 147 | {'v', 0, 1} 148 | }; 149 | 150 | /* Reset "visited" */ 151 | memset(m->aux,0,mapSize(m)); 152 | 153 | /* Poor's man queue... Very poor. */ 154 | struct {int x; int y; int depth;} *queue = malloc(sizeof(queue[0])*10000); 155 | int qlen = 0; 156 | 157 | /* Add the starting point in the queue and mark it as already 158 | * visited. */ 159 | queue[qlen].x = m->sx; 160 | queue[qlen].y = m->sy; 161 | queue[qlen].depth = 0; 162 | qlen++; 163 | setAux(m,m->sx,m->sy,'.'); 164 | 165 | while(qlen) { 166 | qlen--; 167 | int x = queue[0].x; 168 | int y = queue[0].y; 169 | int depth = queue[0].depth; 170 | 171 | /* God, forgive me for what I'm doing: */ 172 | memmove(queue,queue+1,qlen*sizeof(queue[0])); 173 | 174 | /* Check if we are already at 'E'. */ 175 | int curh = mapGet(m,x,y); /* Current elevation. */ 176 | if (curh == target) { 177 | printf("Found a path of len %d\n", depth); 178 | /* The following map printing is nice with small maps, but 179 | * terrible with the actual input. */ 180 | // printMap(m,x,y); 181 | free(queue); 182 | return depth; 183 | } 184 | if (curh == 'S') curh = 'a'; /* Normalize special elevation. */ 185 | 186 | /* Queue all the possible next steps starting from here. */ 187 | for (int j = 0; j < 4; j++) { 188 | int xx = x+dir[j].dx; 189 | int yy = y+dir[j].dy; 190 | int h = mapGet(m,xx,yy); 191 | if (h == 'E') h = 'z'; 192 | if (h == -1) continue; /* Out of our world boundaries. */ 193 | /* Check for height jump. However if 'invert' is true 194 | * instead of following the rule of going back just by 1 195 | * and going lower as much as we wish, we reverse it, and 196 | * we go lower only 1 step, and high as much as we want. 197 | * This is useful for Puzzle 2. */ 198 | if (!invert) { 199 | if ((h - curh) > 1) continue; 200 | } else { 201 | if ((h - curh) < -1) continue; 202 | } 203 | if (getAux(m,xx,yy) != 0) continue; /* Already visited. */ 204 | 205 | /* Remember to explore this path. */ 206 | queue[qlen].x = xx; 207 | queue[qlen].y = yy; 208 | queue[qlen].depth = depth+1; 209 | qlen++; 210 | 211 | /* Mark as visited. */ 212 | setAux(m,xx,yy,'.'); 213 | } 214 | } 215 | free(queue); 216 | return -1; 217 | } 218 | 219 | int main(void) { 220 | /* Read map in memory. */ 221 | map *m = readMapFromFile(stdin); 222 | if (m == NULL) { 223 | printf("Out of memory reading map\n"); 224 | exit(1); 225 | } 226 | 227 | printf("Map loaded. Size: %dx%d\n", m->width, m->height); 228 | printf("Start is at %d,%d\n", m->sx, m->sy); 229 | findShortestPath(m,'E',0); 230 | 231 | /* To find the shortest a -> E, we do a trick, start from E and 232 | * search for the first 'a', however we have to fix those 'S' 233 | * and 'E' special chars that will create issues otherwise. */ 234 | m->buf[m->sx+m->sy*m->width] = 'a'; 235 | mapFind(m,'E',&m->sx,&m->sy); /* Set the start location. */ 236 | m->buf[m->sx+m->sy*m->width] = 'z'; 237 | findShortestPath(m,'a',1); 238 | 239 | /* Cleanup. */ 240 | freeMap(m); 241 | return 0; 242 | } 243 | -------------------------------------------------------------------------------- /day-13/1_2.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | /* This describes our elf object type. It can be used to represent 9 | * nested lists of lists and/or integers. */ 10 | #define ELFOBJ_TYPE_INT 0 11 | #define ELFOBJ_TYPE_LIST 1 12 | typedef struct elfobj { 13 | int type; /* ELFOBJ_TYPE_... */ 14 | union { 15 | int i; /* Integer value. */ 16 | struct { /* List value. */ 17 | struct elfobj **ele; 18 | size_t len; 19 | } l; 20 | } val; 21 | } elfobj; 22 | 23 | /* Life is too short to handle OOM for Advent of Code. */ 24 | void *elfalloc(size_t size) { 25 | void *p = malloc(size); 26 | if (!p) { 27 | fprintf(stderr,"Out of memory allocating %zu bytes\n", size); 28 | exit(1); 29 | } 30 | return p; 31 | } 32 | 33 | void *elfrealloc(void *ptr, size_t size) { 34 | void *p = realloc(ptr,size); 35 | if (!p) { 36 | fprintf(stderr,"Out of memory allocating %zu bytes\n", size); 37 | exit(1); 38 | } 39 | return p; 40 | } 41 | 42 | /* Recursively free an elf object. */ 43 | void freeElfObj(elfobj *obj) { 44 | switch(obj->type) { 45 | case ELFOBJ_TYPE_INT: break; /* Nothing nested to free. */ 46 | case ELFOBJ_TYPE_LIST: 47 | for (size_t j = 0; j < obj->val.l.len; j++) 48 | freeElfObj(obj->val.l.ele[j]); 49 | free(obj->val.l.ele); 50 | break; 51 | } 52 | free(obj); 53 | } 54 | 55 | /* Given the string 's' return the elfobj representing the list or 56 | * NULL on syntax error. '*next' is set to the next byte to parse, after 57 | * the current value was completely parsed. */ 58 | elfobj *parseList(const char *s, const char **next) { 59 | elfobj *obj = elfalloc(sizeof(*obj)); 60 | while(isspace(s[0])) s++; 61 | if (s[0] == '-' || isdigit(s[0])) { 62 | char buf[64]; 63 | size_t len = 0; 64 | while((*s == '-' || isdigit(*s)) && len < sizeof(buf)-1) 65 | buf[len++] = *s++; 66 | buf[len] = 0; 67 | obj->type = ELFOBJ_TYPE_INT; 68 | obj->val.i = atoi(buf); 69 | if (next) *next = s; 70 | return obj; 71 | } else if (s[0] == '[') { 72 | obj->type = ELFOBJ_TYPE_LIST; 73 | obj->val.l.len = 0; 74 | obj->val.l.ele = NULL; 75 | s++; 76 | /* Parse comma separated elements. */ 77 | while(1) { 78 | /* The list may be empty, so we need to parse for "]" 79 | * ASAP. */ 80 | while(isspace(s[0])) s++; 81 | if (s[0] == ']') { 82 | if (next) *next = s+1; 83 | return obj; 84 | } 85 | 86 | /* Parse the current sub-element recursively. */ 87 | const char *nextptr; 88 | elfobj *element = parseList(s,&nextptr); 89 | if (element == NULL) { 90 | freeElfObj(obj); 91 | return NULL; 92 | } 93 | obj->val.l.ele = elfrealloc(obj->val.l.ele, 94 | sizeof(elfobj*)*(obj->val.l.len+1)); 95 | obj->val.l.ele[obj->val.l.len++] = element; 96 | s = nextptr; /* Continue from first byte not parsed. */ 97 | 98 | while(isspace(s[0])) s++; 99 | if (s[0] == ']') continue; /* Will be handled by the loop. */ 100 | if (s[0] == ',') { 101 | s++; 102 | continue; /* Parse next element. */ 103 | } 104 | 105 | /* Syntax error. */ 106 | freeElfObj(obj); 107 | return NULL; 108 | } 109 | /* Syntax error (list not closed). */ 110 | freeElfObj(obj); 111 | return NULL; 112 | } else { 113 | /* In a serious program you don't printf() in the middle of 114 | * a function. Just return NULL. */ 115 | fprintf(stderr,"Syntax error parsing '%s'\n", s); 116 | return NULL; 117 | } 118 | return obj; 119 | } 120 | 121 | /* Output an object human readable representation .*/ 122 | void printElfObj(elfobj *obj) { 123 | switch(obj->type) { 124 | case ELFOBJ_TYPE_INT: 125 | printf("%d",obj->val.i); 126 | break; 127 | case ELFOBJ_TYPE_LIST: 128 | printf("["); 129 | for (size_t j = 0; j < obj->val.l.len; j++) { 130 | printElfObj(obj->val.l.ele[j]); 131 | if (j != obj->val.l.len-1) printf(", "); 132 | } 133 | printf("]"); 134 | break; 135 | } 136 | } 137 | 138 | /* Read the lists contained in the file 'fp', parse them into an elfobj 139 | * type and populate v[...] with the values. The number of lists processed 140 | * is returned. */ 141 | int readLists(FILE *fp, elfobj **v, size_t vlen) { 142 | char buf[1024]; 143 | size_t idx = 0; 144 | while(fgets(buf,sizeof(buf),fp) != NULL && idx < vlen) { 145 | size_t l = strlen(buf); 146 | if (l <= 1) continue; 147 | if (buf[l-1] == '\n') { 148 | buf[l-1] = 0; 149 | l--; 150 | } 151 | v[idx++] = parseList(buf,NULL); 152 | } 153 | return idx; 154 | } 155 | 156 | /* Compare the two objects 'a' and 'b' and return: 157 | * -1 if ab. */ 158 | int compare(elfobj *a, elfobj *b) { 159 | if (a->type == ELFOBJ_TYPE_INT && b->type == ELFOBJ_TYPE_INT) { 160 | if (a->val.i < b->val.i) return -1; 161 | else if (a->val.i > b->val.i) return 1; 162 | return 0; 163 | } 164 | 165 | /* If one of the objects is not a list, promote it to a list. 166 | * Just use the stack to avoid allocating stuff for a single 167 | * element list. */ 168 | elfobj list, listele, *ele[1]; 169 | list.type = ELFOBJ_TYPE_LIST; 170 | list.val.l.len = 1; 171 | list.val.l.ele = ele; 172 | list.val.l.ele[0] = &listele; 173 | listele.type = ELFOBJ_TYPE_INT; 174 | 175 | /* Promote. */ 176 | if (a->type == ELFOBJ_TYPE_INT) { 177 | listele.val.i = a->val.i; 178 | a = &list; 179 | } else if (b->type == ELFOBJ_TYPE_INT) { 180 | listele.val.i = b->val.i; 181 | b = &list; 182 | } 183 | 184 | /* Now we can handle the list to list comparison without 185 | * special cases. */ 186 | size_t minlen = a->val.l.len < b->val.l.len ? a->val.l.len : b->val.l.len; 187 | for (size_t j = 0; j < minlen; j++) { 188 | int cmp = compare(a->val.l.ele[j],b->val.l.ele[j]); 189 | if (cmp != 0) return cmp; 190 | } 191 | 192 | /* First MIN(len_a,len_b) elements are the same? Longer list wins. */ 193 | if (a->val.l.len < b->val.l.len) return -1; 194 | else if (a->val.l.len > b->val.l.len) return 1; 195 | return 0; 196 | } 197 | 198 | /* qsort() helper to sort arrays of elfobj pointers. */ 199 | int qsort_list_cmp(const void *a, const void *b) { 200 | elfobj **obja = (elfobj**)a, **objb = (elfobj**)b; 201 | return compare(obja[0],objb[0]); 202 | } 203 | 204 | #define LISTS_MAX 1024 205 | int main(int argc, char **argv) { 206 | if (argc != 2) { 207 | printf("Usage: %s \n",argv[0]); 208 | exit(1); 209 | } 210 | elfobj *lists[LISTS_MAX]; 211 | FILE *fp = fopen(argv[1],"r"); 212 | if (!fp) { 213 | perror("Can't open file"); 214 | exit(1); 215 | } 216 | size_t count = readLists(fp,lists,LISTS_MAX); 217 | fclose(fp); 218 | 219 | printf("%zu lists read from file\n", count); 220 | assert(count % 2 == 0); /* Must be all pairs. */ 221 | 222 | /* Part 1: just compare all the pairs and do the sum. */ 223 | int okpairs = 0; 224 | for (size_t j = 0; j < count; j += 2) { 225 | int cmp = compare(lists[j], lists[j+1]); 226 | if (cmp == -1) okpairs += (j/2)+1; 227 | } 228 | printf("Puzzle 1: %d\n", okpairs); 229 | 230 | /* Part 2: add the two additional lists. */ 231 | elfobj *div1 = parseList("[[2]]",NULL); 232 | elfobj *div2 = parseList("[[6]]",NULL); 233 | lists[count++] = div1; 234 | lists[count++] = div2; 235 | qsort(lists,count,sizeof(elfobj*),qsort_list_cmp); 236 | 237 | /* Now scan the list to locate div1 and div2. */ 238 | size_t div1idx, div2idx; 239 | for (size_t j = 0; j < count; j++) { 240 | if (lists[j] == div1) div1idx = j+1; 241 | else if (lists[j] == div2) div2idx = j+1; 242 | } 243 | printf("Puzzle 2: %zu\n", div1idx*div2idx); 244 | return 0; 245 | } 246 | -------------------------------------------------------------------------------- /day-14/anim.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include /* usleep(). */ 8 | 9 | #if 1 /* small.txt */ 10 | #define XOFFSET 480 /* World appears to start at x >= 490. */ 11 | #define WORLDW 50 12 | #define WORLDH 15 13 | #else /* input.txt needs bigger world. */ 14 | #define XOFFSET 280 /* Make more space for sand to rest. */ 15 | #define WORLDW 500 16 | #define WORLDH 300 17 | #endif 18 | 19 | /* Our map. */ 20 | typedef struct map { 21 | int width; 22 | int height; 23 | char *buf; /* Map data: width*height bytes of data. */ 24 | char *aux; /* Aux data, used for visualization in printMap() and more. */ 25 | int sx, sy; /* Start position. */ 26 | } map; 27 | 28 | /* Macros to set/get aux data. */ 29 | #define setAux(m,x,y,v) (m)->aux[(y)*m->width+(x)] = (v) 30 | #define getAux(m,x,y) (m)->aux[(y)*m->width+(x)] 31 | 32 | /* Allocate and initialize a map structure of the specified 33 | * width 'w' and height 'h'. Return NULL on OOM. */ 34 | map *createMap(int w, int h) { 35 | map *m = malloc(sizeof(*m)); 36 | if (!m) return NULL; 37 | m->width = w; 38 | m->height = h; 39 | m->buf = malloc(w*h); 40 | m->aux = malloc(w*h); 41 | if (!m->buf || !m->aux) { 42 | free(m->buf); 43 | free(m->aux); 44 | return NULL; 45 | } 46 | m->sx = m->sy = 0; 47 | return m; 48 | } 49 | 50 | /* Relase map memory. */ 51 | void freeMap(map *m) { 52 | free(m->buf); 53 | free(m->aux); 54 | free(m); 55 | } 56 | 57 | /* Return the current map size, widht*height. */ 58 | int mapSize(map *m) { 59 | return m->width * m->height; 60 | } 61 | 62 | /* Print the current map and aux value. cx,cy is 63 | * the current position we want to highlight. */ 64 | void printMap(map *m, int cx, int cy) { 65 | for (int y = 0; y < m->height; y++) { 66 | for (int x = 0; x < m->width; x++) { 67 | int h = m->buf[x+y*m->width]; /* Map elevation / value. */ 68 | int d = m->aux[x+y*m->width]; /* Aux data. */ 69 | if (h == 0) h = '.'; 70 | if (x == cx && y == cy) { 71 | printf("\033[32;1m%c\033[0m", h); 72 | } else { 73 | printf("%c", d ? d : h); 74 | } 75 | } 76 | printf("\n"); 77 | } 78 | } 79 | 80 | /* Return the byte at x,y. Performs bound checking returning -1 81 | * for out of range areas. */ 82 | char mapGet(map *m, int x, int y) { 83 | int idx = m->width*y+x; 84 | if (x < 0 || x >= m->width || 85 | y < 0 || y >= m->height) return -1; 86 | return m->buf[idx]; 87 | } 88 | 89 | /* Set the specific point on the map. Silently discards out of range 90 | * coordinates. */ 91 | void mapSet(map *m, int x, int y, int c) { 92 | int idx = m->width*y+x; 93 | if (x < 0 || x >= m->width || 94 | y < 0 || y >= m->height) return; 95 | m->buf[idx] = c; 96 | } 97 | 98 | /* Draws a line from x1,y1 to x2,y2. The function is pretty trivial and 99 | * will not work if the line is not exactly horizontal, vertical or diagonal. */ 100 | void mapLine(map *m, int x1, int y1, int x2, int y2, int c) { 101 | int dx = x2-x1; 102 | int dy = y2-y1; 103 | 104 | /* Normalize retaining sign. */ 105 | if (dx) dx /= abs(dx); 106 | if (dy) dy /= abs(dy); 107 | 108 | int x = x1, y = y1; 109 | while(1) { 110 | mapSet(m,x,y,c); 111 | if (x == x2 && y == y2) break; 112 | x += dx; 113 | y += dy; 114 | } 115 | } 116 | 117 | /* Find 'c' in the map. Return 1 if it was found, 0 otherwise. 118 | * The position is returned in *xp and *yp. */ 119 | int mapFind(map *m, int c, int *xp, int *yp) { 120 | /* Scan the map in a cache obvious way. However this function is not 121 | * speed critical for the search of the solution. */ 122 | for (int y = 0; y < m->height; y++) { 123 | for (int x = 0; x < m->width; x++) { 124 | if (mapGet(m,x,y) == c) { 125 | *xp = x; 126 | *yp = y; 127 | return 1; 128 | } 129 | } 130 | } 131 | return 0; 132 | } 133 | 134 | /* Read the map from the input file and return a map object, or NULL 135 | * on out of memory. */ 136 | map *readMapFromFile(FILE *fp, int *maxyp) { 137 | map *m = createMap(WORLDW,WORLDH); 138 | if (!m) return NULL; 139 | 140 | char buf[1024]; 141 | int maxy = 0; 142 | while(fgets(buf,sizeof(buf),fp) != NULL) { 143 | size_t l = strlen(buf); 144 | if (l <= 1) continue; 145 | if (buf[l-1] == '\n') { 146 | buf[l-1] = 0; 147 | l--; 148 | } 149 | 150 | /* Lines are in the form x1,y1 -> x2,y2 -> x3,y2 -> ... */ 151 | int x1, y1, x2, y2; 152 | int count = 0; 153 | char *p = buf; 154 | while(1) { 155 | while(isspace(*p)) p++; 156 | char *sep = strchr(p,'>'); /* Seek -> */ 157 | if (sep) sep[-1] = 0; 158 | 159 | /* Now p points to the x coordinate, seek y. */ 160 | char *yp = strchr(p,','); 161 | assert(yp != NULL); 162 | *yp = 0; yp++; /* yp points to y coordinate. */ 163 | x2 = atoi(p); 164 | y2 = atoi(yp); 165 | 166 | x2 -= XOFFSET; /* World seems to start at around 490. */ 167 | assert(x2 > 0); 168 | 169 | if (count) { /* Nothing to draw if it's the first pair of 170 | numbers seen. */ 171 | if (x1 >= m->width || x2 >= m->width || 172 | y1 >= m->height || y2 >= m->height) 173 | { 174 | printf("Map is too small for this world.\n"); 175 | exit(1); 176 | } 177 | mapLine(m,x1,y1,x2,y2,'#'); 178 | if (y1 > maxy) maxy = y1; 179 | if (y2 > maxy) maxy = y2; 180 | } 181 | 182 | /* More data? */ 183 | if (!sep) break; 184 | 185 | p = sep+1; /* Skip "->" */ 186 | x1 = x2; 187 | y1 = y2; 188 | count++; 189 | } 190 | } 191 | *maxyp = maxy; 192 | return m; 193 | } 194 | 195 | /* Simulate sand falling from 500,0. Return the resting position 196 | * in *rx, *ry. If the sand fall out of the world limits they 197 | * will be set to -1,-1. 198 | * 199 | * If animate is non zero, the map is printed and the screen cleared at 200 | * every step. */ 201 | void simulSand(map *m, int *rx, int *ry, int animate) { 202 | int x = 500-XOFFSET; 203 | int y = 0; 204 | 205 | struct { 206 | int dx, dy; 207 | } nextpos[3] = { 208 | {0,1}, /* Down. */ 209 | {-1,1}, /* Down left. */ 210 | {1,1} /* Down right. */ 211 | }; 212 | 213 | while(1) { 214 | int j; 215 | for (j = 0; j < 3; j++) { 216 | int nx = x + nextpos[j].dx; 217 | int ny = y + nextpos[j].dy; 218 | int cur = mapGet(m,nx,ny); 219 | if (cur == -1) { 220 | /* Out of range. */ 221 | *rx = -1; 222 | *ry = -1; 223 | return; 224 | } 225 | if (cur != 0) continue; /* Try next direction. */ 226 | x = nx; 227 | y = ny; 228 | break; 229 | } 230 | 231 | if (animate) { 232 | mapSet(m,x,y,'+'); 233 | printf("\x1b[H\x1b[2J"); 234 | printMap(m,x,y); 235 | mapSet(m,x,y,0); 236 | fflush(stdout); 237 | usleep(30000); 238 | } 239 | 240 | if (j == 3) { 241 | /* This sand can't move more. */ 242 | *rx = x; 243 | *ry = y; 244 | mapSet(m,x,y,'o'); 245 | return; 246 | } 247 | } 248 | } 249 | 250 | int main(int argc, char **argv) { 251 | FILE *fp; 252 | if (argc != 2) { 253 | fp = stdin; 254 | } else { 255 | fp = fopen(argv[1],"r"); 256 | if (!fp) { 257 | perror("Opening file"); 258 | exit(1); 259 | } 260 | } 261 | 262 | /* Read map in memory. */ 263 | int maxy; /* Used for part 2. */ 264 | map *m = readMapFromFile(fp,&maxy); 265 | if (argc == 2) fclose(fp); 266 | if (m == NULL) { 267 | printf("Out of memory reading map\n"); 268 | exit(1); 269 | } 270 | 271 | /* Draw the floor. */ 272 | mapLine(m,0,maxy+2,m->width-1,maxy+2,'_'); 273 | int count = 0; 274 | 275 | /* Show the animation. */ 276 | while(1) { 277 | int restx, resty; /* Where the sand rested. */ 278 | simulSand(m,&restx,&resty,1); 279 | if (restx == 500-XOFFSET && resty == 0) break; 280 | count++; 281 | } 282 | 283 | /* Cleanup. */ 284 | freeMap(m); 285 | return 0; 286 | } 287 | -------------------------------------------------------------------------------- /day-8/1_2.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #define ELFDIR_NAME_MAX 64 7 | #define ELFDIR_SUB_MAX 16 8 | 9 | /* Our map. */ 10 | typedef struct map { 11 | int width; 12 | int height; 13 | char *buf; /* Map data: width*height bytes of data. */ 14 | char *aux; /* Aux data used for running algorithms on the three. */ 15 | } map; 16 | 17 | /* Initialize a map structure. */ 18 | void initMap(map *m) { 19 | m->width = 0; 20 | m->height = 0; 21 | m->buf = NULL; 22 | m->aux = NULL; 23 | } 24 | 25 | /* Relase map memory. */ 26 | void freeMap(map *m) { 27 | free(m->buf); 28 | free(m->aux); 29 | free(m); 30 | } 31 | 32 | /* Return the current map size, widht*height. */ 33 | int mapSize(map *m) { 34 | return m->width * m->height; 35 | } 36 | 37 | /* Return the byte at x,y. Performs bound checking returning -1 38 | * for out of range areas. */ 39 | char mapGet(map *m, int x, int y) { 40 | int idx = m->width*y+x; 41 | if (x < 0 || x >= m->width || 42 | y < 0 || y >= m->height) return -1; 43 | return m->buf[idx]; 44 | } 45 | 46 | /* Read the map from the input file and return a map object, or NULL 47 | * on out of memory. */ 48 | map *readMapFromFile(FILE *fp) { 49 | map *m = malloc(sizeof(*m)); 50 | if (!m) return NULL; 51 | initMap(m); 52 | 53 | char buf[1024]; 54 | while(fgets(buf,sizeof(buf),fp) != NULL) { 55 | size_t l = strlen(buf); 56 | if (l <= 1) continue; 57 | if (buf[l-1] == '\n') { 58 | buf[l-1] = 0; 59 | l--; 60 | } 61 | 62 | /* The first line we see we can set the width of the 63 | * map. */ 64 | if (m->width == 0) { 65 | m->width = l; 66 | } else { 67 | /* We want the other lines be equally sized. */ 68 | assert(l == (size_t)m->width); 69 | } 70 | 71 | /* Make space and concat this new line. */ 72 | m->height++; 73 | char *newbuf = realloc(m->buf,mapSize(m)); 74 | if (newbuf == NULL) { 75 | freeMap(m); 76 | return NULL; /* Out of memory. */ 77 | } 78 | m->buf = newbuf; 79 | memcpy(m->buf+mapSize(m)-m->width,buf,l); 80 | } 81 | return m; 82 | } 83 | 84 | /* Print the current map and aux value. */ 85 | void mapPrint(map *m) { 86 | for (int y = 0; y < m->height; y++) { 87 | for (int x = 0; x < m->width; x++) { 88 | printf("%c[%d]", m->buf[x+y*m->width], 89 | m->aux ? m->aux[x+y*m->width] : 0); 90 | } 91 | printf("\n"); 92 | } 93 | } 94 | 95 | /* countVisibleTrees() helper: 96 | * 97 | * This function scans the map 'm' for visible trees in a specific direction. 98 | * The scan starts at px, py, and visits consecutive map cells moving every 99 | * time by x += vx, y+= vy. When the scan of the current line ends, it starts 100 | * again from where it was before scanning this line, but moving to the next 101 | * line doing x+= nx, y+= ny. 102 | * 103 | * So for instance starting at px = 0, py = 0, with velocity vx = 1, vy = 0, 104 | * means that each line scanned we move towards right. Then when this line 105 | * was completely scanned, we restore the current x,y position we had before 106 | * the line scan, and update them using nx, ny. In this case we would use 107 | * nx = 0 and ny = 1 to start again our left-to-right scan in the next row. 108 | * 109 | * The algorith used is simple: we mark each point in the map as visible as 110 | * at each new line scanned the current point is the highest visited so far. 111 | * 112 | * As visible trees are found, they are marked in m->aux, that must be 113 | * already allocated. */ 114 | void markVisibleTrees(map *m, int px, int py, /* Position x,y */ 115 | int vx, int vy, /* Velocity x,y (direction) */ 116 | int nx, int ny) /* Change line movement. */ 117 | { 118 | int x = px, y = py; /* Our starting points. */ 119 | int bx, by; /* We save the starting point at the start of each line. */ 120 | int steps = mapSize(m); 121 | while(steps--) { 122 | bx = x, by = y; /* Save starting point. */ 123 | int max = 0; /* Max height seen so far. */ 124 | int c; /* Current value on the map. */ 125 | while((c = mapGet(m,x,y)) != -1) { 126 | if (c > max) { 127 | m->aux[y*m->width+x] = 1; 128 | max = c; 129 | } 130 | /* Go to next point of current line. */ 131 | x += vx; 132 | y += vy; 133 | } 134 | /* Go to next line. */ 135 | x = bx+nx; 136 | y = by+ny; 137 | } 138 | } 139 | 140 | /* Count all the threes that are not protected from one of the borders 141 | * by a tree that is higher or the same length. On out of memory 142 | * zero is returned. */ 143 | int countVisibleTrees(map *m) { 144 | /* We don't want to use an O(N*N) algorithm that casts from every 145 | * point to all the four directions. There is a simple four pass O(N) 146 | * algorithm that will do: 147 | * 148 | * 1. From each direction, mark all the trees that have an height 149 | * greater than any tree seen so far visiting trees in that 150 | * direction. 151 | * 2 At the end of the four scans all the trees that are marked 152 | * are all visible. 153 | * 154 | * To do so we use a markVisibleTrees() function. it takes a starting 155 | * point and a direction vector. This way we can generalize the marking 156 | * stage needed for all the four sides. */ 157 | 158 | /* To run this algorithm, we use an auxiliary map data where we mark 159 | * the trees without destroying our view of the height map. */ 160 | if (m->aux == NULL) { 161 | m->aux = malloc(mapSize(m)); 162 | if (!m->aux) return 0; 163 | } 164 | memset(m->aux,0,mapSize(m)); 165 | 166 | /* The following starting points, directions, and next line calls 167 | * correspond to: 168 | * 1. From upper-left corner, toward east, one step south each line. 169 | * 2. From upper-right corner, toward west, one step south each line. 170 | * 3. From upper-left corner, towards south, one step east each line. 171 | * 3. From bottom-left corner, towards north, one step east each line. */ 172 | markVisibleTrees(m,0,0,1,0,0,1); 173 | markVisibleTrees(m,m->width-1,0,-1,0,0,1); 174 | markVisibleTrees(m,0,0,0,1,1,0); 175 | markVisibleTrees(m,0,m->height-1,0,-1,1,0); 176 | 177 | int visible = 0, size = mapSize(m); 178 | for (int j = 0; j < size; j++) visible += m->aux[j]; 179 | return visible; 180 | } 181 | 182 | /* computeScenicScore() helper: 183 | * 184 | * This function starts from x, y and goes toward vx, vy, counting 185 | * the number of visible trees: we walk as soon as we reach the border 186 | * or a tree of height equal or higher than the current one. */ 187 | int viewDistance(map *m, int x, int y, /* Position x,y */ 188 | int vx, int vy) /* Velocity x,y (direction) */ 189 | { 190 | int distance = 0; 191 | int height = mapGet(m,x,y); 192 | while(1) { 193 | x += vx; 194 | y += vy; 195 | int this = mapGet(m,x,y); 196 | if (this == -1) break; /* Border reached. */ 197 | distance++; 198 | if (this >= height) break; /* Tall tree reached. */ 199 | } 200 | return distance; 201 | } 202 | 203 | /* Compute the scenic score for point x,y. */ 204 | int computeScenicScore(map *m, int x, int y) { 205 | return viewDistance(m,x,y,1,0) * 206 | viewDistance(m,x,y,-1,0) * 207 | viewDistance(m,x,y,0,1) * 208 | viewDistance(m,x,y,0,-1); 209 | } 210 | 211 | int main(int argc, char **argv) { 212 | /* Read map in memory. */ 213 | const char *filename = (argc == 2) ? argv[1] : "input.txt"; 214 | FILE *fp = fopen(filename,"r"); 215 | if (fp == NULL) { 216 | perror("Opening input file"); 217 | exit(1); 218 | } 219 | map *m = readMapFromFile(fp); 220 | if (m == NULL) { 221 | printf("Out of memory reading map\n"); 222 | exit(1); 223 | } 224 | fclose(fp); 225 | 226 | printf("Map loaded. Size: %dx%d\n", m->width, m->height); 227 | 228 | /* Puzzle 1. */ 229 | int visible = countVisibleTrees(m); 230 | printf("Visble trees: %d\n", visible); 231 | 232 | /* Puzzle 2. 233 | * 234 | * Here we resort to a O(N^2) algorithm even if it's likely 235 | * we can do better (for instance marking trees that can't be 236 | * better by already computed trees exploiting the fact scores of 237 | * nearby trees are not independent). */ 238 | int best_score = 0; 239 | for (int x = 0; x < m->width; x++) { 240 | for (int y = 0; y < m->height; y++) { 241 | int score = computeScenicScore(m,x,y); 242 | if (score > best_score) best_score = score; 243 | } 244 | } 245 | printf("Best scenic score: %d\n", best_score); 246 | 247 | /* Cleanup. */ 248 | freeMap(m); 249 | 250 | return 0; 251 | } 252 | -------------------------------------------------------------------------------- /day-14/1_2.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include /* usleep(). */ 8 | 9 | #if 1 /* small.txt */ 10 | #define XOFFSET 480 /* World appears to start at x >= 490. */ 11 | #define WORLDW 50 12 | #define WORLDH 15 13 | #else /* input.txt needs bigger world. */ 14 | #define XOFFSET 280 /* Make more space for sand to rest. */ 15 | #define WORLDW 500 16 | #define WORLDH 300 17 | #endif 18 | 19 | /* Our map. */ 20 | typedef struct map { 21 | int width; 22 | int height; 23 | char *buf; /* Map data: width*height bytes of data. */ 24 | char *aux; /* Aux data, used for visualization in printMap() and more. */ 25 | int sx, sy; /* Start position. */ 26 | } map; 27 | 28 | /* Macros to set/get aux data. */ 29 | #define setAux(m,x,y,v) (m)->aux[(y)*m->width+(x)] = (v) 30 | #define getAux(m,x,y) (m)->aux[(y)*m->width+(x)] 31 | 32 | /* Allocate and initialize a map structure of the specified 33 | * width 'w' and height 'h'. Return NULL on OOM. */ 34 | map *createMap(int w, int h) { 35 | map *m = malloc(sizeof(*m)); 36 | if (!m) return NULL; 37 | m->width = w; 38 | m->height = h; 39 | m->buf = malloc(w*h); 40 | m->aux = malloc(w*h); 41 | if (!m->buf || !m->aux) { 42 | free(m->buf); 43 | free(m->aux); 44 | return NULL; 45 | } 46 | m->sx = m->sy = 0; 47 | return m; 48 | } 49 | 50 | /* Relase map memory. */ 51 | void freeMap(map *m) { 52 | free(m->buf); 53 | free(m->aux); 54 | free(m); 55 | } 56 | 57 | /* Return the current map size, widht*height. */ 58 | int mapSize(map *m) { 59 | return m->width * m->height; 60 | } 61 | 62 | /* Print the current map and aux value. cx,cy is 63 | * the current position we want to highlight. */ 64 | void printMap(map *m, int cx, int cy) { 65 | for (int y = 0; y < m->height; y++) { 66 | for (int x = 0; x < m->width; x++) { 67 | int h = m->buf[x+y*m->width]; /* Map elevation / value. */ 68 | int d = m->aux[x+y*m->width]; /* Aux data. */ 69 | if (h == 0) h = '.'; 70 | if (x == cx && y == cy) { 71 | printf("\033[32;1m%c\033[0m", h); 72 | } else { 73 | printf("%c", d ? d : h); 74 | } 75 | } 76 | printf("\n"); 77 | } 78 | } 79 | 80 | /* Return the byte at x,y. Performs bound checking returning -1 81 | * for out of range areas. */ 82 | char mapGet(map *m, int x, int y) { 83 | int idx = m->width*y+x; 84 | if (x < 0 || x >= m->width || 85 | y < 0 || y >= m->height) return -1; 86 | return m->buf[idx]; 87 | } 88 | 89 | /* Set the specific point on the map. Silently discards out of range 90 | * coordinates. */ 91 | void mapSet(map *m, int x, int y, int c) { 92 | int idx = m->width*y+x; 93 | if (x < 0 || x >= m->width || 94 | y < 0 || y >= m->height) return; 95 | m->buf[idx] = c; 96 | } 97 | 98 | /* Draws a line from x1,y1 to x2,y2. The function is pretty trivial and 99 | * will not work if the line is not exactly horizontal, vertical or diagonal. */ 100 | void mapLine(map *m, int x1, int y1, int x2, int y2, int c) { 101 | int dx = x2-x1; 102 | int dy = y2-y1; 103 | 104 | /* Normalize retaining sign. */ 105 | if (dx) dx /= abs(dx); 106 | if (dy) dy /= abs(dy); 107 | 108 | int x = x1, y = y1; 109 | while(1) { 110 | mapSet(m,x,y,c); 111 | if (x == x2 && y == y2) break; 112 | x += dx; 113 | y += dy; 114 | } 115 | } 116 | 117 | /* Find 'c' in the map. Return 1 if it was found, 0 otherwise. 118 | * The position is returned in *xp and *yp. */ 119 | int mapFind(map *m, int c, int *xp, int *yp) { 120 | /* Scan the map in a cache obvious way. However this function is not 121 | * speed critical for the search of the solution. */ 122 | for (int y = 0; y < m->height; y++) { 123 | for (int x = 0; x < m->width; x++) { 124 | if (mapGet(m,x,y) == c) { 125 | *xp = x; 126 | *yp = y; 127 | return 1; 128 | } 129 | } 130 | } 131 | return 0; 132 | } 133 | 134 | /* Read the map from the input file and return a map object, or NULL 135 | * on out of memory. */ 136 | map *readMapFromFile(FILE *fp, int *maxyp) { 137 | map *m = createMap(WORLDW,WORLDH); 138 | if (!m) return NULL; 139 | 140 | char buf[1024]; 141 | int maxy = 0; 142 | while(fgets(buf,sizeof(buf),fp) != NULL) { 143 | size_t l = strlen(buf); 144 | if (l <= 1) continue; 145 | if (buf[l-1] == '\n') { 146 | buf[l-1] = 0; 147 | l--; 148 | } 149 | 150 | /* Lines are in the form x1,y1 -> x2,y2 -> x3,y2 -> ... */ 151 | int x1, y1, x2, y2; 152 | int count = 0; 153 | char *p = buf; 154 | while(1) { 155 | while(isspace(*p)) p++; 156 | char *sep = strchr(p,'>'); /* Seek -> */ 157 | if (sep) sep[-1] = 0; 158 | 159 | /* Now p points to the x coordinate, seek y. */ 160 | char *yp = strchr(p,','); 161 | assert(yp != NULL); 162 | *yp = 0; yp++; /* yp points to y coordinate. */ 163 | x2 = atoi(p); 164 | y2 = atoi(yp); 165 | 166 | x2 -= XOFFSET; /* World seems to start at around 490. */ 167 | assert(x2 > 0); 168 | 169 | if (count) { /* Nothing to draw if it's the first pair of 170 | numbers seen. */ 171 | if (x1 >= m->width || x2 >= m->width || 172 | y1 >= m->height || y2 >= m->height) 173 | { 174 | printf("Map is too small for this world.\n"); 175 | exit(1); 176 | } 177 | mapLine(m,x1,y1,x2,y2,'#'); 178 | if (y1 > maxy) maxy = y1; 179 | if (y2 > maxy) maxy = y2; 180 | } 181 | 182 | /* More data? */ 183 | if (!sep) break; 184 | 185 | p = sep+1; /* Skip "->" */ 186 | x1 = x2; 187 | y1 = y2; 188 | count++; 189 | } 190 | } 191 | *maxyp = maxy; 192 | return m; 193 | } 194 | 195 | /* Simulate sand falling from 500,0. Return the resting position 196 | * in *rx, *ry. If the sand fall out of the world limits they 197 | * will be set to -1,-1. 198 | * 199 | * If animate is non zero, the map is printed and the screen cleared at 200 | * every step. */ 201 | void simulSand(map *m, int *rx, int *ry, int animate) { 202 | int x = 500-XOFFSET; 203 | int y = 0; 204 | 205 | struct { 206 | int dx, dy; 207 | } nextpos[3] = { 208 | {0,1}, /* Down. */ 209 | {-1,1}, /* Down left. */ 210 | {1,1} /* Down right. */ 211 | }; 212 | 213 | while(1) { 214 | int j; 215 | for (j = 0; j < 3; j++) { 216 | int nx = x + nextpos[j].dx; 217 | int ny = y + nextpos[j].dy; 218 | int cur = mapGet(m,nx,ny); 219 | if (cur == -1) { 220 | /* Out of range. */ 221 | *rx = -1; 222 | *ry = -1; 223 | return; 224 | } 225 | if (cur != 0) continue; /* Try next direction. */ 226 | x = nx; 227 | y = ny; 228 | break; 229 | } 230 | 231 | if (animate) { 232 | mapSet(m,x,y,'+'); 233 | printf("\x1b[H\x1b[2J"); 234 | printMap(m,x,y); 235 | mapSet(m,x,y,0); 236 | fflush(stdout); 237 | usleep(30000); 238 | } 239 | 240 | if (j == 3) { 241 | /* This sand can't move more. */ 242 | *rx = x; 243 | *ry = y; 244 | mapSet(m,x,y,'o'); 245 | return; 246 | } 247 | } 248 | } 249 | 250 | int main(int argc, char **argv) { 251 | FILE *fp; 252 | if (argc != 2) { 253 | fp = stdin; 254 | } else { 255 | fp = fopen(argv[1],"r"); 256 | if (!fp) { 257 | perror("Opening file"); 258 | exit(1); 259 | } 260 | } 261 | 262 | /* Read map in memory. */ 263 | int maxy; /* Used for part 2. */ 264 | map *m = readMapFromFile(fp,&maxy); 265 | if (argc == 2) fclose(fp); 266 | if (m == NULL) { 267 | printf("Out of memory reading map\n"); 268 | exit(1); 269 | } 270 | 271 | /* Part 1 */ 272 | // printMap(m,0,0); 273 | int count = 0; 274 | while(1) { 275 | int restx, resty; /* Where the sand rested. */ 276 | simulSand(m,&restx,&resty,0); 277 | if (restx == -1 && resty == -1) { 278 | printf("Puzzle 1: %d\n", count); 279 | break; 280 | } 281 | count++; 282 | } 283 | // printMap(m,0,0); 284 | 285 | /* Part 2. Draw the floor. */ 286 | mapLine(m,0,maxy+2,m->width-1,maxy+2,'_'); 287 | // printMap(m,0,0); 288 | 289 | /* Emit more sand until it rests at its origin. */ 290 | while(1) { 291 | int restx, resty; /* Where the sand rested. */ 292 | simulSand(m,&restx,&resty,1); 293 | if (restx == 500-XOFFSET && resty == 0) { 294 | printf("Puzzle 2: %d\n", count+1); 295 | break; 296 | } 297 | count++; 298 | } 299 | // printMap(m,0,0); 300 | 301 | /* Cleanup. */ 302 | freeMap(m); 303 | return 0; 304 | } 305 | -------------------------------------------------------------------------------- /day-8/input.txt: -------------------------------------------------------------------------------- 1 | 200210101302123001201232003214413304042424024222111455334421333412020113121332322101331130101222121 2 | 120100002010203210130421301201404231101254535242322112224524254031333224202413331320010302202022220 3 | 001200100200133300103241144403033124133341435524324143423341133252144040000423121430200100022211211 4 | 000012321202320024030320421230202213131514345325422513145221212451233202023402411040301113132131121 5 | 111103022312211340103042313022513413532253114352113252432213335135141552003023313142423321320321212 6 | 012112331020102411442404102132241553154421513555415233312432515445154422402444314033003303323320102 7 | 200110201230142322043222345241215442224221523534521123322555135454422121142320102300340211100120310 8 | 120012121330311223132012342543213553334431544155643463443115441515143121132442433102420433301221030 9 | 232202001121031432403445341332243414414443326545556526423425612114153351234111432130314202330220010 10 | 133033302004430221300431213144135422424546344243432363665246244341243432352514332142044434023131003 11 | 323030003440212122341123551231453352464334362343245665335563565343421512431425213111441304340011231 12 | 003000034413321402514254435224115366533425244663634336625232232553226312522142535212414040004113221 13 | 203203234020411021411532552144456644553434362455342664624546642245543563524451523133334201141411113 14 | 103032442424101341214421543433253563535422262333555222632224462463423526635422354541113034433423000 15 | 020133314440123532124351233325245665424345546323747756264656566346366665333444354252523314300303020 16 | 303102341103425544443131253325266522334544545666744335557473366256323634266213415324324341134211112 17 | 023044020203451414535535625633224445223364357435363343536455577666362444542245113553311434011140201 18 | 130031020304324235255516652533544625454347643363434554557436654343442356543323225524232341230421320 19 | 220403302205252431242554332553635575345744474647573376655365465333365246645632425211423335322131241 20 | 214400202003451322143346242334324356456753434655775663756755654555657245563342333124515412311131042 21 | 144333342021131124452334346355653767663565565443573444757577736363654665266666525633314514341134041 22 | 111433243134224443344522523636635556736633645434676475377437457745566744646666544632522235344014021 23 | 421102342525325521256266235434736567476654664744455647574564433767653357626264235361354533341223334 24 | 030103204353142134336562363447366767454375766855756788856466566674566447433523254456444314525331002 25 | 410404421315115456635435323737634573668554668666466474777667486334467637567356564452622223212300033 26 | 012140231351312622653242266664756743747655464548677545754787855754646777456542663563451151125130001 27 | 122202541435443225443523376367336378575474446665666578564485767586653557636553243543226514123433024 28 | 322341213145516625463356665437453687675788656768568586885644456856643777435654242663525154214512210 29 | 140223342343464363346556333753354858857777544686557677466886555488585473373334765233552623543312200 30 | 422403124152143243445554363655577858878487546898958587796787475657654747656366532662626445424424410 31 | 321231255223524234247766447646866656646454795565859795788557647554485844673466335434256341522445230 32 | 434145334313623446664556646655886667557495589675986998765976684664875654474437775454342445551523513 33 | 433432522546645452345446344376857768848989787655576756768988889768856644743374354326655353222112422 34 | 420512322415655344574666457745755754768778785979569655887679799664764746786677655366663463434125353 35 | 124155335466242262756735466446866676986698997576575557966855895697587767454454543472442666623435524 36 | 415345153363443642766655644464854747967899588766957797576697788779586574578644737774624632644545113 37 | 441333524323362443745375688445665755769658789797769878578585579797547585786676677364322333511241423 38 | 434241414244556353633455448684455597576765697869997689879755769799778646786856633667554436244553435 39 | 245314523664342366643466667485888767568897999988699997889967759988686546445685776346654553265354523 40 | 321432211425653366363657657447568665877957979987786779697868577888595675855456734636524456425431142 41 | 033422313632342655364345567644755898785796699996888776886796657757797857688876376354363532536232314 42 | 052242355542323647576334458576689579586968867996689878797799969587659875547656644765646363224253444 43 | 234434342653226546436658855775896968867876797997996768779677667699889796745768337366436634632245213 44 | 445222213235346735753667755676669878598898697986687998696976996987769858656476757667332332625351514 45 | 435355546442363575345376588657989988589877788898987788998987888969858697674677876744344654353312151 46 | 133553556352633665357787686775799577779997878787787897797699998878965787455885663557545355624324115 47 | 545233354544544435573376578458655587598789677877787899897869896658788766588656837747764363655341521 48 | 211555453542466735366787685658866856979676887788987997989769978968996968546685834576542622243213155 49 | 144113123264426777463777488587699869767977889987787997788887696979756858576885677473635653233543243 50 | 311313235543366635754558457576795998769778679778889889889987668888968988774448543757733325643231422 51 | 443355342254425446767468656476595865887986787897998879979969967775865587546587644777655235234324344 52 | 442443355324564334365767887885668589686866989997898887797879967668978575855866836656334552623632351 53 | 413433144665547465436464847768768777996977968777788977797977679895685768676556634643436422334442455 54 | 453142566345254453333444885587565578677688779977889999789888796877778557847675867477652535546215422 55 | 151332265265444777364585745778956687969888787989789897978868788787686655764465553577745632625231455 56 | 445223254646322766445774546689887968566967668798798897976876999668956869458456654344465452425345523 57 | 354122314463434747436654644484979696677686898978887878797976779669677694454485555635752664656513133 58 | 012232355266625635373378685656767767887668769986988989987778777769685698467858437754343553255322444 59 | 024555213224464774353435485656687879797989768686778867676969798596899575656786466333455553355345234 60 | 132432444233664544676735848585667856997869777886887797667989767578765688576686457343436442546533142 61 | 444143435624244477333448558448667577665667766788798979786987858959699677748784665774745235262414311 62 | 231541231646652273467743578658756967656599897986666898787998598868878558884847373763743436333442222 63 | 452115141256244235637554556584849575796768969699769887767797597866989785545764765437552564345131455 64 | 425244513366263336575446588857846976888767658868676696667958899568857767458773744637333452423533532 65 | 105131435443626324576435676555478786567757999689999668897789599599856875674774656477364623225123151 66 | 032315232453426453465765574644575446896598678899586759777588775565758668474745575344566425615355433 67 | 414341314426235264647543645746457657967695558965975769898785985654576867658657635475666624352134144 68 | 100323311242236242255347744575476776858879688698797878579969975874748675444573747344653555211352221 69 | 014311441544336355454575445686757688689666888758996965685596966444845578855576543546465554243154142 70 | 342254542123656656546356366778675574845697675569556687688586558646447667434456665352633422255244414 71 | 211453143353434566563465675745864885674687588998996685977676784567474566434544466522533343353114231 72 | 313022332133466332336477634667465867888785648576775865668487487544484845366535575442326624351431012 73 | 114211155121535434243656644454647447848458486648876856858767458446765544736737656643222525432544232 74 | 010122525344156263354227756636434587458665676586887787858748554686666673755577552352343354534152040 75 | 412321535231542523462334653374657358685586488785485678564864446878734675557735423665442154552342011 76 | 104424333415333444626345536643374555557465464777678466847574454875666744474766234464241242553110441 77 | 124112314331255362622446225633636335345644866876474848854678487634655646573245644334324331251444400 78 | 312000445323443215433555564337345455776744675674478888474578745344363573744242633426233313351422233 79 | 430022234512251423424326264637465355355746637447648757857473743746654776525262553642221524414041323 80 | 233102134414232412332356226435465646465443546335436365365755446655434343246552323324433143130002111 81 | 111404313153153442123666355224747746356376564475444457353545546774737575424345446353354342244313412 82 | 234334440424325351212523232526466575445565545647676363335445774536647332224524363441415351434423203 83 | 123130340344441323432464644565445455655737653455763575457374566467753266262333355253144434121341413 84 | 032133414041244541233153446223224334665566654364436733465455436362242424353334354423444542342323120 85 | 331120000421342243325115456255364522626457536537755343436545747263466663636524533235411311121411332 86 | 332230404213303353133111256254363655255434744674474754434646343454354433433515513135334442222004010 87 | 202121313223222511453512322255566444565544643556454452443454524223535655434354335552444042314134332 88 | 213300030010040331541141441242645424354334635234565662362526354224246533454523242512414430303043302 89 | 303300002321212004244535244451242654252646636554662636263664646235263231315331142352102120130122303 90 | 331101014024440131342122251123415223633335635453354263636226636262256541131443215354304023243302102 91 | 331202033431032221244232125455313233642635432336534464333635335635423524411525215033323313120333013 92 | 033030202002100313111523432311242321352266332543436322536365535415434245433251242122313014031212313 93 | 222211100333332310242343252221251543414443226355325632364262625135251521332232522230244440201332023 94 | 000203310213011213412344315255131512335223453552465335425413252322422253334440310223340313231332020 95 | 011332231323130141310431031222132533232453353124412341254122255424331153344341340113311310010033130 96 | 010021033100310312123242131122524221555411455523421253253142545515323423322444300142424333201332021 97 | 110101220202201114310003401420513324334525253112533435355244442344311112421320024234333132222021000 98 | 020011123333222200003244032430305123255531342321413242534522552125444313014002424233330331130222200 99 | 100220000312023302114114440201033304323431155212155522541415515211123243000444221343002001121202102 100 | -------------------------------------------------------------------------------- /day-3/input.txt: -------------------------------------------------------------------------------- 1 | pqgZZSZgcZJqpzBbqTbbLjBDBLhB 2 | wHptFFsHttHFLMDQDFTbbj 3 | fVfvsstwPHwNwfNGfHWRSnlpClcJzCWCzddSrddg 4 | bdgHbZJHgMHgJgJctDtVssVcpFtq 5 | rNNQqBSzTcBPTDsP 6 | GWNNrhGnNnWNzRfnRQRbhCdqHMbdmbZddbmCmd 7 | BSBDzrSwrqccDDwbfcBjsRwggClslTRWGWGMFlsF 8 | dnhVhLJtzNZdgCRlsTGWCRJG 9 | ZHZdNzptLNtPhPdnprPbbDBrSqrSQPjbqD 10 | rlSwlrGvwTTSwSggCJGQJdhVgJGQ 11 | jcrHrMWfNHNzQgVH 12 | WbfjmBMrBrrmLtqMbwwsPTvPpwvBPFPsws 13 | NRNcHzbzbMRcNPjPrrlBPlbtBl 14 | CZwVCCpWggqprwtlHlssHtPr 15 | WpmLghCVCqCnmVTLnccRQvvQQHDhNQzzzc 16 | NvGTmNGDJsrCmCWPHpCP 17 | nqfVfnFQnZQfFqzMZBPtppcBPPCBptcrbF 18 | fhRSSVfqMZZhMnQfjVzShNNlLvldsNDdvvljGpllDT 19 | JGRNWRGJbGmCGRbLmGpqShhcQpQgCcncScSQ 20 | FFdtjvvpvVFnQhhnQhgf 21 | ltvjjtjHlzBtWRmNPLZRHLpH 22 | FFCJFsvgLsjLgWzJFWJgGwBDbwnbwlDddqffnjnlnd 23 | pTpTMQpMZHQhZQpHPZMmTMlwhDNNddbnDqdDwwlbVNVd 24 | SHpmrHPZHQpmvFrqsFvgCsRq 25 | TtWpWhQlVZrVptJhtrtdbLPDPbjFbCCWCvFFbLSN 26 | zMGlnlsgSSvjjGSF 27 | msznlgcwMnRwznmBqTZQJrddhfQJtBJtZQ 28 | mwTwLftmqqSHWfCfLHjWftBthNNNVrlcFRVNrNrRTrMgrRNg 29 | pvJPJQPGPPzbpVpVlMBVchFl 30 | bzQPQbQQdsDZPDGJnBGnPGnjHDttqqqqmCjftLCmWmfftC 31 | ZNpfdHcccTfdwfMFNjBttMgMbBnvlvjBmB 32 | QVPsGzhbszRLRrgvtgjWgljlRtgt 33 | VJrVLsSrzLzGPChVGzbrrfpTSHFfDDHSdpZFfHpDTZ 34 | NPpvDbmbsmdbNvQvDdWQpmWSnnQCLBnCcQSCnnLlwCBlZz 35 | jggrtGTFhtGfjhDVjrjgMftFwnZcwwBCnzzVwBBwSZcVwLSw 36 | JfHftHhgftgFJWPdPDWRPDvPJv 37 | ZSLLZJGglDSVNDGGGgGgngGmHrfLzmHvvjfjwLhHvLfHHr 38 | QqFWszFMTQFdFPMqBmWBHvfhCwCjhHff 39 | pTsdppTMPtqqdbnlNVzJVbSSnbZR 40 | gBqDccrrJDwmpTWHHTdWMPWWZFHF 41 | RNfnfSwRjlLSWjQMHWvQZtvH 42 | GRLbnzNnzVRLCqhwzwBmJrmc 43 | CcGnZGnGlRncsspmFmmcmGRJJzCDTzjLBSDfqjwDDzDLDB 44 | hHrNdPWhrbPdhPgVWvvrgWdfwjfNzSqfqjLqzfBTzJzJTz 45 | HHQhhvMWbbdRswmlsmwsQc 46 | rrwhpZPrccRpQdcFDJNqhtqtqMLhqfMh 47 | lTtTllgbzTlJsmDMvbLbsf 48 | VVWBTgzlzgGnngrtQRQRtCtwZRQB 49 | HGnGvVdLhlFcmvPWmT 50 | jwBLqZgjrtjqmFsQTscPQs 51 | ZBNZtwLwztLpMrfZBLMdbdnfSRVVfnGbnfDVGh 52 | LmBBBzQrBgBhmmggmtdVdhJNMHNdhsHNDd 53 | ScSZbRplCcMnSpvCfCCZcpPwtJPNtHPHNVVNtPddwlNH 54 | CpvpZGfnffSpnvRSSbcfScQBWrMWmjrmFFBzTGQWjMmL 55 | sljSjSgsjcCLllsjVgSjCtspQwvNNhdFwFQvwpbtmhwhpN 56 | hDqqWzGRHHfRrJnrWrfWfHBdFmBFmBbdBGBpwmFdFpww 57 | TDnDHZrWWHhTjPClClSP 58 | wGNQGQDGjqqmwHHs 59 | MWvvrzgfsdWsvMrSdqJqcpgHgnqLFLnjpH 60 | fvsPMsPdrTZhChNDhbhPVN 61 | sbMgDDtttVvpMtcJsgcGGBBfGLBSLclQTGPS 62 | CWHWzhhRRHjqRmSGPfBSzJfSBnBB 63 | HjjRHWFWhRRwHNmCCRHhhFdNDNrdptMstJvsbMDtVptd 64 | RnSwRsLsnSswjDDDBJPrJv 65 | cpzCzlczHTJVQhvBQlDVDj 66 | WmGzqTmHSsffqqnJ 67 | vQSPHMwpmpQMLGfTPVLRPRVP 68 | hsWhnncsJqbGjGfcfBMMRR 69 | sqdNWqqghbsJslgsJqgWllMWDppSvNCHQHDSSHrHrHCSvvCQ 70 | ZWWnWMmmndQZmffcdZcmssQqrsptVwwTtQHTCTHH 71 | SvvrPzvvFDzGzTszpGGwHT 72 | vrRLjjrPhLjrjPDSfdcMZnmdcmJcfcRf 73 | HpqWhDJjzmcTSbmMBVBb 74 | nCzfLtFnZZrcbcVVfTBfsc 75 | FtRFzgrRtnRzrFwzDjljpjgHNJDlNlhN 76 | gtNRRSSrRmjshHmm 77 | PQDMwPwMppcQQcvCFlhLhGmjflctlnHGjf 78 | QwDMFFdtwFDQJZZZNqSqJSqBgBqTNJNg 79 | cddzbbzQflTDcDfRbcfbJVsplVsChNghHNsSsVpn 80 | FBWFWjFFCjWPBSPPJsVpppPSVH 81 | CrCwvjWvmqmvrBvFwZRGQQDDcGTcfbddZdRc 82 | ZBQqdGLFmmzDmTZz 83 | PvrVMvGgWmwSmllglS 84 | NrfGnvWWPhfpspsGvLJBsFBbqJCbdQcLBq 85 | DrwTrlfGThhQTpDdWSWgdgwLLgBSZH 86 | bqbPRVRmzJCLWSgCzCLH 87 | jRtbNVtNjNqRqsJtbjbMDQHQGlchfQpfsTcHpGHr 88 | tMnRcnpDcZtpQDSCCsGGHvcGPGqGsr 89 | mzJmjWJNlbfmbhzVCCPmZrCZqPGCgZ 90 | JWhzjJBdWnMLZtSBTw 91 | tvdLttzvtHLztnQpssdTPbMqbqMTdTss 92 | jhSRGNjjSjhSDCNhRgRgclNjmfZTPnbTMqJJfqqsbMflTfMs 93 | WnCjcjDRCChSNSCNDjNhGVDtQvVLHzFrpFwFrHFQQwQpzp 94 | fLbLLLLQhVPhBVmDwmCfwsdwwDps 95 | GNtctFTSrrJqGGpHFcTJFTwsslwmlmWsdsqRRCmqwdWs 96 | ppctFTTSgHcSrGrrTGFcrrnhhQbPLbQZgzLvQQVVvZvLhv 97 | mBBWnnBbBCtssmRThRDllR 98 | wfwFQcpHFpddFrwpGcHSHdcjQZZlqqDTTjZqssRhWllssj 99 | dWfrcSGFpgrSzFgMbCPNPLtCtVMV 100 | llLlGLJJMjJMGVSvVMSLRRHvjCZtgZccttnmbCtdCcmCCztn 101 | sBQNqPhsrrqrrwrsppsHswsZcmnNCzdZtbgntcNgcctnCt 102 | WWFBBsPwpWPwBBHpFFrWGRMRLlJfJVMJRJLWSJ 103 | vgMvQnPMntnSQPSgMvSMpNJfJDNNRpfZmGQmbDND 104 | HlbjHHBLjCHGZGpfJLpfwm 105 | qdHWqBbbbjrTzdqFqssvtPMSSFFg 106 | TGDfDHSgtTzPPbnCtnNtVn 107 | WQrWMFpMWMQbCVNPRWVWWv 108 | pdpMMrhrprQshlMFjZpdjZMgmlGJJGlGDBmgmHgmJCSBHG 109 | zWWBjZZjWPFFPPnBCVdsqmnCdSLn 110 | rJvpbvbpGgTGrNJGGpRRhsCqSsLhnsmTVnSLTLHh 111 | gNNNJDbpvGNfvNSDPPWQWWPZZWtjlQfc 112 | RRVbWWWvvZVWmsFSsDNbHsDSsg 113 | CrTwJQJpJpCCwvlJQTTPsfzDgfwNhszfszFhzFDh 114 | ttQJtvjpPvcqTllJTPtPRGMGRGLWdVZLVZjWdMjj 115 | NnPCTQWMMQNNNWwWnMzpHczzsZcCscddHdGs 116 | mqRgqqVlLgqmfVzcGpzzSHGZcgcz 117 | tjmZjZmhqftlJRJhlTMPTPQbrPBBWnhnnT 118 | hvTQqpvTqjvhpjnCqmCnSDSFDWFFLSSSWDnSVL 119 | tZwGgsfPcltgcZltRgNSDSSSSldmWMLWFVHd 120 | GrZtwRPbGwwPcGRsZGtRtgQJJhCjpzmTBTvJzJrjvzQp 121 | rwmwqDWwfDtztnFGBB 122 | LPdpdVcdPGvPVgZsPtlhTTtthHBhHF 123 | dRdCjvpCRpjvCMZgvLgRVJJSWMqmbwQJbMWGWQNbbQ 124 | CMCcMcDGzBGPmBmznTNbnGbrswNTwTvN 125 | SSHVWZphqWWJJzNsbnFwFVNjbz 126 | flLQqHzzgtQdcDRB 127 | mdzvFtllBgFttGnvfMwMVRRZCThSNZVhMd 128 | pDTrDHjWWJPqjDjDSMqNwSZRZhNSRNCZ 129 | jpcTpQPWLLpDTLcTrPjPDcjzzFLFzvgLzlzfvGFgfmgFzF 130 | fQVVPzBpFVVrtrsJ 131 | PldSLNSmWwMCcCMMcCNN 132 | mSPlldllmPdRnLRwmbnLwmwvTjBTghTHQjfgjpZHpfHHfZbZ 133 | pmfMcfprMqMrZZJcMZMGWTsFCVCTVPPsVTWCGPDP 134 | vrvvvLRbBNNBbvBbjBHbQhgDslPTWsPTlFDsFTFwTWlDVQ 135 | hgjznNBjHHgrhRHgrRLRnRfSSJmdqMfffzqJptdmmmdd 136 | nRnPlCRPWPMFqwPLwq 137 | tBGfbSbHtBVQgrbrqfTFFLvTNLLNGTGMLdws 138 | bgHVtBDtqnqqlJRD 139 | SdSJrHssFBSVsNtMMdRWnTRhRl 140 | vcvfDvgvcwvFRlbnwWRlMhtn 141 | DDDqcqFZQPgcgcfvDjLDfVrsSVrHBLJVpLpCSppGpS 142 | gJGTFLTdrpLdBcWBvnllvlMvMC 143 | RRqbbQhwNZZwQRPrSZWnvHSZWSvSZC 144 | fQDNRsrsQzfbDrbsqwdtpgJVjdJdpVfJFLFF 145 | DzWqFvqpqFSCSzGRGmwfntGjmR 146 | cbhZNJQBtgMHJbJcNcrmfhrRrswmfRwnVrhG 147 | bJNgbNdJBBPMHbcMNMWWvSFpDLFvCStqpLdv 148 | sLsHTsTbRLRwqssHwHjFrPDwJDppzFDJmmcrPJ 149 | BnZGBlMZnQSgSnvVSMmJzPDCzFcrLPPJmpDG 150 | BgBffVLhQLgvnBRRssfqdfHbHdNT 151 | HRPVmjqBqVjVRRPmcPmJjbDgLDDshbfRLlfbfLbhlL 152 | rtTzSMSMFpTzfgDzzgsLfLHZ 153 | rNpGpSSHwMTrrdHGNtTPmVjnGGjVjmBGmmBjJB 154 | DBqDQDQHSFlHsFnN 155 | MfLfwwLMWGLrWMMnpSlsnGJJlbFVjV 156 | gRhMZzhrFLWQvTPqTPcvvh 157 | NwwsHwtnFCtzcPdbvrQbBqclQq 158 | VmZLLTLfVpwMBrVVqqMM 159 | mgJDjTgWgLWDppJZJTWZmSRzCtRHhGGwHNzshGFFCSRt 160 | RGCCDRdFZdRCMzzGCDGCmGHMfqbNNNLQLfFqnnqnNQqVPnQn 161 | glgcrwrJjJccBwdSfnSnVqrqQVVnNq 162 | jvtBsjstgstjltBcWzTGGddHTWDTZCmDGm 163 | HJHGZZHnctSSDhZtmZ 164 | MjjQFSvQlRjSdRqdqvVSqCCPtpRpPPDfDmfPbbpphC 165 | SNsWqMNvFFqdqVMgwwBHrGHnHgcWTJ 166 | jBcbjSmSBbbCcPcMjmbzFPhDMDfrfGRhGQRMnGQfdrDh 167 | wHlqwlqpwZqcwVlqHtJVJLTdhndTDnhffftTGDTTDdTG 168 | JNllcwpZZlpZJjNzSzSCNjSmFN 169 | FhwRPzmPWmQQmwFPGGMGGRPnRHHVfDbvJlvDlHSvDTDfVHbD 170 | NpjcpCdqpZZvwvJVfDdDHT 171 | twZtqrBrBQBMBPGn 172 | fBFGjbLLFblmbWFmVfBvrvMdMdncnrdNbdQNTr 173 | shZHHRZhtsqJZhHhgZzgJzVJrrSSvrMdMQrNTvMNJQNrdn 174 | szHwgtHtwPzPLpVFpVPLlfLC 175 | mrsrtrWjljjjvwwgNnZfDHJDqTqrHL 176 | FccMPFQcpczpdMPhMqJngNfqfnFgDnnFfg 177 | BdMpdcDPcpjBmlBmVWts 178 | VvwTTlfVlblwwSsbfTdzVqjhzVjpjjqjqpzV 179 | rwCWFGmJrNCmMRHmwRFPmHQQhBLBzdLqBjhLBHZdQB 180 | rFwDrMNRJDJFPRmCvcTcbDsvstTgfTsg 181 | zhRzdRRChHCFGPDRvWRWvWvHpZpscrrmrZrJcmspJmJZFfpM 182 | wQqLtQLtnjbjVnVjbBgjbBnbMZMZJlVpZfJprsMprmGZZZml 183 | jQjjNBLLwjtQBtwwdGGDCHhNzzWDzTPD 184 | DzzQnCMMznFnCdnFFlHtlmhVRtmVVmVhSF 185 | PWrPPRTfLJJtfbtBfV 186 | wsrggZsTwTTWGvDppQMRjjMCjMZp 187 | fTjzZVTlbffCMvjgMpSFWBNBWSFsvBsNNccF 188 | nJdwdPRQqGqbGJQbmmQQhRSBBBSsPPHWNSWFBtDNBsHH 189 | nnQhwwQGdLqqwnZbpfjMfzpzLbLj 190 | jgTgCwgjMgGLhvRrHrHwhvhV 191 | bqSsSsZFZBlFsBlTSppVvVvnVHHvHnhp 192 | qFlbPbFFsWFsBlFWbsbsmzTcMjLmtfcCmcWtgzgm 193 | rrHbfBLbfMcghcmrcCzg 194 | RDStDtvdZRQdJSQWWWdvFSgNvVcnghhmnnzhVPhczPch 195 | ZtJpJttSZStwtttFDQmLGTlqMLqGfwTTGLfTGG 196 | MrfLWwfBwgghvLmNvmHHHGGQHQSSscscVvTV 197 | dDjZjDPJtFRzjdTTsqVjTpqHsGrT 198 | JbFtlbPRJCzffBrgnlMWmg 199 | ZFsbbVLLdZppLFpcJjCCQJlGcQCMZq 200 | TwRtRBdBClCTGlcJ 201 | rwBvBzDvwNNDHLHzfHssdHhS 202 | gdhgftTNGTbpqJqjjgRJ 203 | lcBcMLFzMzLFMzFzPjRBQjQPQpSqhpbp 204 | mzzmZHZZnZwLhtGfddVsNCCnGG 205 | lblbPGSGrTLRwqZLvP 206 | FffCCFzFCWzzvmjRJnRTnZZNJCTqCR 207 | gdhztVjhHMsGvrGVVB 208 | ZJZjJGHZhDJRFJHjDZjhPNFgFmrnVmgVVzVBscnzSg 209 | bwlWtMwtbqdCvlQCplmsqgnVVScnVgmnmzNs 210 | WMWltTtvvCdwCCRPPfTHGcJDfGZL 211 | svqQJLvSSZrZZZCFCBDPDCMTDpPwMWDPCwRw 212 | GnlnGbdldjhzzhpPDTWjmtMwPmWW 213 | HzVbGnnbchblbnbzcQTZBZrQrFSHvLBBJv 214 | MmgMmVpcRDlvbvpHJF 215 | GSGTLTwhwwhzQqTqwjFlbdvdbrlrbrrDnDvHlQ 216 | zLNNNtwGFCMsWsCWNR 217 | tSTDDDftSqSsTDnTtCWNrbFsNJJvbzJbvJ 218 | dhRdVHdMGRgPJbjNPbzgvr 219 | VllQmQdhRHLhhHmLlGzSqSQDDcDBnnBnqDfSct 220 | zBzJWZBLZNNGLsbTvLbmbT 221 | QdtQwfdnPdPTbsRQGhRvbl 222 | pgtPgPjVDnpVnDtPTFFrJJTBCcpcrpCW 223 | GnWMfBfdCGMbjRNpnzvvNLRNVv 224 | FShJDJJscwwszNjvNjNNqZ 225 | tJmccwlcFlFcHlPcHFfdrbBGBGfjCGTfBCPf 226 | GhlcQsZNQZWhpcGhwlPmqnnqnjJjLRnqzJsJLJ 227 | VTMtTtDTbvbMTfvdJqngjmqzdjmJjCLm 228 | vHtbHTDBFvffBPGwLLZBQNNl 229 | bDphJrpbpnBbDrdBvJdDFBMtMlfgtsFSstfGPPgggPGP 230 | RZmNjTZQNVHQHNGSgMsfPlShSs 231 | VmchTLZQLjVLjmTVmQVhTmwVrWJqbDqddBrpnWbvnqrqcnJB 232 | jWWgThWtgSvSSWlJtlShllPcHVnJHPbMHPcPVPbVZrHM 233 | fGdfRsRdNwfRQhnpcZdVhVpbPh 234 | fGhwNBqNjqStFqtj 235 | TSTBrSDlQlTDrrQclrBSLffPvcfcdVjVMGGPLjLL 236 | qnbnbngFGhhhPfjjVffjff 237 | RRWbmgpnmqlrCwwSrwmG 238 | mZZTsdBZVZBZLVHdFmsNnCrCVQQbWvWjWNCnbg 239 | QSffDGwGGrPGWrgN 240 | hflwzltflDpMpDSllcMDhSShdsdZQdLZZdHTssZzmqLzFmLB 241 | LLRJRshLfsJfWnLBTlTBlFzNrnrBBl 242 | qmmVwmdHqmqGHZdHbbqSScdZQTjjpTFFVBBrlDrzDFBTjFjF 243 | wZZwmcbvHgqTmGccmvdCLhCPJsJCPWgMLPtJsJ 244 | TWbbbNbJJjJbqTjtJJjTQCtnGSBndMGCcSZSQwCB 245 | mcfRfrcmrDRrPsdQSGZQGnsSQMnB 246 | DDRLDRDFPpgmpcgPghpfgvRTjbhTVjHljJjzlVzVTlbHll 247 | rPlPrPllBGgJgdJfHgfjJt 248 | pppZVfFDWssMfFVVFMpsMMVmHCRLdcZCRtvLRdCtCJdHRttH 249 | mDMfDFDmnMMmsMFznDFpzswbNbPGwwSGBrGrhrTzThSl 250 | qDNFfCCNWLfWWhqhDGPMMZVwgpCpMbJwJCvV 251 | RdstRRvdtmtPVpppVbVtrp 252 | zzncSRdsTdQTczQBsLvvHNhDWGjDHNLDSG 253 | bNNpcfJcCtNpHFsJsGGjLGzmLjLmGzlFGW 254 | qwqZdnQnQwnhhzmnMWjmNlMzLr 255 | qhwwQSwStJbHNftS 256 | WlfWSwDftzRltBWVlRDlsmBJPcsZPmcJnmPmFhrn 257 | dLQbQbvGTddTvbjQCbLbhmCrZZPPsshPPPrJZrnF 258 | QgFjQHHbMvdRMVllSqfSlf 259 | MDPJBWWPggVlPVDMSljdZNNpwjwbHZpNbDdH 260 | mGmzcThGrtntHhthzGctRbNRNwRNzZwfdZpjpdRj 261 | ThtcvvtThFcnqFQSHgBSVJll 262 | hVqhFLBngHVFtJjtLCBJVSbbPNNbSmfLLTSNSrrLTb 263 | vsdZZpvQdczlMdMvzlcvvdQprbGGTfSbWmzPTgmmGTbmmfGP 264 | vgRZZMgwdgsQZdMBqVhjhJqBhJtRhq 265 | bgFQbMMbTbQhghddFTFGnmSmsNdzHvzSSzlcHsls 266 | fZDjVtfZLqwpqtCfCjCjlvqScrvzqHSzszzSnczr 267 | jpftjCfWCjCfCRZZlpCpjRWQBRTQQbgBBTMbghgbbPGJBJ 268 | VZZrbBVwbbbVVvgbntnggNRJqRRNNccMcNqJcJ 269 | jfDPfDdGGhDGfGFPCcZQqMpRNJhqTcMc 270 | LPfffPHGPDjPFGWSdHPFjWtlBlwvlwBlbtmLltsmvtZb 271 | TTfJDfrJTSrHMcVMJDTfMcMDBQBPwnPlznPszFVBFgzFgnsn 272 | CqtmWNNGBPzwbbwm 273 | htdCthhWGtWWGNZqcZpJjwwHHHMcHZDM 274 | VvjQjQCZLbbSbTPpSHtFzsHzppMfzz 275 | DJrJWBcDcWJWmmcgGRGRGWGDzHHwzdfRHpMztMpfdFdFdzdM 276 | DmBgGDqJNhGcccWmcZLjTPLVLTQhPtvvTZ 277 | qfhvwNDQqwDGdGZZGwPTTw 278 | STsJgsRtJMZPjlsmdpbs 279 | SCTTHTWHNVfHQqqq 280 | djCDgllgjJjDRRNgRlDdBgtpQHfhQTrLLrGBtzrQhpBH 281 | SVcsMGcPSbqSPmLTPHHQTHrftPTr 282 | VcWnsScqSScWcZbMMcSVGbNNlgDRlgCCNgwWvvRJdNdj 283 | mgPllfRgvNmPGQGGsmQNWlpFtnBPFShncTFShtFShnjS 284 | tLLzMJJwwbbdrrMLqLVJMzVZFnpTTFpnCSSpShCjBJhpThph 285 | HMdVwbbLMbDMDVlmDsgtNtNRfgsm 286 | hNsgsgzNZRghPhZBdssPQfzDmQSmmzQGJWzfCDJJ 287 | bblVHvvHHTljwFCfGrvmfmmJBmGQ 288 | THMMFVwqTPRdZptMBP 289 | QvcPGSvQLjmcQWSGWWGjLCNhhqpCdBCNCbJNdVWpCh 290 | rwtLlzZggLHnHlwHRDdVqBbCdqqVVhbqVnVh 291 | zRDzwRrwlRlRTgrDtllmQGLcPjGLccFmTcGSQc 292 | RWlgQlbcWBwzsJggTfhh 293 | GrnLjHLjmLjjGSLjSDmfJJpfThhfSWJPqJqhwz 294 | vLvDDnDNrCVjCmNDbFlBVZdVRQlRbWcb 295 | mTlwFngwmlLlvsmLHmHsLJhJFfcbdpbNcjCNCbpccb 296 | tZRzBRzBBRQzPqGRqrVQtjjfbCMcfMfCMMjVjfCJNd 297 | SDBBPtZZTdnnwSvg 298 | nddNNMMPNBnBNnBTQSShlSHghlDHBr 299 | VcccVmqJsJsjlTmzTDggmHHT 300 | VqLtFCqFJfVtVjsNgPNNMMWNwgtNvn 301 | -------------------------------------------------------------------------------- /day-5/input.txt: -------------------------------------------------------------------------------- 1 | [J] [F] [M] 2 | [Z] [F] [G] [Q] [F] 3 | [G] [P] [H] [Z] [S] [Q] 4 | [V] [W] [Z] [P] [D] [G] [P] 5 | [T] [D] [S] [Z] [N] [W] [B] [N] 6 | [D] [M] [R] [J] [J] [P] [V] [P] [J] 7 | [B] [R] [C] [T] [C] [V] [C] [B] [P] 8 | [N] [S] [V] [R] [T] [N] [G] [Z] [W] 9 | 1 2 3 4 5 6 7 8 9 10 | 11 | move 2 from 4 to 6 12 | move 1 from 9 to 5 13 | move 3 from 2 to 4 14 | move 8 from 4 to 7 15 | move 2 from 9 to 7 16 | move 3 from 8 to 3 17 | move 2 from 1 to 2 18 | move 5 from 7 to 9 19 | move 1 from 9 to 4 20 | move 1 from 8 to 3 21 | move 1 from 3 to 4 22 | move 2 from 4 to 9 23 | move 7 from 3 to 5 24 | move 6 from 1 to 8 25 | move 11 from 7 to 9 26 | move 12 from 5 to 3 27 | move 6 from 6 to 9 28 | move 3 from 3 to 8 29 | move 4 from 2 to 7 30 | move 3 from 5 to 7 31 | move 1 from 5 to 7 32 | move 2 from 2 to 5 33 | move 1 from 5 to 2 34 | move 5 from 8 to 9 35 | move 7 from 7 to 2 36 | move 3 from 8 to 7 37 | move 1 from 8 to 9 38 | move 4 from 3 to 6 39 | move 1 from 5 to 1 40 | move 9 from 9 to 6 41 | move 7 from 9 to 6 42 | move 20 from 6 to 5 43 | move 12 from 9 to 8 44 | move 5 from 5 to 1 45 | move 3 from 7 to 4 46 | move 6 from 2 to 7 47 | move 2 from 3 to 1 48 | move 4 from 3 to 8 49 | move 1 from 4 to 1 50 | move 7 from 7 to 5 51 | move 4 from 8 to 2 52 | move 3 from 6 to 2 53 | move 3 from 2 to 9 54 | move 4 from 1 to 7 55 | move 2 from 1 to 2 56 | move 3 from 9 to 5 57 | move 11 from 8 to 5 58 | move 1 from 6 to 9 59 | move 1 from 8 to 5 60 | move 1 from 1 to 2 61 | move 24 from 5 to 4 62 | move 2 from 1 to 6 63 | move 11 from 5 to 4 64 | move 2 from 7 to 9 65 | move 1 from 6 to 2 66 | move 4 from 2 to 1 67 | move 28 from 4 to 2 68 | move 1 from 7 to 8 69 | move 9 from 2 to 5 70 | move 2 from 9 to 6 71 | move 4 from 4 to 2 72 | move 1 from 7 to 4 73 | move 3 from 4 to 7 74 | move 1 from 6 to 9 75 | move 21 from 2 to 3 76 | move 3 from 1 to 6 77 | move 5 from 6 to 2 78 | move 7 from 2 to 3 79 | move 1 from 9 to 3 80 | move 1 from 8 to 4 81 | move 1 from 7 to 8 82 | move 3 from 5 to 8 83 | move 1 from 1 to 7 84 | move 2 from 7 to 9 85 | move 2 from 8 to 4 86 | move 1 from 9 to 2 87 | move 1 from 8 to 6 88 | move 11 from 3 to 4 89 | move 1 from 7 to 8 90 | move 6 from 5 to 9 91 | move 2 from 8 to 7 92 | move 1 from 6 to 5 93 | move 7 from 3 to 8 94 | move 9 from 3 to 6 95 | move 1 from 8 to 3 96 | move 1 from 7 to 4 97 | move 2 from 3 to 5 98 | move 4 from 5 to 7 99 | move 4 from 6 to 8 100 | move 2 from 7 to 9 101 | move 11 from 4 to 2 102 | move 1 from 4 to 2 103 | move 6 from 8 to 9 104 | move 1 from 7 to 1 105 | move 1 from 3 to 7 106 | move 3 from 7 to 8 107 | move 6 from 8 to 9 108 | move 6 from 4 to 8 109 | move 18 from 9 to 3 110 | move 1 from 5 to 8 111 | move 5 from 6 to 5 112 | move 6 from 8 to 1 113 | move 3 from 5 to 4 114 | move 1 from 9 to 8 115 | move 3 from 4 to 8 116 | move 15 from 3 to 6 117 | move 2 from 5 to 9 118 | move 3 from 3 to 1 119 | move 9 from 6 to 4 120 | move 2 from 1 to 5 121 | move 2 from 5 to 8 122 | move 6 from 4 to 2 123 | move 6 from 1 to 6 124 | move 3 from 4 to 6 125 | move 6 from 9 to 1 126 | move 4 from 2 to 1 127 | move 7 from 8 to 1 128 | move 1 from 6 to 7 129 | move 17 from 1 to 5 130 | move 1 from 7 to 1 131 | move 5 from 2 to 1 132 | move 1 from 8 to 6 133 | move 11 from 6 to 4 134 | move 2 from 2 to 3 135 | move 3 from 1 to 8 136 | move 7 from 2 to 5 137 | move 4 from 6 to 7 138 | move 4 from 1 to 5 139 | move 15 from 5 to 9 140 | move 2 from 3 to 7 141 | move 2 from 8 to 2 142 | move 1 from 1 to 9 143 | move 6 from 2 to 6 144 | move 7 from 5 to 6 145 | move 5 from 7 to 3 146 | move 1 from 6 to 1 147 | move 2 from 3 to 4 148 | move 1 from 3 to 4 149 | move 5 from 6 to 4 150 | move 14 from 9 to 2 151 | move 1 from 8 to 9 152 | move 1 from 7 to 8 153 | move 1 from 9 to 6 154 | move 2 from 9 to 5 155 | move 1 from 1 to 2 156 | move 7 from 6 to 9 157 | move 1 from 3 to 4 158 | move 8 from 5 to 2 159 | move 1 from 6 to 7 160 | move 1 from 7 to 4 161 | move 1 from 8 to 4 162 | move 1 from 3 to 9 163 | move 7 from 9 to 5 164 | move 1 from 9 to 1 165 | move 6 from 5 to 1 166 | move 8 from 2 to 4 167 | move 1 from 5 to 6 168 | move 1 from 6 to 7 169 | move 1 from 7 to 9 170 | move 7 from 2 to 9 171 | move 1 from 9 to 4 172 | move 3 from 9 to 1 173 | move 1 from 9 to 6 174 | move 11 from 2 to 8 175 | move 9 from 1 to 8 176 | move 1 from 6 to 4 177 | move 1 from 1 to 9 178 | move 12 from 4 to 2 179 | move 4 from 9 to 3 180 | move 3 from 4 to 6 181 | move 9 from 8 to 6 182 | move 12 from 4 to 9 183 | move 8 from 6 to 3 184 | move 8 from 2 to 7 185 | move 11 from 3 to 4 186 | move 2 from 2 to 7 187 | move 2 from 6 to 1 188 | move 1 from 2 to 3 189 | move 2 from 6 to 2 190 | move 3 from 2 to 6 191 | move 2 from 1 to 6 192 | move 1 from 6 to 1 193 | move 1 from 6 to 4 194 | move 2 from 6 to 3 195 | move 1 from 6 to 5 196 | move 4 from 3 to 8 197 | move 12 from 4 to 5 198 | move 5 from 9 to 7 199 | move 3 from 8 to 7 200 | move 1 from 9 to 1 201 | move 3 from 8 to 2 202 | move 13 from 5 to 6 203 | move 1 from 2 to 9 204 | move 13 from 6 to 7 205 | move 7 from 9 to 6 206 | move 2 from 4 to 6 207 | move 1 from 8 to 6 208 | move 1 from 1 to 6 209 | move 1 from 2 to 9 210 | move 1 from 2 to 3 211 | move 12 from 7 to 9 212 | move 7 from 8 to 4 213 | move 1 from 1 to 3 214 | move 2 from 7 to 9 215 | move 15 from 7 to 4 216 | move 8 from 6 to 3 217 | move 1 from 8 to 9 218 | move 1 from 7 to 2 219 | move 10 from 3 to 5 220 | move 6 from 5 to 9 221 | move 1 from 2 to 8 222 | move 1 from 5 to 8 223 | move 2 from 8 to 9 224 | move 10 from 4 to 9 225 | move 20 from 9 to 6 226 | move 1 from 7 to 6 227 | move 4 from 9 to 3 228 | move 1 from 5 to 9 229 | move 4 from 4 to 9 230 | move 8 from 9 to 7 231 | move 2 from 5 to 1 232 | move 7 from 4 to 3 233 | move 8 from 3 to 2 234 | move 6 from 9 to 8 235 | move 1 from 3 to 7 236 | move 1 from 3 to 1 237 | move 7 from 7 to 8 238 | move 13 from 8 to 3 239 | move 2 from 2 to 8 240 | move 1 from 8 to 2 241 | move 1 from 4 to 1 242 | move 1 from 1 to 8 243 | move 2 from 8 to 2 244 | move 24 from 6 to 2 245 | move 2 from 7 to 8 246 | move 5 from 3 to 4 247 | move 25 from 2 to 6 248 | move 5 from 4 to 9 249 | move 2 from 8 to 7 250 | move 2 from 7 to 3 251 | move 4 from 6 to 2 252 | move 2 from 6 to 4 253 | move 9 from 2 to 3 254 | move 11 from 3 to 7 255 | move 10 from 7 to 8 256 | move 1 from 7 to 9 257 | move 3 from 2 to 4 258 | move 8 from 8 to 2 259 | move 1 from 2 to 6 260 | move 2 from 4 to 1 261 | move 1 from 8 to 2 262 | move 1 from 6 to 9 263 | move 1 from 8 to 3 264 | move 6 from 9 to 7 265 | move 2 from 9 to 1 266 | move 9 from 6 to 8 267 | move 7 from 2 to 3 268 | move 7 from 8 to 2 269 | move 10 from 6 to 8 270 | move 7 from 1 to 2 271 | move 9 from 3 to 2 272 | move 5 from 3 to 8 273 | move 4 from 7 to 2 274 | move 2 from 3 to 2 275 | move 12 from 2 to 3 276 | move 6 from 4 to 2 277 | move 1 from 7 to 6 278 | move 5 from 3 to 5 279 | move 16 from 8 to 4 280 | move 12 from 2 to 7 281 | move 5 from 5 to 7 282 | move 1 from 8 to 3 283 | move 1 from 6 to 4 284 | move 17 from 7 to 4 285 | move 1 from 7 to 1 286 | move 1 from 1 to 9 287 | move 1 from 9 to 5 288 | move 11 from 4 to 9 289 | move 10 from 2 to 3 290 | move 1 from 5 to 4 291 | move 1 from 9 to 2 292 | move 2 from 2 to 1 293 | move 1 from 2 to 3 294 | move 23 from 4 to 5 295 | move 7 from 9 to 7 296 | move 3 from 9 to 1 297 | move 20 from 5 to 6 298 | move 3 from 5 to 8 299 | move 1 from 4 to 1 300 | move 2 from 8 to 3 301 | move 4 from 6 to 4 302 | move 7 from 7 to 2 303 | move 1 from 8 to 4 304 | move 19 from 3 to 9 305 | move 5 from 1 to 7 306 | move 7 from 2 to 6 307 | move 3 from 7 to 5 308 | move 2 from 3 to 4 309 | move 1 from 5 to 4 310 | move 1 from 1 to 4 311 | move 1 from 7 to 6 312 | move 13 from 6 to 7 313 | move 6 from 9 to 3 314 | move 1 from 3 to 5 315 | move 2 from 3 to 4 316 | move 2 from 6 to 2 317 | move 3 from 4 to 3 318 | move 8 from 9 to 1 319 | move 2 from 2 to 1 320 | move 8 from 6 to 7 321 | move 2 from 9 to 4 322 | move 20 from 7 to 1 323 | move 2 from 7 to 5 324 | move 2 from 5 to 1 325 | move 8 from 1 to 8 326 | move 8 from 8 to 6 327 | move 1 from 6 to 9 328 | move 8 from 6 to 1 329 | move 1 from 5 to 3 330 | move 7 from 3 to 2 331 | move 1 from 5 to 2 332 | move 2 from 9 to 7 333 | move 1 from 5 to 8 334 | move 18 from 1 to 4 335 | move 1 from 8 to 9 336 | move 3 from 2 to 3 337 | move 2 from 7 to 4 338 | move 5 from 2 to 4 339 | move 3 from 3 to 8 340 | move 8 from 1 to 7 341 | move 2 from 9 to 2 342 | move 32 from 4 to 5 343 | move 1 from 9 to 7 344 | move 1 from 2 to 1 345 | move 6 from 1 to 6 346 | move 1 from 2 to 4 347 | move 3 from 8 to 1 348 | move 3 from 6 to 5 349 | move 1 from 3 to 6 350 | move 2 from 1 to 9 351 | move 4 from 4 to 7 352 | move 31 from 5 to 4 353 | move 4 from 5 to 6 354 | move 1 from 6 to 1 355 | move 7 from 6 to 5 356 | move 1 from 9 to 4 357 | move 19 from 4 to 2 358 | move 1 from 5 to 9 359 | move 5 from 5 to 6 360 | move 3 from 4 to 2 361 | move 2 from 7 to 1 362 | move 4 from 7 to 8 363 | move 3 from 8 to 6 364 | move 2 from 6 to 7 365 | move 6 from 7 to 8 366 | move 3 from 1 to 5 367 | move 4 from 5 to 9 368 | move 15 from 2 to 1 369 | move 4 from 6 to 4 370 | move 2 from 6 to 3 371 | move 1 from 3 to 7 372 | move 4 from 1 to 2 373 | move 1 from 3 to 4 374 | move 2 from 7 to 4 375 | move 5 from 9 to 3 376 | move 2 from 7 to 3 377 | move 16 from 4 to 8 378 | move 8 from 8 to 5 379 | move 2 from 1 to 5 380 | move 1 from 9 to 6 381 | move 1 from 6 to 5 382 | move 7 from 5 to 9 383 | move 3 from 1 to 8 384 | move 1 from 8 to 4 385 | move 8 from 2 to 7 386 | move 3 from 1 to 3 387 | move 1 from 3 to 9 388 | move 2 from 4 to 2 389 | move 7 from 8 to 5 390 | move 7 from 9 to 1 391 | move 6 from 3 to 5 392 | move 6 from 7 to 4 393 | move 3 from 4 to 1 394 | move 3 from 2 to 5 395 | move 1 from 7 to 8 396 | move 1 from 7 to 5 397 | move 1 from 9 to 8 398 | move 2 from 2 to 4 399 | move 15 from 1 to 6 400 | move 8 from 5 to 9 401 | move 3 from 3 to 4 402 | move 4 from 4 to 3 403 | move 1 from 9 to 7 404 | move 6 from 9 to 4 405 | move 1 from 9 to 2 406 | move 6 from 4 to 9 407 | move 2 from 4 to 6 408 | move 5 from 6 to 9 409 | move 1 from 3 to 1 410 | move 8 from 6 to 8 411 | move 12 from 5 to 3 412 | move 1 from 5 to 3 413 | move 1 from 3 to 8 414 | move 4 from 6 to 1 415 | move 11 from 3 to 8 416 | move 1 from 2 to 1 417 | move 23 from 8 to 2 418 | move 3 from 1 to 2 419 | move 1 from 1 to 9 420 | move 2 from 2 to 3 421 | move 6 from 3 to 6 422 | move 1 from 7 to 6 423 | move 1 from 4 to 7 424 | move 1 from 4 to 3 425 | move 1 from 7 to 3 426 | move 4 from 8 to 4 427 | move 2 from 1 to 8 428 | move 3 from 8 to 1 429 | move 4 from 6 to 2 430 | move 7 from 9 to 1 431 | move 1 from 9 to 6 432 | move 2 from 2 to 3 433 | move 3 from 9 to 4 434 | move 1 from 9 to 3 435 | move 10 from 2 to 8 436 | move 16 from 2 to 5 437 | move 2 from 3 to 6 438 | move 6 from 1 to 8 439 | move 1 from 1 to 5 440 | move 8 from 8 to 5 441 | move 11 from 5 to 9 442 | move 2 from 1 to 8 443 | move 1 from 1 to 8 444 | move 4 from 4 to 6 445 | move 3 from 3 to 9 446 | move 14 from 9 to 3 447 | move 15 from 8 to 5 448 | move 9 from 5 to 4 449 | move 7 from 6 to 1 450 | move 1 from 6 to 3 451 | move 4 from 4 to 7 452 | move 2 from 6 to 2 453 | move 4 from 7 to 4 454 | move 4 from 1 to 4 455 | move 10 from 4 to 3 456 | move 14 from 3 to 6 457 | move 5 from 4 to 1 458 | move 6 from 5 to 7 459 | move 1 from 2 to 6 460 | move 3 from 7 to 2 461 | move 2 from 2 to 3 462 | move 3 from 7 to 8 463 | move 2 from 8 to 2 464 | move 2 from 2 to 7 465 | move 6 from 6 to 2 466 | move 1 from 8 to 7 467 | move 8 from 2 to 7 468 | move 1 from 4 to 1 469 | move 5 from 5 to 3 470 | move 3 from 3 to 2 471 | move 5 from 1 to 3 472 | move 7 from 5 to 8 473 | move 6 from 6 to 3 474 | move 1 from 5 to 9 475 | move 10 from 7 to 9 476 | move 26 from 3 to 4 477 | move 1 from 5 to 1 478 | move 6 from 8 to 2 479 | move 9 from 2 to 9 480 | move 1 from 7 to 5 481 | move 1 from 8 to 5 482 | move 2 from 6 to 2 483 | move 20 from 9 to 6 484 | move 1 from 1 to 6 485 | move 1 from 4 to 2 486 | move 1 from 5 to 8 487 | move 1 from 5 to 7 488 | move 3 from 1 to 3 489 | move 1 from 3 to 6 490 | move 12 from 4 to 8 491 | move 11 from 4 to 5 492 | move 1 from 7 to 5 493 | move 1 from 2 to 8 494 | move 1 from 1 to 8 495 | move 2 from 2 to 5 496 | move 8 from 6 to 2 497 | move 5 from 6 to 4 498 | move 2 from 5 to 3 499 | move 12 from 8 to 4 500 | move 5 from 2 to 6 501 | move 3 from 8 to 1 502 | move 11 from 6 to 8 503 | move 10 from 4 to 6 504 | move 5 from 4 to 6 505 | move 12 from 6 to 5 506 | move 22 from 5 to 6 507 | move 3 from 6 to 5 508 | move 3 from 8 to 5 509 | move 1 from 3 to 8 510 | move 4 from 8 to 1 511 | move 6 from 1 to 7 512 | move 5 from 6 to 9 513 | -------------------------------------------------------------------------------- /day-16/prog.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include "aoc.h" 9 | 10 | /* Node (valve) representation. */ 11 | typedef struct node { 12 | char name[3]; /* Name is always two letters, plus null term. */ 13 | int flow; /* Flow rate. */ 14 | struct node *next[32]; /* Connected nodes. */ 15 | int numnext; /* How many next nodes it has. */ 16 | 17 | /* We have a "next" variant where we enlist all the other nodes 18 | * with the number of steps needed to reach them. Otherwise the program 19 | * takes quite a while to run (hours). This is a way to cut the problem 20 | * dimension, since we are getting rid of all the useless nodes (flow 0) */ 21 | 22 | int open; /* Node already open? */ 23 | struct node *nn; /* Next Node in the linked list of nodes. 24 | This is used for lookup. */ 25 | } node; 26 | 27 | /* Create a new node, and take all the nodes in a linked list 28 | * so we can lookup them even as long as they are not reachable 29 | * from the graph. */ 30 | node *NodesHead = NULL; 31 | node *newNode(void) { 32 | node *n = xalloc(sizeof(*n)); 33 | n->name[0] = n->name[1] = '?'; 34 | n->name[2] = 0; 35 | n->numnext = 0; 36 | n->open = 0; 37 | n->flow = 0; 38 | n->nn = NodesHead; 39 | NodesHead = n; 40 | return n; 41 | } 42 | 43 | /* Return the node named 'name' */ 44 | node *lookupNode(char *name) { 45 | node *n = NodesHead; 46 | while(n) { 47 | if (!memcmp(n->name,name,2)) return n; 48 | n = n->nn; 49 | } 50 | return NULL; 51 | } 52 | 53 | /* Let's remember the path, so that we can print the best path found so far. */ 54 | char BestPath[64]; 55 | char CurPath[64]; 56 | int CurPathLen = 0; 57 | int bestflow[30] = {0}; // Best flow so far in a given minute 58 | int DEBUG = 0; 59 | 60 | /* Scan the graph lookign for the best total flow. 61 | * This scan would take a big amount of time, even in C, so to speedup 62 | * it I use a TERRIBLE heuristic that may not work reliably. 63 | * The search memorize the best flow at every minute, and will 64 | * avoid taking certain paths if the current flow is worse of what 65 | * we seen. This in practice work if you run the program a few times but 66 | * is technically not correct. However allows to substitute all the 67 | * graph preprocessing (shortest path and so forth) with a trivial IF. */ 68 | void searchGraph(node *root, int curflow, int leftminutes, int *maxflow) { 69 | if (DEBUG) printf("Scanning %s\n", CurPath); 70 | /* Ok, so this is the gist of it. The search space is big and it takes 71 | * (even with a C implementation) like one hour to find the solution. 72 | * However solutions that seem to suck compared to what already saw 73 | * in this same minute, are not likely to cut it. However there are times 74 | * where this heuristic would remove trees that are the best so we 75 | * apply it just with a probability. This is not "exact" but works very 76 | * well in practice, without doing precomputation of shortest paths. */ 77 | if (bestflow[leftminutes] < curflow) { 78 | bestflow[leftminutes] = curflow; 79 | } 80 | if (random() % 100 > 25 && curflow < bestflow[leftminutes]) return; 81 | 82 | /* No time left nor valves to open, let's check our total flow. */ 83 | if (leftminutes <= 1) { 84 | if (curflow > *maxflow) { 85 | printf("Best %d: %s\n", curflow, CurPath); 86 | *maxflow = curflow; 87 | memcpy(BestPath,CurPath,sizeof(BestPath)); 88 | } 89 | return; 90 | } 91 | 92 | /* For every next step we can do, consider both the possibility 93 | * of opening this valve and of not opening it. */ 94 | for (int j = 0; j < root->numnext; j++) { 95 | 96 | /* PATH A: "Open it" path. */ 97 | if (root->open == 0 && // We can open it only if not already open. 98 | root->flow > 0) // We don't open broken valves. */ 99 | { 100 | root->open = 1; 101 | CurPath[CurPathLen++] = root->name[0]; 102 | CurPath[CurPathLen++] = root->name[1]; 103 | CurPath[CurPathLen] = 0; 104 | 105 | int flow = root->flow*(leftminutes-1); 106 | searchGraph(root->next[j],flow+curflow,leftminutes-2,maxflow); 107 | 108 | CurPathLen -= 2; 109 | CurPath[CurPathLen] = 0; 110 | root->open = 0; /* Undo so next paths will find it closed. */ 111 | } 112 | 113 | /* PATH B: "Don't open it" path. */ 114 | CurPath[CurPathLen++] = tolower(root->name[0]); 115 | CurPath[CurPathLen++] = tolower(root->name[1]); 116 | CurPath[CurPathLen] = 0; 117 | 118 | searchGraph(root->next[j],curflow,leftminutes-1,maxflow); 119 | CurPathLen -= 2; 120 | CurPath[CurPathLen] = 0; 121 | } 122 | } 123 | 124 | /* Given that we do things randomly, we need more randomness... 125 | * Shuffle all the children nodes of every node. */ 126 | void shuffle(node *n) { 127 | for (int j = 0; j < n->numnext; j++) { 128 | int r = rand() % n->numnext; 129 | if (j == r) continue; 130 | void *tmp = n->next[r]; 131 | n->next[r] = n->next[j]; 132 | n->next[j] = tmp; 133 | } 134 | } 135 | 136 | /* More broken generalizatino of searchGraph(). Needs to run several times 137 | * to find the *actual* best result. */ 138 | void searchGraph2(node *root1, node *root2, int curflow, int leftminutes1, int leftminutes2, int *maxflow) { 139 | if (DEBUG) printf("Scanning %s\n", CurPath); 140 | /* Ok, so this is the gist of it. The search space is big and it takes 141 | * (even with a C implementation) like one hour to find the solution. 142 | * However solutions that seem to suck compared to what already saw 143 | * in this same minute, are not likely to cut it. However there are times 144 | * where this heuristic would remove trees that are the best so we 145 | * apply it just with a probability. This is not "exact" but works very 146 | * well in practice, without doing precomputation of shortest paths. */ 147 | if (leftminutes1 > 0) { 148 | if (bestflow[leftminutes1] < curflow) { 149 | bestflow[leftminutes1] = curflow; 150 | } 151 | if (random() % 100 > 10 && curflow < bestflow[leftminutes1]) return; 152 | } 153 | 154 | if (leftminutes2 > 0) { 155 | if (bestflow[leftminutes2] < curflow) { 156 | bestflow[leftminutes2] = curflow; 157 | } 158 | if (random() % 100 > 10 && curflow < bestflow[leftminutes2]) return; 159 | } 160 | 161 | /* No time left nor valves to open, let's check our total flow. */ 162 | if (leftminutes1 <= 1 && leftminutes2 <= 1) { 163 | if (curflow > *maxflow) { 164 | //printf("Best (%d %d) %d\n", leftminutes1, leftminutes2, curflow); 165 | *maxflow = curflow; 166 | } 167 | return; 168 | } 169 | 170 | /* For every next step we can do, consider both the possibility 171 | * of opening this valve and of not opening it. */ 172 | for (int j = 0; j < root1->numnext; j++) { 173 | for (int i = 0; i < root2->numnext; i++) { 174 | for (int open1 = 0; open1 < 2; open1++) { 175 | for (int open2 = 0; open2 < 2; open2++) { 176 | if (root1 == root2 && open1 && open2) { 177 | /* Both actors can't open the same valve 178 | * at the same time. */ 179 | continue; 180 | } 181 | 182 | if (open1 && root1->open) continue; 183 | if (open2 && root2->open) continue; 184 | 185 | int flow1 = 0, flow2 = 0; 186 | int o1 = open1, o2 = open2; 187 | 188 | if (open1 && root1->open == 0 && root1->flow != 0 && 189 | leftminutes1 >= 1) 190 | { 191 | root1->open = 1; 192 | flow1 = root1->flow*(leftminutes1-1); 193 | } else { 194 | o1 = 0; 195 | flow1 = 0; 196 | } 197 | if (open2 && root2->open == 0 && root2->flow != 0 && 198 | leftminutes2 >= 1) 199 | { 200 | root2->open = 1; 201 | flow2 = root2->flow*(leftminutes2-1); 202 | } else { 203 | o2 = 0; 204 | flow2 = 0; 205 | } 206 | 207 | searchGraph2(root1->next[j],root2->next[i],flow1+flow2+curflow,leftminutes1-1-o1,leftminutes2-1-o2,maxflow); 208 | if (o1) root1->open = 0; 209 | if (o2) root2->open = 0; 210 | } 211 | } 212 | } 213 | } 214 | } 215 | 216 | 217 | 218 | /* Only for debugging: I wanted to see if everything loaded correctly. */ 219 | void printGraph(node *root) { 220 | printf("From %s [%p] you can go to (%d):\n", root->name, (void*)root, 221 | root->numnext); 222 | for (int j = 0; j < root->numnext; j++) { 223 | printf("%d) %s [%p]\n", j, root->next[j]->name, (void*)root->next[j]); 224 | } 225 | root->open = 1; 226 | for (int j = 0; j < root->numnext; j++) { 227 | if (root->next[j]->open == 0) 228 | printGraph(root->next[j]); 229 | } 230 | } 231 | 232 | int main(int argc, char **argv) { 233 | srand(time(NULL)); 234 | 235 | FILE *fp = argc == 2 ? fopen(argv[1],"r") : stdin; 236 | if (!fp) { 237 | perror("fopen"); 238 | exit(1); 239 | } 240 | 241 | /* Input parsing. Boring but needed. */ 242 | char buf[256]; 243 | node *root = NULL; 244 | int numvalves = 0; 245 | while(fgets(buf,sizeof(buf),fp) != NULL) { 246 | size_t l = strlen(buf); 247 | if (l <= 1) continue; 248 | if (buf[l-1] == '\n') { 249 | buf[l-1] = 0; 250 | l--; 251 | } 252 | 253 | char name[3]; 254 | int flow; 255 | 256 | /* Note: next line is quick and dirty and unsafe. */ 257 | sscanf(buf, 258 | "Valve %s has flow rate=%d; tunnels lead to valves", 259 | name, &flow); 260 | 261 | node *this = NULL; 262 | this = lookupNode(name); 263 | if (!this) { 264 | this = newNode(); /* Happens for AA. */ 265 | if (!root) root = this; 266 | } 267 | memcpy(this->name,name,3); 268 | this->flow = flow; 269 | this->open = 0; 270 | 271 | /* Populate list of connected nodes. */ 272 | char *p = strstr(buf,"valve"); 273 | assert(p != NULL); 274 | p += p[5] == 's' ? 7 : 6; 275 | while(1) { 276 | node *new = lookupNode(p); 277 | if (!new) { 278 | new = newNode(); 279 | memcpy(new->name,p,2); 280 | new->name[2] = 0; 281 | } 282 | 283 | /* Add the node as child of the parent. */ 284 | this->next[this->numnext++] = new; 285 | 286 | if (p[2] != ',') break; 287 | p += 4; 288 | } 289 | 290 | printf("Valve %s at %p, flow:%d, numnext:%d\n", 291 | this->name, (void*)this, this->flow, this->numnext); 292 | numvalves++; 293 | } 294 | if (argc == 2) fclose(fp); 295 | 296 | /* Part 1. */ 297 | int maxflow = 0; 298 | root = lookupNode("AA"); 299 | searchGraph(root,0,30,&maxflow); 300 | printf("Part 1 %d following this path:\n", maxflow); 301 | printf("%s\n", BestPath); 302 | 303 | /* Part 2. 304 | * 305 | * Let's find the best path using 26 minutes. */ 306 | int mmflow = 0; /* max maxflow. */ 307 | printf("Keep part 2 running for some time (a few minutes). It will\n" 308 | "converge to the actual solution.\n"); 309 | while(1) { 310 | memset(bestflow,0,sizeof(bestflow)); 311 | CurPathLen = 0; 312 | maxflow = 0; 313 | searchGraph2(root,root,0,26,26,&maxflow); 314 | if (mmflow < maxflow) mmflow = maxflow; 315 | printf("Part 2 %d (highet found: %d)\n", maxflow, mmflow); 316 | 317 | /* Rearrange nodes to explore other paths */ 318 | node *n = NodesHead; 319 | while(n) { 320 | shuffle(n); 321 | n = n->nn; 322 | } 323 | } 324 | } 325 | -------------------------------------------------------------------------------- /day-5/adlist.c: -------------------------------------------------------------------------------- 1 | /* adlist.c - A generic doubly linked list implementation 2 | * 3 | * Copyright (c) 2006-2010, Salvatore Sanfilippo 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions are met: 8 | * 9 | * * Redistributions of source code must retain the above copyright notice, 10 | * this list of conditions and the following disclaimer. 11 | * * Redistributions in binary form must reproduce the above copyright 12 | * notice, this list of conditions and the following disclaimer in the 13 | * documentation and/or other materials provided with the distribution. 14 | * * Neither the name of Redis nor the names of its contributors may be used 15 | * to endorse or promote products derived from this software without 16 | * specific prior written permission. 17 | * 18 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 22 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | * POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | 31 | 32 | #include 33 | #include "adlist.h" 34 | 35 | #define zmalloc malloc 36 | #define zfree free 37 | 38 | /* Create a new list. The created list can be freed with 39 | * listRelease(), but private value of every node need to be freed 40 | * by the user before to call listRelease(), or by setting a free method using 41 | * listSetFreeMethod. 42 | * 43 | * On error, NULL is returned. Otherwise the pointer to the new list. */ 44 | list *listCreate(void) 45 | { 46 | struct list *list; 47 | 48 | if ((list = zmalloc(sizeof(*list))) == NULL) 49 | return NULL; 50 | list->head = list->tail = NULL; 51 | list->len = 0; 52 | list->dup = NULL; 53 | list->free = NULL; 54 | list->match = NULL; 55 | return list; 56 | } 57 | 58 | /* Remove all the elements from the list without destroying the list itself. */ 59 | void listEmpty(list *list) 60 | { 61 | unsigned long len; 62 | listNode *current, *next; 63 | 64 | current = list->head; 65 | len = list->len; 66 | while(len--) { 67 | next = current->next; 68 | if (list->free) list->free(current->value); 69 | zfree(current); 70 | current = next; 71 | } 72 | list->head = list->tail = NULL; 73 | list->len = 0; 74 | } 75 | 76 | /* Free the whole list. 77 | * 78 | * This function can't fail. */ 79 | void listRelease(list *list) 80 | { 81 | listEmpty(list); 82 | zfree(list); 83 | } 84 | 85 | /* Add a new node to the list, to head, containing the specified 'value' 86 | * pointer as value. 87 | * 88 | * On error, NULL is returned and no operation is performed (i.e. the 89 | * list remains unaltered). 90 | * On success the 'list' pointer you pass to the function is returned. */ 91 | list *listAddNodeHead(list *list, void *value) 92 | { 93 | listNode *node; 94 | 95 | if ((node = zmalloc(sizeof(*node))) == NULL) 96 | return NULL; 97 | node->value = value; 98 | listLinkNodeHead(list, node); 99 | return list; 100 | } 101 | 102 | /* 103 | * Add a node that has already been allocated to the head of list 104 | */ 105 | void listLinkNodeHead(list* list, listNode *node) { 106 | if (list->len == 0) { 107 | list->head = list->tail = node; 108 | node->prev = node->next = NULL; 109 | } else { 110 | node->prev = NULL; 111 | node->next = list->head; 112 | list->head->prev = node; 113 | list->head = node; 114 | } 115 | list->len++; 116 | } 117 | 118 | /* Add a new node to the list, to tail, containing the specified 'value' 119 | * pointer as value. 120 | * 121 | * On error, NULL is returned and no operation is performed (i.e. the 122 | * list remains unaltered). 123 | * On success the 'list' pointer you pass to the function is returned. */ 124 | list *listAddNodeTail(list *list, void *value) 125 | { 126 | listNode *node; 127 | 128 | if ((node = zmalloc(sizeof(*node))) == NULL) 129 | return NULL; 130 | node->value = value; 131 | if (list->len == 0) { 132 | list->head = list->tail = node; 133 | node->prev = node->next = NULL; 134 | } else { 135 | node->prev = list->tail; 136 | node->next = NULL; 137 | list->tail->next = node; 138 | list->tail = node; 139 | } 140 | list->len++; 141 | return list; 142 | } 143 | 144 | list *listInsertNode(list *list, listNode *old_node, void *value, int after) { 145 | listNode *node; 146 | 147 | if ((node = zmalloc(sizeof(*node))) == NULL) 148 | return NULL; 149 | node->value = value; 150 | if (after) { 151 | node->prev = old_node; 152 | node->next = old_node->next; 153 | if (list->tail == old_node) { 154 | list->tail = node; 155 | } 156 | } else { 157 | node->next = old_node; 158 | node->prev = old_node->prev; 159 | if (list->head == old_node) { 160 | list->head = node; 161 | } 162 | } 163 | if (node->prev != NULL) { 164 | node->prev->next = node; 165 | } 166 | if (node->next != NULL) { 167 | node->next->prev = node; 168 | } 169 | list->len++; 170 | return list; 171 | } 172 | 173 | /* Remove the specified node from the specified list. 174 | * The node is freed. If free callback is provided the value is freed as well. 175 | * 176 | * This function can't fail. */ 177 | void listDelNode(list *list, listNode *node) 178 | { 179 | listUnlinkNode(list, node); 180 | if (list->free) list->free(node->value); 181 | zfree(node); 182 | } 183 | 184 | /* 185 | * Remove the specified node from the list without freeing it. 186 | */ 187 | void listUnlinkNode(list *list, listNode *node) { 188 | if (node->prev) 189 | node->prev->next = node->next; 190 | else 191 | list->head = node->next; 192 | if (node->next) 193 | node->next->prev = node->prev; 194 | else 195 | list->tail = node->prev; 196 | 197 | node->next = NULL; 198 | node->prev = NULL; 199 | 200 | list->len--; 201 | } 202 | 203 | /* Returns a list iterator 'iter'. After the initialization every 204 | * call to listNext() will return the next element of the list. 205 | * 206 | * This function can't fail. */ 207 | listIter *listGetIterator(list *list, int direction) 208 | { 209 | listIter *iter; 210 | 211 | if ((iter = zmalloc(sizeof(*iter))) == NULL) return NULL; 212 | if (direction == AL_START_HEAD) 213 | iter->next = list->head; 214 | else 215 | iter->next = list->tail; 216 | iter->direction = direction; 217 | return iter; 218 | } 219 | 220 | /* Release the iterator memory */ 221 | void listReleaseIterator(listIter *iter) { 222 | zfree(iter); 223 | } 224 | 225 | /* Create an iterator in the list private iterator structure */ 226 | void listRewind(list *list, listIter *li) { 227 | li->next = list->head; 228 | li->direction = AL_START_HEAD; 229 | } 230 | 231 | void listRewindTail(list *list, listIter *li) { 232 | li->next = list->tail; 233 | li->direction = AL_START_TAIL; 234 | } 235 | 236 | /* Return the next element of an iterator. 237 | * It's valid to remove the currently returned element using 238 | * listDelNode(), but not to remove other elements. 239 | * 240 | * The function returns a pointer to the next element of the list, 241 | * or NULL if there are no more elements, so the classical usage 242 | * pattern is: 243 | * 244 | * iter = listGetIterator(list,); 245 | * while ((node = listNext(iter)) != NULL) { 246 | * doSomethingWith(listNodeValue(node)); 247 | * } 248 | * 249 | * */ 250 | listNode *listNext(listIter *iter) 251 | { 252 | listNode *current = iter->next; 253 | 254 | if (current != NULL) { 255 | if (iter->direction == AL_START_HEAD) 256 | iter->next = current->next; 257 | else 258 | iter->next = current->prev; 259 | } 260 | return current; 261 | } 262 | 263 | /* Duplicate the whole list. On out of memory NULL is returned. 264 | * On success a copy of the original list is returned. 265 | * 266 | * The 'Dup' method set with listSetDupMethod() function is used 267 | * to copy the node value. Otherwise the same pointer value of 268 | * the original node is used as value of the copied node. 269 | * 270 | * The original list both on success or error is never modified. */ 271 | list *listDup(list *orig) 272 | { 273 | list *copy; 274 | listIter iter; 275 | listNode *node; 276 | 277 | if ((copy = listCreate()) == NULL) 278 | return NULL; 279 | copy->dup = orig->dup; 280 | copy->free = orig->free; 281 | copy->match = orig->match; 282 | listRewind(orig, &iter); 283 | while((node = listNext(&iter)) != NULL) { 284 | void *value; 285 | 286 | if (copy->dup) { 287 | value = copy->dup(node->value); 288 | if (value == NULL) { 289 | listRelease(copy); 290 | return NULL; 291 | } 292 | } else { 293 | value = node->value; 294 | } 295 | 296 | if (listAddNodeTail(copy, value) == NULL) { 297 | /* Free value if dup succeed but listAddNodeTail failed. */ 298 | if (copy->free) copy->free(value); 299 | 300 | listRelease(copy); 301 | return NULL; 302 | } 303 | } 304 | return copy; 305 | } 306 | 307 | /* Search the list for a node matching a given key. 308 | * The match is performed using the 'match' method 309 | * set with listSetMatchMethod(). If no 'match' method 310 | * is set, the 'value' pointer of every node is directly 311 | * compared with the 'key' pointer. 312 | * 313 | * On success the first matching node pointer is returned 314 | * (search starts from head). If no matching node exists 315 | * NULL is returned. */ 316 | listNode *listSearchKey(list *list, void *key) 317 | { 318 | listIter iter; 319 | listNode *node; 320 | 321 | listRewind(list, &iter); 322 | while((node = listNext(&iter)) != NULL) { 323 | if (list->match) { 324 | if (list->match(node->value, key)) { 325 | return node; 326 | } 327 | } else { 328 | if (key == node->value) { 329 | return node; 330 | } 331 | } 332 | } 333 | return NULL; 334 | } 335 | 336 | /* Return the element at the specified zero-based index 337 | * where 0 is the head, 1 is the element next to head 338 | * and so on. Negative integers are used in order to count 339 | * from the tail, -1 is the last element, -2 the penultimate 340 | * and so on. If the index is out of range NULL is returned. */ 341 | listNode *listIndex(list *list, long index) { 342 | listNode *n; 343 | 344 | if (index < 0) { 345 | index = (-index)-1; 346 | n = list->tail; 347 | while(index-- && n) n = n->prev; 348 | } else { 349 | n = list->head; 350 | while(index-- && n) n = n->next; 351 | } 352 | return n; 353 | } 354 | 355 | /* Rotate the list removing the tail node and inserting it to the head. */ 356 | void listRotateTailToHead(list *list) { 357 | if (listLength(list) <= 1) return; 358 | 359 | /* Detach current tail */ 360 | listNode *tail = list->tail; 361 | list->tail = tail->prev; 362 | list->tail->next = NULL; 363 | /* Move it as head */ 364 | list->head->prev = tail; 365 | tail->prev = NULL; 366 | tail->next = list->head; 367 | list->head = tail; 368 | } 369 | 370 | /* Rotate the list removing the head node and inserting it to the tail. */ 371 | void listRotateHeadToTail(list *list) { 372 | if (listLength(list) <= 1) return; 373 | 374 | listNode *head = list->head; 375 | /* Detach current head */ 376 | list->head = head->next; 377 | list->head->prev = NULL; 378 | /* Move it as tail */ 379 | list->tail->next = head; 380 | head->next = NULL; 381 | head->prev = list->tail; 382 | list->tail = head; 383 | } 384 | 385 | /* Add all the elements of the list 'o' at the end of the 386 | * list 'l'. The list 'other' remains empty but otherwise valid. */ 387 | void listJoin(list *l, list *o) { 388 | if (o->len == 0) return; 389 | 390 | o->head->prev = l->tail; 391 | 392 | if (l->tail) 393 | l->tail->next = o->head; 394 | else 395 | l->head = o->head; 396 | 397 | l->tail = o->tail; 398 | l->len += o->len; 399 | 400 | /* Setup other as an empty list. */ 401 | o->head = o->tail = NULL; 402 | o->len = 0; 403 | } 404 | 405 | /* Initializes the node's value and sets its pointers 406 | * so that it is initially not a member of any list. 407 | */ 408 | void listInitNode(listNode *node, void *value) { 409 | node->prev = NULL; 410 | node->next = NULL; 411 | node->value = value; 412 | } 413 | -------------------------------------------------------------------------------- /day-7/input.txt: -------------------------------------------------------------------------------- 1 | $ cd / 2 | $ ls 3 | dir drblq 4 | 133789 fjf 5 | dir jpfrhmw 6 | dir jqfwd 7 | dir ncgffsr 8 | 12962 ntnr.lrq 9 | dir qnbq 10 | dir rqdngnrq 11 | dir shcvnqq 12 | dir vsd 13 | dir vtzvf 14 | $ cd drblq 15 | $ ls 16 | 133843 bglzqdd 17 | dir brfnfhj 18 | 268201 fbqjmp.jzv 19 | 80676 shcvnqq 20 | $ cd brfnfhj 21 | $ ls 22 | 150447 jlcg.dsg 23 | dir nhvgrzs 24 | $ cd nhvgrzs 25 | $ ls 26 | 282889 jlcg.dsg 27 | 19004 ncgffsr.gwr 28 | dir vbzr 29 | 6338 vpsgdph.gbh 30 | dir wdcn 31 | $ cd vbzr 32 | $ ls 33 | 225101 fbqjmp 34 | 243277 vbzr 35 | $ cd .. 36 | $ cd wdcn 37 | $ ls 38 | 154089 dlmpbbf.psv 39 | $ cd .. 40 | $ cd .. 41 | $ cd .. 42 | $ cd .. 43 | $ cd jpfrhmw 44 | $ ls 45 | 87622 cffdsj.jzf 46 | 26165 qnbq.sbm 47 | dir vbzr 48 | $ cd vbzr 49 | $ ls 50 | dir blhstw 51 | 16919 nttftcts 52 | dir rgdp 53 | 116477 shcvnqq 54 | 242592 tmjrnqbz.chq 55 | dir vbzr 56 | dir wmct 57 | $ cd blhstw 58 | $ ls 59 | 98023 jwdv.qct 60 | $ cd .. 61 | $ cd rgdp 62 | $ ls 63 | dir gcb 64 | 141507 shcvnqq 65 | dir ssvzm 66 | $ cd gcb 67 | $ ls 68 | 189016 ncgffsr.rbq 69 | $ cd .. 70 | $ cd ssvzm 71 | $ ls 72 | 82667 shcvnqq.zjq 73 | $ cd .. 74 | $ cd .. 75 | $ cd vbzr 76 | $ ls 77 | 120202 jlcg.dsg 78 | 86205 vbzr.jtr 79 | $ cd .. 80 | $ cd wmct 81 | $ ls 82 | dir fbsfcgph 83 | 155709 hpsftv 84 | 13636 lztgs 85 | 273353 ncgffsr.jsg 86 | dir pvwhpfp 87 | $ cd fbsfcgph 88 | $ ls 89 | 139944 ncgffsr.gpf 90 | $ cd .. 91 | $ cd pvwhpfp 92 | $ ls 93 | 111230 bscrjpzh.glp 94 | dir dgjsddgq 95 | 37234 lwd 96 | 107139 lztgs 97 | 258111 mgtwwvwz 98 | 117638 qpdvnfb.gnf 99 | dir szrplcdw 100 | dir vzsl 101 | dir wsmf 102 | $ cd dgjsddgq 103 | $ ls 104 | dir qnbq 105 | $ cd qnbq 106 | $ ls 107 | 199119 jlcg.dsg 108 | $ cd .. 109 | $ cd .. 110 | $ cd szrplcdw 111 | $ ls 112 | 122236 qclr.cpf 113 | 269638 qnbq 114 | $ cd .. 115 | $ cd vzsl 116 | $ ls 117 | 233006 twpz.tdm 118 | $ cd .. 119 | $ cd wsmf 120 | $ ls 121 | dir wcnptvtz 122 | $ cd wcnptvtz 123 | $ ls 124 | 183952 shcvnqq.lwt 125 | $ cd .. 126 | $ cd .. 127 | $ cd .. 128 | $ cd .. 129 | $ cd .. 130 | $ cd .. 131 | $ cd jqfwd 132 | $ ls 133 | dir hqb 134 | 285121 jqffsjbs.jrm 135 | dir nhpqpdn 136 | dir qnbq 137 | dir qtrv 138 | dir wspztvjr 139 | $ cd hqb 140 | $ ls 141 | 253786 jwdv.qct 142 | dir vbzr 143 | $ cd vbzr 144 | $ ls 145 | 153 gbh 146 | dir gqpqqrgl 147 | dir jzncgd 148 | 36914 nvdnsnls.mpd 149 | $ cd gqpqqrgl 150 | $ ls 151 | 206691 dmdgcwm.bgh 152 | $ cd .. 153 | $ cd jzncgd 154 | $ ls 155 | 122640 vrgmf.tnp 156 | $ cd .. 157 | $ cd .. 158 | $ cd .. 159 | $ cd nhpqpdn 160 | $ ls 161 | 86329 ntnr.lrq 162 | $ cd .. 163 | $ cd qnbq 164 | $ ls 165 | 76269 fbqjmp.lbd 166 | 118968 fbqjmp.msg 167 | 190416 gfwhsb.dpc 168 | dir lhgjrmj 169 | dir pbv 170 | 173541 pfl 171 | 141842 srrmt.ssj 172 | $ cd lhgjrmj 173 | $ ls 174 | dir ghccnw 175 | 180420 ldzcj.rwz 176 | 149356 lztgs 177 | 61792 ncgffsr 178 | dir spmbcjhc 179 | $ cd ghccnw 180 | $ ls 181 | 253233 lztgs 182 | 56439 ntnr.lrq 183 | 19225 ntrmjf.gdb 184 | 31628 pdhhzjhm.lbd 185 | $ cd .. 186 | $ cd spmbcjhc 187 | $ ls 188 | dir shcvnqq 189 | $ cd shcvnqq 190 | $ ls 191 | 122334 drjbh 192 | $ cd .. 193 | $ cd .. 194 | $ cd .. 195 | $ cd pbv 196 | $ ls 197 | 69436 cctsjqh.wqr 198 | 285573 ljtqddz 199 | $ cd .. 200 | $ cd .. 201 | $ cd qtrv 202 | $ ls 203 | 234568 dmwqfbwd 204 | dir pwwsrjc 205 | 245046 qmcr 206 | 159151 qtvdjncm.rdb 207 | dir swhzds 208 | 178915 vbzr.vgn 209 | dir vcgv 210 | $ cd pwwsrjc 211 | $ ls 212 | 173975 bgdj.jnw 213 | 202714 jwdv.qct 214 | 270702 wggrgcvw.rtp 215 | $ cd .. 216 | $ cd swhzds 217 | $ ls 218 | 114686 jwdv.qct 219 | $ cd .. 220 | $ cd vcgv 221 | $ ls 222 | dir fbqjmp 223 | dir qlsgtfhf 224 | dir vbzr 225 | $ cd fbqjmp 226 | $ ls 227 | 73065 fbqjmp.jfb 228 | dir shcvnqq 229 | $ cd shcvnqq 230 | $ ls 231 | 231428 shcvnqq 232 | $ cd .. 233 | $ cd .. 234 | $ cd qlsgtfhf 235 | $ ls 236 | 75227 ntnr.lrq 237 | $ cd .. 238 | $ cd vbzr 239 | $ ls 240 | 128050 ncgffsr.gsj 241 | 187649 vbzr 242 | $ cd .. 243 | $ cd .. 244 | $ cd .. 245 | $ cd wspztvjr 246 | $ ls 247 | dir pntrhtwh 248 | dir qnbq 249 | dir zfdzvv 250 | $ cd pntrhtwh 251 | $ ls 252 | 237258 cffhtr 253 | $ cd .. 254 | $ cd qnbq 255 | $ ls 256 | dir qnbq 257 | $ cd qnbq 258 | $ ls 259 | dir ccwmftsj 260 | $ cd ccwmftsj 261 | $ ls 262 | dir mfc 263 | dir shcvnqq 264 | 12262 smpjmn 265 | $ cd mfc 266 | $ ls 267 | 198047 fbqjmp.cgh 268 | dir gghsht 269 | 205411 wlclz 270 | $ cd gghsht 271 | $ ls 272 | 31767 vbzr.lmb 273 | $ cd .. 274 | $ cd .. 275 | $ cd shcvnqq 276 | $ ls 277 | dir lgrghwf 278 | $ cd lgrghwf 279 | $ ls 280 | 114786 shcvnqq.vrz 281 | $ cd .. 282 | $ cd .. 283 | $ cd .. 284 | $ cd .. 285 | $ cd .. 286 | $ cd zfdzvv 287 | $ ls 288 | 54298 sjp 289 | 60303 tcmhrll.htm 290 | $ cd .. 291 | $ cd .. 292 | $ cd .. 293 | $ cd ncgffsr 294 | $ ls 295 | dir fqqsqmpr 296 | dir gfznw 297 | dir ncdft 298 | dir pwmppt 299 | dir shcvnqq 300 | 196969 vbzr 301 | 214841 vzgvr 302 | $ cd fqqsqmpr 303 | $ ls 304 | dir mcdjcntr 305 | $ cd mcdjcntr 306 | $ ls 307 | 281856 ncgffsr.lbm 308 | $ cd .. 309 | $ cd .. 310 | $ cd gfznw 311 | $ ls 312 | 255657 fzrctbsj.lgf 313 | dir ltfsndpd 314 | 175434 qnbq 315 | 31794 qnbq.zhd 316 | 13366 shcvnqq.wld 317 | dir vcspqgn 318 | 235199 wmnjjd.bnh 319 | dir wqpnp 320 | $ cd ltfsndpd 321 | $ ls 322 | dir ncgffsr 323 | dir zpzvdhb 324 | $ cd ncgffsr 325 | $ ls 326 | 9898 jjbsnj.gcg 327 | $ cd .. 328 | $ cd zpzvdhb 329 | $ ls 330 | 106139 lnp 331 | $ cd .. 332 | $ cd .. 333 | $ cd vcspqgn 334 | $ ls 335 | 25386 dgsmmqj 336 | $ cd .. 337 | $ cd wqpnp 338 | $ ls 339 | 65905 wjtbfvjp.fmd 340 | $ cd .. 341 | $ cd .. 342 | $ cd ncdft 343 | $ ls 344 | 34616 bzlpmsqc 345 | 59863 jlcg.dsg 346 | 64629 zpzjcl.fmp 347 | $ cd .. 348 | $ cd pwmppt 349 | $ ls 350 | dir dwnqgrzm 351 | 80901 vbzr.vsg 352 | 89557 vbzr.zlz 353 | $ cd dwnqgrzm 354 | $ ls 355 | 184770 jwdv.qct 356 | dir vbzr 357 | $ cd vbzr 358 | $ ls 359 | 210329 jlcg.dsg 360 | 62272 jwdv.qct 361 | $ cd .. 362 | $ cd .. 363 | $ cd .. 364 | $ cd shcvnqq 365 | $ ls 366 | 128433 gbh 367 | 30208 hjbw 368 | 200071 jlcg.dsg 369 | dir sgcz 370 | 25045 tbhlwfqg.hts 371 | $ cd sgcz 372 | $ ls 373 | 193481 gbh 374 | 96461 jwdv.qct 375 | $ cd .. 376 | $ cd .. 377 | $ cd .. 378 | $ cd qnbq 379 | $ ls 380 | 236171 shcvnqq 381 | $ cd .. 382 | $ cd rqdngnrq 383 | $ ls 384 | dir cprnb 385 | 280135 hshsfqwm 386 | dir hwhm 387 | 245626 qnbq 388 | 145502 qspgdz 389 | 114231 rctg.tgt 390 | dir zgn 391 | $ cd cprnb 392 | $ ls 393 | 115025 twwgmmp.wbb 394 | $ cd .. 395 | $ cd hwhm 396 | $ ls 397 | 229849 cvm 398 | 190622 jwdv.qct 399 | dir mscztz 400 | dir ncgffsr 401 | $ cd mscztz 402 | $ ls 403 | 59743 bzgpzn.bds 404 | 75184 pbdgv 405 | 181089 shcvnqq.dhq 406 | dir zqgtr 407 | $ cd zqgtr 408 | $ ls 409 | 189142 ffnznfs.nct 410 | $ cd .. 411 | $ cd .. 412 | $ cd ncgffsr 413 | $ ls 414 | dir dphrnjl 415 | dir zzfztql 416 | $ cd dphrnjl 417 | $ ls 418 | 117317 vbzr 419 | $ cd .. 420 | $ cd zzfztql 421 | $ ls 422 | 51096 lztgs 423 | $ cd .. 424 | $ cd .. 425 | $ cd .. 426 | $ cd zgn 427 | $ ls 428 | dir bpbzwgz 429 | dir gqnw 430 | 75631 ljptj 431 | 283351 ljzhsw.rbs 432 | 131158 lztgs 433 | dir ncgffsr 434 | 3136 nnpl.swf 435 | dir shcvnqq 436 | dir vbzr 437 | $ cd bpbzwgz 438 | $ ls 439 | 29659 jlcg.dsg 440 | 15547 shcvnqq 441 | 117389 zprhsdfv 442 | $ cd .. 443 | $ cd gqnw 444 | $ ls 445 | 117091 brqwhst.jgb 446 | 88406 nzjmbrrm.hmh 447 | $ cd .. 448 | $ cd ncgffsr 449 | $ ls 450 | 195821 gbh 451 | dir lbzgc 452 | 226692 llqqr.spq 453 | 247989 lztgs 454 | 231909 vnctc 455 | 157973 wqnggh 456 | $ cd lbzgc 457 | $ ls 458 | 251414 ffmsbscc.dqg 459 | 46840 lztgs 460 | $ cd .. 461 | $ cd .. 462 | $ cd shcvnqq 463 | $ ls 464 | dir dvvmhzcq 465 | dir ncgffsr 466 | dir sqzzllv 467 | $ cd dvvmhzcq 468 | $ ls 469 | dir qnbq 470 | 70226 qvvm.rpp 471 | dir shcvnqq 472 | $ cd qnbq 473 | $ ls 474 | 103994 bfcjrmvr.ltq 475 | dir fbqjmp 476 | dir fcs 477 | 177152 gjghvvw.bzg 478 | dir lbfjqh 479 | 78412 ntnr.lrq 480 | dir sgjtm 481 | 286995 shcvnqq 482 | 51750 wmq.vjj 483 | $ cd fbqjmp 484 | $ ls 485 | 267212 qhhb.zvg 486 | $ cd .. 487 | $ cd fcs 488 | $ ls 489 | 272051 znhsswwh.mjj 490 | $ cd .. 491 | $ cd lbfjqh 492 | $ ls 493 | 261487 jlcg.dsg 494 | $ cd .. 495 | $ cd sgjtm 496 | $ ls 497 | dir dnznpj 498 | dir jzsntnbs 499 | dir nqgcbd 500 | dir vdg 501 | $ cd dnznpj 502 | $ ls 503 | 173938 hrp.cjq 504 | 180485 qnbq.thj 505 | 215400 ztvt.wnt 506 | $ cd .. 507 | $ cd jzsntnbs 508 | $ ls 509 | 67448 gpvgh.psg 510 | $ cd .. 511 | $ cd nqgcbd 512 | $ ls 513 | 196250 fbqjmp.qcv 514 | 198482 jlcg.dsg 515 | $ cd .. 516 | $ cd vdg 517 | $ ls 518 | 257343 jwdv.qct 519 | $ cd .. 520 | $ cd .. 521 | $ cd .. 522 | $ cd shcvnqq 523 | $ ls 524 | 156769 fbqjmp.hdb 525 | $ cd .. 526 | $ cd .. 527 | $ cd ncgffsr 528 | $ ls 529 | 205473 fbqjmp 530 | 113067 gsvznzz.qtv 531 | $ cd .. 532 | $ cd sqzzllv 533 | $ ls 534 | 146018 ddvjgswr.gsq 535 | $ cd .. 536 | $ cd .. 537 | $ cd vbzr 538 | $ ls 539 | dir vbzr 540 | $ cd vbzr 541 | $ ls 542 | 266721 mhlfqpbs.pwr 543 | $ cd .. 544 | $ cd .. 545 | $ cd .. 546 | $ cd .. 547 | $ cd shcvnqq 548 | $ ls 549 | dir slnvdd 550 | $ cd slnvdd 551 | $ ls 552 | 90875 pzqv.gnv 553 | 207484 rbrj.vcr 554 | $ cd .. 555 | $ cd .. 556 | $ cd vsd 557 | $ ls 558 | dir dfb 559 | dir fqqnsph 560 | dir gbwdhjr 561 | 18837 jwdv.qct 562 | dir ncgffsr 563 | dir qnbq 564 | dir rjzjrbvs 565 | $ cd dfb 566 | $ ls 567 | dir bpst 568 | 66174 jwdv.qct 569 | dir lcwhfzjw 570 | $ cd bpst 571 | $ ls 572 | dir nqftnn 573 | dir pcvgnvnp 574 | $ cd nqftnn 575 | $ ls 576 | dir bbrsg 577 | dir gjfc 578 | dir hfql 579 | dir shcvnqq 580 | 139226 shcvnqq.sbd 581 | dir ssnjqbg 582 | $ cd bbrsg 583 | $ ls 584 | 73382 vjcf 585 | $ cd .. 586 | $ cd gjfc 587 | $ ls 588 | 164310 gbh 589 | 126316 mmqnrc 590 | 133899 ntnr.lrq 591 | 102615 rgfhrt 592 | $ cd .. 593 | $ cd hfql 594 | $ ls 595 | 14685 jwdv.qct 596 | $ cd .. 597 | $ cd shcvnqq 598 | $ ls 599 | 119597 lztgs 600 | 34165 shcvnqq.zcg 601 | $ cd .. 602 | $ cd ssnjqbg 603 | $ ls 604 | 77678 gqdfbqj.tmj 605 | $ cd .. 606 | $ cd .. 607 | $ cd pcvgnvnp 608 | $ ls 609 | 21250 lhq 610 | 266619 qps.crp 611 | $ cd .. 612 | $ cd .. 613 | $ cd lcwhfzjw 614 | $ ls 615 | dir bhdnnbvm 616 | dir fdnsvfh 617 | 12002 jlcg.dsg 618 | dir lfdbzfl 619 | 46488 ncgffsr 620 | 233704 nthcv.pnc 621 | 204660 ntnr.lrq 622 | 172482 shcvnqq 623 | dir tlw 624 | $ cd bhdnnbvm 625 | $ ls 626 | 37204 fwrdjw.zvv 627 | 3248 ntnr.lrq 628 | $ cd .. 629 | $ cd fdnsvfh 630 | $ ls 631 | 20765 jlfgnwb.szl 632 | $ cd .. 633 | $ cd lfdbzfl 634 | $ ls 635 | dir fspntmld 636 | 183925 jlcg.dsg 637 | $ cd fspntmld 638 | $ ls 639 | 251568 lztgs 640 | 146785 ncgffsr.mmj 641 | $ cd .. 642 | $ cd .. 643 | $ cd tlw 644 | $ ls 645 | dir qqn 646 | $ cd qqn 647 | $ ls 648 | 39232 lprqfwf 649 | $ cd .. 650 | $ cd .. 651 | $ cd .. 652 | $ cd .. 653 | $ cd fqqnsph 654 | $ ls 655 | 132318 lztgs 656 | 103863 ntnr.lrq 657 | 18793 tngbs 658 | $ cd .. 659 | $ cd gbwdhjr 660 | $ ls 661 | 253798 jwdv.qct 662 | $ cd .. 663 | $ cd ncgffsr 664 | $ ls 665 | 110767 blctz.tqz 666 | dir csfssn 667 | dir dbbfz 668 | dir hjgm 669 | dir hwd 670 | 249139 rgcz.gnz 671 | dir wgw 672 | $ cd csfssn 673 | $ ls 674 | dir dlcw 675 | dir jqspd 676 | 119066 mlwlc.mql 677 | dir ncgffsr 678 | 203475 nwnbsc 679 | 143071 qnbq 680 | 116623 qvw.gjz 681 | 83637 whm.cdg 682 | $ cd dlcw 683 | $ ls 684 | 232066 gqllsd.qpl 685 | 1046 mfsh 686 | $ cd .. 687 | $ cd jqspd 688 | $ ls 689 | 251070 mthmm.bmh 690 | $ cd .. 691 | $ cd ncgffsr 692 | $ ls 693 | 83639 ntnr.lrq 694 | $ cd .. 695 | $ cd .. 696 | $ cd dbbfz 697 | $ ls 698 | 112576 jgqf.qmj 699 | 148549 jlcg.dsg 700 | 144811 jwdv.qct 701 | 23726 ntnr.lrq 702 | 123802 pgdjchrf.vnm 703 | dir vzfbzbcp 704 | $ cd vzfbzbcp 705 | $ ls 706 | 39375 fbqq 707 | 31914 jwdv.qct 708 | 165999 lztgs 709 | $ cd .. 710 | $ cd .. 711 | $ cd hjgm 712 | $ ls 713 | dir ljqjtdmf 714 | 100534 mdw 715 | 219057 qnbq 716 | 97164 rzjwmvdw.vlv 717 | dir shcvnqq 718 | 83034 vbzr 719 | $ cd ljqjtdmf 720 | $ ls 721 | 23716 dmslzv.qns 722 | 159519 gbh 723 | dir hlvbmpg 724 | dir nlqqshp 725 | 247315 vqt 726 | dir wlsjnthg 727 | $ cd hlvbmpg 728 | $ ls 729 | 54421 jlcg.dsg 730 | $ cd .. 731 | $ cd nlqqshp 732 | $ ls 733 | dir rvzprwhp 734 | $ cd rvzprwhp 735 | $ ls 736 | 35024 lztgs 737 | $ cd .. 738 | $ cd .. 739 | $ cd wlsjnthg 740 | $ ls 741 | 29178 gnrlgb.bgh 742 | $ cd .. 743 | $ cd .. 744 | $ cd shcvnqq 745 | $ ls 746 | 150311 nvrd 747 | $ cd .. 748 | $ cd .. 749 | $ cd hwd 750 | $ ls 751 | dir jzqtmm 752 | $ cd jzqtmm 753 | $ ls 754 | 103547 jtvdt.jtn 755 | $ cd .. 756 | $ cd .. 757 | $ cd wgw 758 | $ ls 759 | dir mmhlt 760 | $ cd mmhlt 761 | $ ls 762 | dir cmwjh 763 | $ cd cmwjh 764 | $ ls 765 | 243844 qnbq.shn 766 | $ cd .. 767 | $ cd .. 768 | $ cd .. 769 | $ cd .. 770 | $ cd qnbq 771 | $ ls 772 | dir dhfng 773 | dir fbqjmp 774 | 16855 rgrszmrh.lbl 775 | dir rqjs 776 | dir shcvnqq 777 | 38322 vhvrmq 778 | $ cd dhfng 779 | $ ls 780 | 132537 gwngz.hpt 781 | dir lbccc 782 | 182221 ntnr.lrq 783 | $ cd lbccc 784 | $ ls 785 | 282448 fbqjmp.njj 786 | 267049 gbh 787 | dir jtj 788 | dir ntnn 789 | dir vbfgmmvw 790 | 128500 vbzr 791 | $ cd jtj 792 | $ ls 793 | dir hvmlh 794 | $ cd hvmlh 795 | $ ls 796 | 131886 dmww.sqc 797 | $ cd .. 798 | $ cd .. 799 | $ cd ntnn 800 | $ ls 801 | 109064 lgh.bbf 802 | dir wfgdd 803 | 53862 wflv.ngc 804 | $ cd wfgdd 805 | $ ls 806 | 58756 gbh 807 | dir lgzlndn 808 | dir qnbq 809 | $ cd lgzlndn 810 | $ ls 811 | 190415 dwsqvczd 812 | $ cd .. 813 | $ cd qnbq 814 | $ ls 815 | 240922 znjhmhp.ngt 816 | $ cd .. 817 | $ cd .. 818 | $ cd .. 819 | $ cd vbfgmmvw 820 | $ ls 821 | 271827 vbzr.dfl 822 | $ cd .. 823 | $ cd .. 824 | $ cd .. 825 | $ cd fbqjmp 826 | $ ls 827 | 144993 gvpnf 828 | 150786 jwdv.qct 829 | 49025 pdcwwtt.grs 830 | $ cd .. 831 | $ cd rqjs 832 | $ ls 833 | dir bwnzs 834 | 119390 jlcg.dsg 835 | 172042 vjzg 836 | $ cd bwnzs 837 | $ ls 838 | 108537 hzzgm.zrn 839 | 38699 qgfqbfr 840 | dir vhvcfhvr 841 | $ cd vhvcfhvr 842 | $ ls 843 | 2783 jwdv.qct 844 | 209933 mgj.nvj 845 | $ cd .. 846 | $ cd .. 847 | $ cd .. 848 | $ cd shcvnqq 849 | $ ls 850 | 257312 fbqjmp 851 | 193792 msdqtrpn.grn 852 | 98165 rgm 853 | $ cd .. 854 | $ cd .. 855 | $ cd rjzjrbvs 856 | $ ls 857 | dir ftrlfg 858 | dir mtrnl 859 | dir rdpbbd 860 | dir shcvnqq 861 | dir vztnr 862 | $ cd ftrlfg 863 | $ ls 864 | 196590 cjjvwjb 865 | dir ffsvh 866 | 70123 ldnbc 867 | dir lwnfc 868 | 106499 lztgs 869 | dir ncgffsr 870 | dir tfdctq 871 | dir vgthdbf 872 | 80852 zndjt.wtl 873 | $ cd ffsvh 874 | $ ls 875 | 20370 dvdftpvb.qcj 876 | $ cd .. 877 | $ cd lwnfc 878 | $ ls 879 | dir fgmd 880 | dir gmdjt 881 | 274331 hmgjmq.vbz 882 | 9726 qjfdqbf.dfj 883 | dir ssnncn 884 | $ cd fgmd 885 | $ ls 886 | 280608 jwdv.qct 887 | 201912 rqtbw.shd 888 | $ cd .. 889 | $ cd gmdjt 890 | $ ls 891 | 202107 jwdv.qct 892 | $ cd .. 893 | $ cd ssnncn 894 | $ ls 895 | 140697 jwdv.qct 896 | $ cd .. 897 | $ cd .. 898 | $ cd ncgffsr 899 | $ ls 900 | 227389 fpdfqp.fzl 901 | 164141 hzhrrvpm.hlf 902 | $ cd .. 903 | $ cd tfdctq 904 | $ ls 905 | dir cttmzlw 906 | dir ntvtm 907 | 257094 qnbq.zjm 908 | 284928 shcvnqq 909 | $ cd cttmzlw 910 | $ ls 911 | 142651 rptschdv.mgv 912 | $ cd .. 913 | $ cd ntvtm 914 | $ ls 915 | 176269 dhpj 916 | 88278 gbh 917 | $ cd .. 918 | $ cd .. 919 | $ cd vgthdbf 920 | $ ls 921 | 130998 ncgffsr.mnf 922 | $ cd .. 923 | $ cd .. 924 | $ cd mtrnl 925 | $ ls 926 | 86144 djwnvdj 927 | 122600 gsdpwh.cmb 928 | $ cd .. 929 | $ cd rdpbbd 930 | $ ls 931 | 177384 gbh 932 | dir gstfdm 933 | dir qnbq 934 | dir qtj 935 | 260302 vbzr.dhq 936 | $ cd gstfdm 937 | $ ls 938 | 23734 mnwzrm.hzr 939 | $ cd .. 940 | $ cd qnbq 941 | $ ls 942 | 51705 gmt 943 | 205537 ntnr.lrq 944 | 94469 vbzr.bvj 945 | $ cd .. 946 | $ cd qtj 947 | $ ls 948 | dir tls 949 | dir zvpcfhg 950 | $ cd tls 951 | $ ls 952 | dir chvgwnt 953 | dir jvgnmfjw 954 | $ cd chvgwnt 955 | $ ls 956 | dir rbw 957 | dir srhj 958 | $ cd rbw 959 | $ ls 960 | 174372 btjd.bvv 961 | 272995 cnqqh.dfc 962 | $ cd .. 963 | $ cd srhj 964 | $ ls 965 | 134054 qwzpr 966 | $ cd .. 967 | $ cd .. 968 | $ cd jvgnmfjw 969 | $ ls 970 | dir hdcwbwgm 971 | 236775 sdc 972 | $ cd hdcwbwgm 973 | $ ls 974 | 113707 ntnr.lrq 975 | $ cd .. 976 | $ cd .. 977 | $ cd .. 978 | $ cd zvpcfhg 979 | $ ls 980 | dir lsq 981 | $ cd lsq 982 | $ ls 983 | 220331 jlcg.dsg 984 | $ cd .. 985 | $ cd .. 986 | $ cd .. 987 | $ cd .. 988 | $ cd shcvnqq 989 | $ ls 990 | dir cmwrqgfq 991 | 258731 fbqjmp.fvn 992 | 277895 gbh 993 | 64973 jlcg.dsg 994 | 77978 jwdv.qct 995 | dir lttjrdn 996 | dir sqgnhc 997 | $ cd cmwrqgfq 998 | $ ls 999 | 81199 gbh 1000 | $ cd .. 1001 | $ cd lttjrdn 1002 | $ ls 1003 | 23355 gbh 1004 | 148263 hcgfqdw 1005 | 57338 hjwr 1006 | 166510 jbvnmcj 1007 | $ cd .. 1008 | $ cd sqgnhc 1009 | $ ls 1010 | dir glswqrdp 1011 | dir qnbq 1012 | $ cd glswqrdp 1013 | $ ls 1014 | 225761 ncgffsr.vct 1015 | $ cd .. 1016 | $ cd qnbq 1017 | $ ls 1018 | 62861 pdqz.wzs 1019 | $ cd .. 1020 | $ cd .. 1021 | $ cd .. 1022 | $ cd vztnr 1023 | $ ls 1024 | 189943 wvtlfsp 1025 | $ cd .. 1026 | $ cd .. 1027 | $ cd .. 1028 | $ cd vtzvf 1029 | $ ls 1030 | 43248 jwdv.qct 1031 | --------------------------------------------------------------------------------