-
Notifications
You must be signed in to change notification settings - Fork 0
/
day61.pl
130 lines (104 loc) · 3.45 KB
/
day61.pl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
/*
Advent of Code Day 6
Fred Martin, [email protected]
Mon Dec 21, 2020 6:40 PM
Looks like we can concatenate all the letters for a single group
together into one list, then go through that list looking for a's,
b's, c's, etc.
Run "do_it(Answer)." to see the answer.
*/
/* start by generating a list of char codes, a thru z. */
a(Char_Code) :-
Char_Code is "a".
z(Char_Code) :-
Char_Code is "z".
/* insert the End char and decrement End */
/* works because we keep putting the new num at the front of the list,
and we're counting down. */
a_to_z(List, Start, End, Result) :-
(
End < Start
-> Result = List
; New_End is End - 1,
a_to_z([End|List], Start, New_End, Result)
).
a_to_z(Result) :-
a(A), z(Z),
a_to_z([], A, Z, Result).
do_it(Answer) :-
phrase_from_file(lines(Ls), "day6-input.txt"),
group_lists(Ls, List_O_Lists),
sum_answers(List_O_Lists, Answer).
/* sum_answers(List_O_Lists, Sum, Result) */
sum_answers([], Result, Result).
sum_answers([List|Rest_Lists], Sum, Result) :-
questions_answered(List, Num),
New_Sum is Sum + Num,
sum_answers(Rest_Lists, New_Sum, Result).
sum_answers(List_O_Lists, Result) :-
sum_answers(List_O_Lists, 0, Result).
/* questions_answered(List, Questions, Count, Result) */
questions_answered(_, [], Result, Result).
questions_answered(List, [Question|Rest_Qs], Count, Result) :-
(
member(Question, List)
-> New_Count is Count + 1,
questions_answered(List, Rest_Qs, New_Count, Result)
; questions_answered(List, Rest_Qs, Count, Result)
).
questions_answered(List, Result) :-
a_to_z(Questions),
questions_answered(List, Questions, 0, Result).
/* file input */
/* Use it with "phrase_from_file(lines(Ls), "INPUT_FN")" */
lines([]) --> call(eos), !.
lines([Line|Lines]) --> line(Line), lines(Lines).
eos([], []).
line([]) --> ( "\n" ; call(eos) ), !.
line([L|Ls]) --> [L], line(Ls).
/*
day6-test is:
abc
a
b
c
ab
ac
etc.
phrase_from_file(lines(Ls), "day6-test.txt").
Ls = [[97, 98, 99], [], [97], [98], [99], [], [97, 98], [97|...], []|...].
OK. Now, want to walk through this list,
having previous line in hand, and then getting the top of the list
peeking into the next item.
If it's null, then we're done.
If it's a list, append to current list, and recurse.
If it's empty-list, add current list to output list,
and recurse with popping the next item as the start of the "line in hand".
group_lists(Line_In_Hand, Next, Remaining, Input, Result)
group_lists/2 is the interface.
Result will be in reverse-order to the input.
Had to add a blank line at end of input file.
This was sort of annoying and ugly because of the special-case
initial condition and ending-condition.
*/
group_lists(Line_In_Hand, _, [], Input, Result) :-
Result = [Line_In_Hand|Input].
group_lists(Line_In_Hand, Next, [Head_Rem|Tail_Rem], Input, Result) :-
(
length(Next, Len),
Len > 0
-> append(Line_In_Hand, Next, New_List),
group_lists(New_List, Head_Rem, Tail_Rem, Input, Result)
;
group_lists([], Head_Rem, Tail_Rem, [Line_In_Hand|Input], Result)
).
/* bootstrap it by picking off first two lines of Input */
/* need car and cdr from prior work */
car([X|_],X).
cdr([_|Y],Y).
group_lists(Input, Result) :-
car(Input, Line_In_Hand),
cdr(Input, Rem1),
car(Rem1, Next),
cdr(Rem1, Remainder),
group_lists(Line_In_Hand, Next, Remainder, [], Result).