scarecrw's recent activity
-
Comment on The mega-rich are turning their mansions into impenetrable fortresses in ~finance
-
Comment on Søren Torpegaard Lund – Før Vi Går Hjem (2026) in ~music
scarecrw LinkSuper well deserved win! It was a great song and ridiculously well performed. While they didn't win, I was glad to be introduced to Myrkur and spent yesterday listening to this wonderful album:...Super well deserved win! It was a great song and ridiculously well performed.
While they didn't win, I was glad to be introduced to Myrkur and spent yesterday listening to this wonderful album: https://myrkur.bandcamp.com/album/folkesange
-
Comment on A case for increasing computer literacy (but also a rant) in ~tech
scarecrw Link ParentI used a chromebook with linux containers for a long while with great success. I actually bought the original pixelbook for that exact reason. Unfortunately, in every case I've seen, student...I used a chromebook with linux containers for a long while with great success. I actually bought the original pixelbook for that exact reason. Unfortunately, in every case I've seen, student chromebooks are locked down in a manner which prevents this from being used.
-
Comment on A case for increasing computer literacy (but also a rant) in ~tech
scarecrw Link ParentI think at this point the installation process is pretty similar for both (at least when considering mainstream distros). They both usually have a simple "reformat the whole drive and set it up...I think at this point the installation process is pretty similar for both (at least when considering mainstream distros). They both usually have a simple "reformat the whole drive and set it up for me" option, it's just that more people installing Linux are doing so from an existing set up and need to care about dual booting or retaining data. The likelyhood of falling off the happy path just seems higher for Linux.
I think one of the key pieces holding back Linux adoption is the variety in set ups meaning that troubleshooting becomes a hassle of determining what information is relevant for you. The experience of running into an issue, finding a supposed fix, trying it, having things break further, and then being told "oh no, that only works on this other DE, you need to do..." isn't fun, and isn't something you're as likely to run into sticking with windows.
Unfortunately, that problem comes part and parcel with the freedom of choice Linux presents.
-
Comment on What’s a point that you think many people missed? in ~talk
scarecrw Link ParentI think your second point is very true. Though, interestingly, I find its counterpart equally fitting for this thread: Just because your portrayal is intended as a critique, that doesn't absolve...I think your second point is very true. Though, interestingly, I find its counterpart equally fitting for this thread: Just because your portrayal is intended as a critique, that doesn't absolve you of responsibility for taking care in your presentation.
Artists and creators can't be held accountable for every interpretation of their work, but I often think we're kidding ourselves when we count a portrayal as a condemnation because the antihero "got what was coming to them" at the end, ignoring the previous 90% of the work that glamorized their behavior.
I don't know if I fully agree with Truffaut's "No such thing as an anti-war movie" perspective, but I am wary of people exploiting the label of "critique" to avoid addressing the potential impact that different portrayals can have.
-
Comment on Browser puzzle game: enclose.horse in ~games
scarecrw LinkAlright, I've been effectively sniped. Anybody have an idea for solving this? My current thought is to model this as a graph with the horse as the source and the border as a sink and search for a...Alright, I've been effectively sniped. Anybody have an idea for solving this?
My current thought is to model this as a graph with the horse as the source and the border as a sink and search for a cut less than the number of walls, optimizing for the number of nodes remaining connected to the source. This almost matches a min-cost flow problem, but not exactly. It should be able to be modelled as an ILP problem, but I'm hoping there's a better approach I'm not seeing.
-
Comment on Scalable oral exams with an ElevenLabs voice AI agent in ~tech
scarecrw Link ParentI'm ambivalent on this. I've thankfully not had anxiety issues with public speaking or exams myself, but knowing a few people who have experienced panic attacks, they're obviously not in a state...I'm ambivalent on this. I've thankfully not had anxiety issues with public speaking or exams myself, but knowing a few people who have experienced panic attacks, they're obviously not in a state where they would be able demonstrate their understanding of a topic.
On the other hand, I do feel like a very low weighted oral exam that was still a hurdle for course grading makes a lot of sense. I don't think its a substitute for other forms of assessment, but setting a bar of "participate in an informed discussion of the topic you've ostensibly been studying for the past few months" doesn't seem like an unreasonable ask to be awarded a confirmation of completion. Put another way: I wouldn't want to graduate anyone who couldn't hold a discussion about the topic being learned, and it's hard to imagine a way to do that without some form of direct assessment.
-
Comment on A, B, C or D – grades might not say all that much about what students are actually learning in ~humanities
scarecrw LinkI try to avoid commenting when I'm just being negative, so I'll start by saying I do want to see changes to the way student performance is assessed and how that assessment is then perceived and...I try to avoid commenting when I'm just being negative, so I'll start by saying I do want to see changes to the way student performance is assessed and how that assessment is then perceived and used.
With that said, from the vast majority of cases I've seen, attempts to introduce alternative assessment approaches are nothing more than grade inflation. Standards based grading is great, but you still have to be willing to fail students who don't demonstrate mastery. By all means, let's not let a single poor test grade keep a student from eventually succeeding, but having them retake the exact same test is not a method to show growth.
-
Comment on Anyone else using the Zed editor? in ~comp
scarecrw LinkI haven't actually tried it, but based on this post I'm interested in giving it a go. I'll probably still need to keep vscode around for specific uses, but I don't have any attachment to it in...I haven't actually tried it, but based on this post I'm interested in giving it a go. I'll probably still need to keep vscode around for specific uses, but I don't have any attachment to it in general.
Speaking of local LLM use, does anybody have a recommended coding model for trying it out? I gave it a shot a while back, but between fussing with vscode extensions and the poor accuracy:speed ratio I gave up on it.
-
Comment on Day 9: Movie Theater in ~comp.advent_of_code
scarecrw LinkCatching up on the last couple of days. This one went alright, though I was just lazy and figured at ~500 points I could probably get away with an n^3 solution. I believe I could get it to n^2logn...Catching up on the last couple of days. This one went alright, though I was just lazy and figured at ~500 points I could probably get away with an n^3 solution. I believe I could get it to n^2logn without too much trouble if I had some more powerful data structures, but I already felt like a cheated on day 8 already by using a pre-made union-find.
Prolog Solution
:- ['src/util.pl']. :- initialization(main). main:- phrase_from_file(input(Points), 'inputs/day09.txt'), solve_1(Points, Result1), write("Part 1: "), write(Result1), nl, solve_2(Points, Result2), write("Part 2: "), write(Result2), nl, halt. solve_2(Points, Result):- findall((I1, I2, P1, P2), (nth0(I1, Points, P1), nth0(I2, Points, P2), I1 < I2), PointPairs), [H|T] = Points, append(T, [H], ShiftedPoints), maplist([P1, P2, R]>>(R = (P1, P2)), Points, ShiftedPoints, LineSegs), include(valid_part_2_rect(LineSegs), PointPairs, ValidPointPairs), maplist([(_, _, P1, P2), A]>>rectangle_area((P1, P2), A), ValidPointPairs, Areas), max_list(Areas, Result). valid_part_2_rect(LineSegs, (I1, I2, X1-Y1, X2-Y2)):- sort([X1, X2], [MinX, MaxX]), sort([Y1, Y2], [MinY, MaxY]), all(no_intersects_rect(MinX, MaxX, MinY, MaxY), LineSegs). no_intersects_rect(MinX, MaxX, MinY, MaxY, (X1-Y1, X2-Y2)):- (X1 =< MinX, X2 =< MinX), !. no_intersects_rect(MinX, MaxX, MinY, MaxY, (X1-Y1, X2-Y2)):- (Y1 =< MinY, Y2 =< MinY), !. no_intersects_rect(MinX, MaxX, MinY, MaxY, (X1-Y1, X2-Y2)):- (X1 >= MaxX, X2 >= MaxX), !. no_intersects_rect(MinX, MaxX, MinY, MaxY, (X1-Y1, X2-Y2)):- (Y1 >= MaxY, Y2 >= MaxY), !. solve_1(Points, Result):- findall((P1, P2), (member(P1, Points), member(P2, Points)), PointPairs), maplist(rectangle_area, PointPairs, Areas), max_list(Areas, Result). rectangle_area((X1-Y1, X2-Y2), Area):- Area is (abs(X2 - X1) + 1) * (abs(Y2 - Y1) + 1). input([Point|Rest]) --> point_dcg(Point), "\n", input(Rest). input([Point]) --> point_dcg(Point). point_dcg(Point) --> number_dcg(X), ",", number_dcg(Y), { Point = X-Y }. -
Comment on Day 8: Playground in ~comp.advent_of_code
scarecrw LinkCatching up (poorly) on the last couple of days. I found a union-find pack which took out most of the hard work, though the rest of my code is still terribly inefficient. Oh well, just gotta keep...Catching up (poorly) on the last couple of days. I found a union-find pack which took out most of the hard work, though the rest of my code is still terribly inefficient. Oh well, just gotta keep the momentum going for now.
Prolog Solution
:- ['src/util.pl']. :- initialization(main). :- use_module(library(record)). :- use_module(library(union_find)). :- record point(x:integer=0, y:integer=0, z:integer=0). main:- phrase_from_file(input(Points), 'inputs/day08.txt'), Merges = 1000, findall((D, P1, P2), point_pair(Points, P1, P2, D), PointPairs), sort(PointPairs, PointPairs1), maplist([(_, P1, P2), R]>>(nth1(I, Points, P1), nth1(J, Points, P2), R = (I, J)), PointPairs1, PointPairs2), solve_1(Points, PointPairs2, Merges, Result1), write("Part 1: "), write(Result1), nl, solve_2(Points, PointPairs2, Result2), write("Part 2: "), write(Result2), nl, halt. solve_1(Points, PointPairs, Merges, Result):- take(Merges, PointPairs, PointPairs1), length(Points, N), union_find(UF, N), maplist([(P1, P2)]>>(union(UF, P1, P2)), PointPairs1), disjoint_sets(UF, DS), maplist(length, DS, Lengths), sort(Lengths, Lengths1), reverse(Lengths1, Lengths2), take(3, Lengths2, ToMult), prod_list(ToMult, Result). solve_2(Points, PointPairs, Result):- length(Points, N), union_find(UF, N), solve_2_rec(UF, PointPairs, (A, B)), nth1(A, Points, P1), nth1(B, Points, P2), point_x(P1, X1), point_x(P2, X2), Result is X1 * X2. solve_2_rec(UF, [(P1, P2)|_], LastPair):- disjoint_sets(UF, DS), length(DS, L), L == 2, find(UF, P1, R1), find(UF, P2, R2), R1 =\= R2, LastPair = (P1, P2). solve_2_rec(UF, [(P1, P2)|Pairs], LastPair):- union(UF, P1, P2), solve_2_rec(UF, Pairs, LastPair). point_pair(Points, P1, P2, Distance):- member(P1, Points), member(P2, Points), distance_sq(P1, P2, Distance), Distance =\= 0, point_x(P1, X1), point_y(P1, Y1), point_z(P1, Z1), point_x(P2, X2), point_y(P2, Y2), point_z(P2, Z2), (X1 > X2 ; (X1 == X2, Y1 > Y2) ; (X1 == X2, Y1 == Y2, Z1 > Z2)). distance_sq(Point1, Point2, Distance):- point_x(Point1, X1), point_y(Point1, Y1), point_z(Point1, Z1), point_x(Point2, X2), point_y(Point2, Y2), point_z(Point2, Z2), Distance is (X1 - X2)^2 + (Y1 - Y2)^2 + (Z1 - Z2)^2. input([Point|Rest]) --> point_dcg(Point), "\n", input(Rest). input([Point]) --> point_dcg(Point). point_dcg(Point) --> number_dcg(X), ",", number_dcg(Y), ",", number_dcg(Z), { make_point([x(X), y(Y), z(Z)], Point) }. -
Comment on Day 6: Trash Compactor in ~comp.advent_of_code
scarecrw Link ParentThe problem is that when you pass params to operate in part 2, it isn't a numpy array, so when numpy.prod() auto-converts it to one, it defaults the datatype to int32 and overflows. You can fix it...The problem is that when you pass
paramstooperatein part 2, it isn't a numpy array, so whennumpy.prod()auto-converts it to one, it defaults the datatype toint32and overflows. You can fix it withnumpy.prod(params, dtype='uint64').As for the rotation, using
list(zip(*inputs))[::-1]is a neat trick if you want to do the rotations yourself. -
Comment on Day 7: Laboratories in ~comp.advent_of_code
scarecrw (edited )LinkPretty easy day for the problem itself, so I used the opportunity to try a couple new things: DCGs and "Association Lists" (why does every language have to have their own name for this?). I'm not...Pretty easy day for the problem itself, so I used the opportunity to try a couple new things: DCGs and "Association Lists" (why does every language have to have their own name for this?).
I'm not convinced using a DCG for this style of parsing made it any easier (it certainly didn't make it more succinct), but I can certainly see how it could be useful for more advanced parsing.
I have to say, while Prolog is growing on me, I'm still feeling silly writing ~9 lines to update a couple values in a data structure. It's not that it's that hard, I'm just hoping there's a more idiomatic approach I don't know about.
Prolog Solution
:- initialization(main). main:- phrase_from_file(input(StartingColumn, Rows), 'inputs/day07.txt'), list_to_assoc([StartingColumn-1], Beams), foldl(process_line, Rows, (Beams, 0), (TotalBeams, Result1)), assoc_to_values(TotalBeams, BeamCounts), sum_list(BeamCounts, Result2), format('Part 1: ~w~n', [Result1]), format('Part 2: ~w~n', [Result2]), halt. process_line([], State, State). process_line([Splitter|Rest], (Beams, Splits), (ResBeams, Splits1)):- get_assoc(Splitter, Beams, _), process_line(Rest, (Beams, Splits), (RecBeams, RecSplits)), split_beams(Splitter, RecBeams, ResBeams), succ(RecSplits, Splits1). process_line([_|Rest], State, ResultingState):- process_line(Rest, State, ResultingState). split_beams(Splitter, Beams, ResBeams):- get_assoc(Splitter, Beams, Count), succ(L, Splitter), succ(Splitter, R), (get_assoc(L, Beams, LCount) ; LCount = 0), (get_assoc(R, Beams, RCount) ; RCount = 0), del_assoc(Splitter, Beams, _, Beams1), LCountNew is LCount + Count, RCountNew is RCount + Count, put_assoc(L, Beams1, LCountNew, Beams2), put_assoc(R, Beams2, RCountNew, ResBeams). % Parsing input(StartingColumn, Rows) --> starting_column(StartingColumn, 0), "\n", rows(Rows). starting_column(StartingColumn, Idx) --> ".", { succ(Idx, Idx1) }, starting_column(StartingColumn, Idx1). starting_column(StartingColumn, StartingColumn) --> "S", rest_of_line. rest_of_line --> ".", rest_of_line ; []. rows([Row]) --> row(Row, 0). rows([Row|Rest]) --> row(Row, 0), "\n", rows(Rest). row(Row, Idx) --> ".", { succ(Idx, Idx1) }, row(Row, Idx1). row(Row, Idx) --> "^", { succ(Idx, Idx1) }, row(RowRest, Idx1), {Row = [Idx|RowRest]}. row([], _) --> []. -
Comment on Day 6: Trash Compactor in ~comp.advent_of_code
scarecrw (edited )LinkAnother day down, though this was mostly just a bit annoying. I did add a few useful tools to my saved utilities: transpose/2, split_list/3, and prod_list/2. Not sure if they'll be useful in...Another day down, though this was mostly just a bit annoying. I did add a few useful tools to my saved utilities:
transpose/2,split_list/3, andprod_list/2. Not sure if they'll be useful in future days, but I thought they were general enough to keep.Prolog Solution
:- ['src/util.pl']. :- initialization(main). main:- read_file_to_strings('inputs/day06.txt', Lines), parse_input_1(Lines, Vals, Ops), maplist(solve, Ops, Vals, Nums), sumlist(Nums, Result1), write("Part 1: "), write(Result1), nl, parse_input_2(Lines, Vals2, Ops2), maplist(solve, Ops2, Vals2, Nums2), sumlist(Nums2, Result2), write("Part 2: "), write(Result2), nl, halt. solve("+", Vals, Result):- sum_list(Vals, Result). solve("*", Vals, Result):- prod_list(Vals, Result). parse_input_1(Lines, Vals, Ops):- maplist([S]>>split_string(S, " ", " "), Lines, SplitLines), last(SplitLines, Ops), append(ValStrings, [Ops], SplitLines), maplist(maplist(string_number), ValStrings, ValRows), transpose(ValRows, Vals). parse_input_2(Lines, Vals, Ops):- last(Lines, OpsString), append(OrigValStrings, [OpsString], Lines), split_string(OpsString, " ", " ", Ops), maplist(string_chars, OrigValStrings, Chars), transpose(Chars, FlippedChars), maplist(exclude(=(' ')), FlippedChars, FilteredChars), maplist([C, S]>>string_chars(S, C), FilteredChars, FlippedStrings), split_list(FlippedStrings, "", ValStrings), maplist(maplist(string_number), ValStrings, Vals).Utilities
transpose([], []). transpose([L], R):- maplist([X, V]>>(V = [X]), L, R). transpose([H|T], R):- transpose(T, RecResult), maplist([X,Y,Z]>>(Z = [X|Y]), H, RecResult, R). split_list(List, Delimiter, Result):- split_list(List, Delimiter, [], Result). split_list([], _, Acc, [Acc]). split_list([Delimiter], Delimiter, Acc, [Acc, []]). split_list([Delimiter|T], Delimiter, Acc, Result):- split_list(T, Delimiter, [], Result1), Result = [Acc|Result1]. split_list([H|T], Delimiter, Acc, Result):- Acc1 = [H|Acc], split_list(T, Delimiter, Acc1, Result). prod_list(List, Result):- foldl([A,B,C]>>(C is A * B), List, 1, Result). -
Comment on Day 5: Cafeteria in ~comp.advent_of_code
scarecrw (edited )LinkVery much needed a good day after yesterday frustrated me so much. It just seemed like yesterday everything I tried with the language went wrong, and today it fell together nicely. Nothing...Very much needed a good day after yesterday frustrated me so much. It just seemed like yesterday everything I tried with the language went wrong, and today it fell together nicely.
Nothing creative on the algorithmic front; I suppose there may be some efficiency gains to be had on both parts by keeping ranges sorted, but the list was short enough it didn't matter.
Prolog Solution
:- ['src/util.pl']. parse_range(RangeString, [Start, End]):- split_string(RangeString, "-", "", [A, B]), number_string(Start, A), number_string(End, B). in_ranges(Ranges, ID):- member([Start, End], Ranges), between(Start, End, ID). overlap([S1, E1], [S2, E2]):- S1 =< E2, S2 =< E1. merge_range_rangelist(Range, RangeList, Result):- partition(overlap(Range), RangeList, OverlappingRanges, OtherRanges), flatten([Range|OverlappingRanges], EndPoints), min_list(EndPoints, Start), max_list(EndPoints, End), Result = [[Start, End]|OtherRanges]. range_size([A, B], RangeSize):- RangeSize is B - A + 1. main:- Filename = 'inputs/day05.txt', read_file_to_strings(Filename, Lines), append(RangeStrings, [""|IDStrings], Lines), maplist(parse_range, RangeStrings, Ranges), maplist(string_number, IDStrings, IDs), include(in_ranges(Ranges), IDs, FreshIDs), length(FreshIDs, Result1), write("Part 1: "), write(Result1), nl, foldl(merge_range_rangelist, Ranges, [], MergedRanges), maplist(range_size, MergedRanges, RangeSizes), sumlist(RangeSizes, Result2), write("Part 2: "), write(Result2), nl, halt. :- initialization(main).I tried reading up on difference lists and DCGs this afternoon and did not get anywhere with it. I'll have to give it another go with a clearer head.
-
Comment on Day 4: Printing Department in ~comp.advent_of_code
scarecrw (edited )LinkOver two hours to write and over a minute to run... Yesterday I would have said Prolog didn't seem so bad and I was getting a feel for things, today I spent the better part of an hour getting a...Over two hours to write and over a minute to run...
Yesterday I would have said Prolog didn't seem so bad and I was getting a feel for things, today I spent the better part of an hour getting a Moore neighborhood to work.
Real tired and pretty disappointed after this one. Hopefully get a second wind with some free time this weekend.
Prolog Solution
:- ['src/util.pl']. :- table contains_paper/3. contains_paper(Grid, 0, Position):- Position = (RowIndex, ColIndex), nth0(RowIndex, Grid, Row), string_chars(Row, RowChars), nth0(ColIndex, RowChars, Char), Char = '@'. contains_paper(Grid, Step, Position):- succ(Step1, Step), contains_paper(Grid, Step1, Position), not(forkliftable(Grid, Step1, Position)). forkliftable(Grid, Step, Position):- contains_paper(Grid, Step, Position), findall(Pos, neighbor(Position, Pos), Neighbors), count(contains_paper(Grid, Step), Neighbors, NeighborPaper), NeighborPaper < 4. neighbor(Position1, Position2):- Position1 = (Row1, Col1), between(-1, 1, DR), between(-1, 1, DC), (DR, DC) \= (0, 0), Row2 is Row1 + DR, Col2 is Col1 + DC, Position2 = (Row2, Col2). paper_removed(Grid, Step, PaperRemoved):- findall(Pos, contains_paper(Grid, 0, Pos), OriginalPaper), findall(Pos, contains_paper(Grid, Step, Pos), FinalPaper), length(OriginalPaper, OriginalCount), length(FinalPaper, FinalCount), PaperRemoved is OriginalCount - FinalCount. main:- Filename = 'inputs/day04.txt', read_file_to_strings(Filename, Grid), paper_removed(Grid, 1, Result1), write("Part 1: "), write(Result1), nl, paper_removed(Grid, 100, Result2), write("Part 2: "), write(Result2), nl, halt. :- initialization(main). -
Comment on Day 3: Lobby in ~comp.advent_of_code
scarecrw Link ParentI'm hoping someone has an actually clean fix, as I've run into that in the past without much luck. Couple of ideas: Reverse the list, then iterate from 11...0, as list[n:] works fine. Use an...I'm hoping someone has an actually clean fix, as I've run into that in the past without much luck.
Couple of ideas:
- Reverse the list, then iterate from 11...0, as
list[n:]works fine. - Use an in-line conditional
list[:n] if n else list
- Reverse the list, then iterate from 11...0, as
-
Comment on Advent of Code starts tomorrow/tonight! Are you participating? Do you have any specific plans for this year? in ~comp.advent_of_code
scarecrw Link ParentI hope you enjoy it! The days get harder as they progress, and later days often require either improved algorithms or optimizing for the properties if the inputs. Hopefully some edifying...I hope you enjoy it!
The days get harder as they progress, and later days often require either improved algorithms or optimizing for the properties if the inputs. Hopefully some edifying challenges await!
-
Comment on Day 3: Lobby in ~comp.advent_of_code
scarecrw LinkBit of a better day, as I guessed Part 2 so was already planning out the algorithm. My first thought was a DP solution (which napkin-math suggests might have worked?), but figured out a better...Bit of a better day, as I guessed Part 2 so was already planning out the algorithm. My first thought was a DP solution (which napkin-math suggests might have worked?), but figured out a better approach instead. Went back and refactored to add a couple new utilities and make the main solver tail-recursive.
I got spooked at first thinking it might be 2D arrays and realized I'll need to read up to figure out how best to handle that, as it's sure to be coming in the next few days.
Prolog Solution
:- ['src/util.pl']. max_batteries(N, Batteries, Joltage):- max_batteries(N, Batteries, 0, Joltage). max_batteries(0, _, Acc, Acc). max_batteries(N, Batteries, Acc, Joltage):- length(Batteries, L), FrontLength is L - N + 1, take(FrontLength, Batteries, Front), max_list(Front, MaxDigit), nth1(MaxIndex, Front, MaxDigit), drop(MaxIndex, Batteries, Rest), succ(N1, N), Acc1 is Acc + 10 ^ N1 * MaxDigit, max_batteries(N1, Rest, Acc1, Joltage). string_to_digits(String, Digits):- string_chars(String, DigitChars), maplist(char_code, DigitChars, Codes), maplist(plus(-48), Codes, Digits). main:- Filename = 'inputs/day03.txt', read_file_to_strings(Filename, BankStrings), maplist(string_to_digits, BankStrings, Banks), maplist(max_batteries(2), Banks, Joltages), sum_list(Joltages, Result1), write("Part 1: "), write(Result1), nl, maplist(max_batteries(12), Banks, Joltages2), sum_list(Joltages2, Result2), write("Part 2: "), write(Result2), nl, halt. :- initialization(main). -
Comment on Day 2: Gift Shop in ~comp.advent_of_code
scarecrw LinkBrute-forced it again, but learned a lot in doing so! Had one of my first "aha!" moments in using string_concat/3 backwards to both check if one string was a prefix of another and find the suffix...Brute-forced it again, but learned a lot in doing so!
Had one of my first "aha!" moments in using
string_concat/3backwards to both check if one string was a prefix of another and find the suffix that matched. No idea if it's the most efficient approach, but super neat!Prolog Solution
parse_range(RangeString, Range):- split_string(RangeString, "-", "", RangeStrings), maplist(number_string, Range, RangeStrings). find_invalids(IsInvalid, [RangeStart, RangeEnd], Invalids):- numlist(RangeStart, RangeEnd, Nums), include(IsInvalid, Nums, Invalids). is_invalid_1(Num):- number_string(Num, NumString), string_length(NumString, L), PartLength is div(L, 2), sub_string(NumString, 0, PartLength, PartLength, Left), sub_string(NumString, PartLength, PartLength, 0, Right), Left == Right. is_invalid_2(Num):- number_string(Num, NumString), string_length(NumString, L), between(2, L, NumParts), 0 is mod(L, NumParts), Before is div(L, NumParts), sub_string(NumString, 0, Before, _, Part), string_repeat(Part, NumString). string_repeat(_, ""). string_repeat(Part, String):- string_concat(Part, Rest, String), string_repeat(Part, Rest). main:- Filename = 'inputs/day02.txt', read_file_to_string(Filename, Input, []), split_string(Input, ",", "", RangeStrings), maplist(parse_range, RangeStrings, Ranges), maplist(find_invalids(is_invalid_1), Ranges, Invalids), maplist(sum_list, Invalids, InvalidSums), sum_list(InvalidSums, Result1), write("Part 1: "), write(Result1), nl, maplist(find_invalids(is_invalid_2), Ranges, Invalids2), maplist(sum_list, Invalids2, InvalidSums2), sum_list(InvalidSums2, Result2), write("Part 2: "), write(Result2), nl, halt. :- initialization(main).I made a note to learn about records, as right now I'm just using lists for everything.
I've had the chance to get to know the security of some ultra-wealthy people and one thing that's very interesting is just how varied it can be. The pattern I've noticed is that the level of security seems less correlated with wealth, and more correlated with how much of their life is wrapped up in their business. For many of these people, their homes/lives are a business, and security equipment and staff are just a part of the operation like you'd have at an office building.
There's also a split between those who want their security approach to be intimidating and restrictive vs those who treat it more as an obligation. Whenever I hear about bad interactions with the wealthy due to their security, it seems like such an obvious own-goal; pissing off the people you interact with not only earns you a terrible reputation, it's also incredibly stupid from a security perspective.