Day 1: Historian Hysteria

Megathread guidelines

  • Keep top level comments as only solutions, if you want to say something other than a solution put it in a new post. (replies to comments can be whatever)
  • You can send code in code blocks by using three backticks, the code, and then three backticks or use something such as https://blocks.programming.dev if you prefer sending it through a URL

FAQ

  • @SteveDinn@lemmy.ca
    link
    fedilink
    136 minutes ago

    C#

    using System;
    using System.Linq;
    
    public record Point(int X, int Y); 
    
    static class Program
    {
        static async Task Main(string[] args)
        {
            var data = (await ReadInputFromFile("data.txt")).ToArray();
    
            var part1Answer = CalculateTotalDifference(data);
            Console.WriteLine($"Part 1 = {part1Answer}");
    
            var part2Answer = CountFrequencies(data);
            Console.WriteLine($"Part 2 = {part2Answer}");
        }
    
        public static int CountFrequencies(ICollection<Point> points)
        {
            var freq = points
                .GroupBy(p => p.Y)
                .ToDictionary(g => g.Key, g => g.Count());
            return points
                .Sum(p => freq.GetValueOrDefault(p.X, 0) * p.X);
        }
    
        public static int CalculateTotalDifference(ICollection<Point> points)
            => points.OrderBy(p => p.X)
                .Zip(
                    points.OrderBy(p => p.Y),
                    (px, py) => Math.Abs(px.X - py.Y))
                .Sum();
    
        public static readonly char[] Delimiter = new char[] { ' ' };
        public static async Task<IEnumerable<Point>> ReadInputFromFile(string path)
            => (await File.ReadAllLinesAsync(path))
                .Select(l =>
                {
                    var parts = l.Split(
                        Delimiter,
                        StringSplitOptions.TrimEntries | StringSplitOptions.RemoveEmptyEntries);
                    return new Point(int.Parse(parts[0]), int.Parse(parts[1]));
                });
    }
    
  • @sjmulder
    link
    14 hours ago

    JavaScript

    After writing a procedural to-the-point version in C, tried a JavaScript solution too because it’s just perfect for list comprehension. The part 2 search is inefficient but the data size is small.

    Code
    const fs = require("fs");
    const U = require("./util");
    
    const pairs = fs
        .readFileSync(process.argv[2] || process.stdin.fd, "utf8")
        .split("\n")
        .filter(x => x != "")
        .map(x => x.split(/ +/).map(Number));
    
    const ls = pairs.map(x => x[0]); ls.sort();
    const rs = pairs.map(x => x[1]); rs.sort();
    
    const p1 = U.sum(ls.map((l, i) => Math.abs(l - rs[i])));
    const p2 = U.sum(ls.map(l => l * U.count(rs, l)));
    
    console.log("01:", p1, p2);
    

    https://github.com/sjmulder/aoc/blob/master/2024/js/day01.js

  • @LeixB@lemmy.world
    link
    fedilink
    111 hours ago

    Haskell

    import Control.Arrow
    import Control.Monad
    import Data.List
    import Data.Map
    
    part1 [a, b] = sum $ abs <$> zipWith (-) (sort a) (sort b)
    part2 [a, b] = sum $ ap (zipWith (*)) (fmap (flip (findWithDefault 0) (freq b))) a
      where
        freq = fromListWith (+) . fmap (,1)
    
    main = getContents >>= (print . (part1 &&& part2)) . transpose . fmap (fmap read . words) . lines
    
  • @grrgyle@slrpnk.net
    link
    fedilink
    112 hours ago

    TypeScript

    This is for part #2 only.

    import { readFileSync } from 'fs'
    
    const f = readFileSync('./input.txt', 'utf-8')
    const lines = f.split("\n")
    
    let rights = {}
    for (const i in lines) {
    	if (lines[i] == '') { continue }
    
    	const [, right] = lines[i].split(/\s+/)
    	if (rights[right] === undefined) {
    		rights[right] = 0
    	}
    
    	rights[right]++
    }
    
    let ans = 0
    for (const i in lines) {
    	const [left] = lines[i].split(/\s+/)
    	const similarity = rights[left]
    
    	if (similarity) {
    		ans += (Number(left) * rights[left])
    	}
    }
    
    console.dir(ans)
    

    Is it possible to get this more efficient? I would love a way that only required iterating over the list once, but I don’t really have the focus to puzzle it out any less than O(2n) (probably more than that, even, if you count reading in the data…).

  • @morrowind@lemmy.ml
    link
    fedilink
    321 hours ago

    Smalltalk

    day1p12: input    
    	| list1 list2 nums dist sim |
    	
    	list1 := OrderedCollection new.
    	list2 := OrderedCollection new.
    	
    	input linesDo: [ :l |
    		nums := l substrings collect: [ :n | n asInteger ].
    		list1 add: (nums at: 1).
    		list2 add: (nums at: 2).
    	].
    
    	list1 sort.
    	list2 sort.
    	
    	dist := 0.
    	list1 with: list2 do: [ :a :b | dist := dist + (a - b) abs ].
    	
    	sim := list1 sumNumbers: [ :x | x * (list2 occurrencesOf: x) ].
    	
    	^ Array with: dist with: sim.
    
  • @morrowind@lemmy.ml
    link
    fedilink
    1
    edit-2
    23 hours ago

    Crystal

    f = ARGV[0]? ? File.read_lines("input.txt") : test.lines
    list1 = Array(Int32).new(f.size)
    list2 = Array(Int32).new(f.size)
    
    f.each do |l|
    	nums = l.split.map(&.to_i)
    	list1.push(nums[0])
    	list2.push(nums[1])
    end
    
    list1.sort!
    list2.sort!
    
    puts list1.zip(list2).sum{ |l1, l2| (l1 - l2).abs }
    
    puts list1.sum {|x| x * list2.count x}
    
  • @VegOwOtenks@lemmy.world
    link
    fedilink
    English
    123 hours ago

    Python

    ids = """<multiline input string>"""
    ids = [pair.split(" ") for pair in ids.split("\n")]
    left = [int(t[0]) for t in ids]
    right = [int(t[-1]) for t in ids]
    left.sort()
    right.sort()
    print(sum(abs(l - r) for l, r in zip(left, right)))
    
    # 2
    s = 0
    for l in left:
        s += right.count(l) * l
    print(s)
    

    Lost a minute because I forgot about abs .-.

  • @Euro@programming.dev
    link
    fedilink
    21 day ago

    Viml

    I think viml is a very fun language, i like weird languages lol, so this year im doing it in viml while trying to use as many of the original ed/ex commands as i can (:d, :p, :a, :g, …)

    Part 1
    !cp ./puzzle1 ./puzzle1.editing
    e ./puzzle1.editing
    
    1,$sort
    let row1 = []
    
    g/^\d/let row1 = add(row1, str2nr(expand("<cword>"))) | norm 0dw
    1d
    1,$sort
    g/^\d/execute 'norm cc' .. string(abs(expand("<cword>") - row1[line('.') - 1]))
    
    $a|---ANSWER---
    0
    .
    1,$-1g/^\d/call setline("$", str2nr(getline("$")) + str2nr(expand("<cword>")))
    
    Part 2
    read ./puzzle1
    
    let cnt = 0
    g/^\d/let cnt += expand("<cword>") *
                \ searchcount(#{pattern: '\s\+' .. expand("<cword>")}).total
    
    echo cnt .. "\n"
    
    w! ./puzzle1.editing
    
  • @vole@lemmy.world
    link
    fedilink
    English
    1
    edit-2
    1 day ago

    Raku

    I’m trying warm up to Raku again.

    Solution

    github

    use v6;
    
    sub MAIN($input) {
        my $file = open $input;
    
        grammar LocationList {
            token TOP { <row>+%"\n" "\n"* }
            token row { <left=.id> " "+ <right=.id> }
            token id { \d+ }
        }
    
        my $locations = LocationList.parse($file.slurp);
        my @rows = $locations<row>.map({ (.<left>.Int, .<right>.Int)});
        my $part-one-solution = (@rows[*;0].sort Z- @rows[*;1].sort)».abs.sum;
        say "part 1: $part-one-solution";
    
        my $rbag = bag(@rows[*;1].sort);
        my $part-two-solution = @rows[*;0].map({ $_ * $rbag{$_}}).sum;
        say "part 2: $part-two-solution";
    }
    

    I’m happy to see that Lemmy no longer eats Raku code.

  • @mykl@lemmy.world
    link
    fedilink
    7
    edit-2
    2 days ago

    Uiua

    For entertainment purposes only, I’ll be trying a solution in Uiua each day until it all gets too much for me…

    $ 3   4
    $ 4   3
    $ 2   5
    $ 1   3
    $ 3   9
    $ 3   3
    ⊜∘⊸≠@\n     # Partition at \n.
    ⊜(⍆∵⋕)⊸≠@\s # Partition at space, parse ints, sort.
    
    &p/+/(⌵-). # Part1 : Get abs differences, sum, print.
    
    &p/+×⟜(/+⍉≡⌕)°⊂ # Part 2 : Count instances, mul out, sum, print.
    
  • bugsmith
    link
    fedilink
    21 day ago

    I’m late to the party, as usual. Damned timezones. This year I’m going to tackle with a small handful of languages, but primarily Elixir and Gleam. This is my first time trying this languages in earnest, so expect some terrible, inefficient and totally unidiomatic code!
    Here’s day one:

    Elixir

    part_one =
      File.read!("input.in")
      |> String.split("\n", trim: true)
      |> Enum.map(fn line ->
        line
        |> String.split()
        |> Enum.map(&String.to_integer/1)
      end)
      |> Enum.reduce({[], []}, fn [first, second], {list1, list2} ->
        {[first | list1], [second | list2]}
      end)
      |> then(fn {list1, list2} ->
        {Enum.sort(list1), Enum.sort(list2)}
      end)
      |> then(fn {list1, list2} ->
        Enum.zip(list1, list2)
        |> Enum.map(fn {x, y} -> abs(x - y) end)
      end)
      |> Enum.sum()
    
    part_two =
      File.read!("input.in")
      |> String.split("\n", trim: true)
      |> Enum.map(fn line ->
        line
        |> String.split()
        |> Enum.map(&String.to_integer/1)
      end)
      |> Enum.reduce({[], []}, fn [first, second], {list1, list2} ->
        {[first | list1], [second | list2]}
      end)
      |> then(fn {list1, list2} ->
        Enum.map(list1, fn line ->
          line * Enum.count(list2, fn x -> x === line end)
        end)
        |> Enum.sum()
      end)
    
    IO.inspect(part_one)
    IO.inspect(part_two)
    
  • Leo Uino
    link
    62 days ago

    Haskell

    Plenty of scope for making part 2 faster, but I think simple is best here. Forgot to sort the lists in the first part, which pushed me waaay off the leaderboard.

    import Data.List
    
    main = do
      [as, bs] <- transpose . map (map read . words) . lines <$> readFile "input01"
      print . sum $ map abs $ zipWith (-) (sort as) (sort bs)
      print . sum $ map (\a -> a * length (filter (== a) bs)) as
    
  • @Rin@lemm.ee
    link
    fedilink
    3
    edit-2
    2 days ago

    TypeScript

    Solution
    import { AdventOfCodeSolutionFunction } from "./solutions";
    
    function InstancesOf(sorted_array: Array<number>, value: number) {
        const index = sorted_array.indexOf(value);
        if(index == -1)
            return 0;
    
        let sum = 1;
    
        for (let array_index = index + 1; array_index < sorted_array.length; array_index++) {
            if(sorted_array[array_index] != value)
                break;
    
            sum += 1;
        }
    
        return sum;
    }
    
    export const solution_1: AdventOfCodeSolutionFunction = (input) => {
        const left: Array<number> = [];
        const right: Array<number> = [];
    
        const lines = input.split("\n");
    
        for (let index = 0; index < lines.length; index++) {
            const element = lines[index].trim();
            if(!element)
                continue;
    
            const leftRight = element.split("   ");
            left.push(Number(leftRight[0]));
            right.push(Number(leftRight[1]));
        }
    
        const numSort = (a: number, b: number) => a - b;
        left.sort(numSort);
        right.sort(numSort);
    
        let sum = 0;
        for (let index = 0; index < left.length; index++) {
            const leftValue = left[index];
            const rightValue = right[index];
    
            sum += Math.abs(leftValue - rightValue);
        }
    
        const part1 = `Part 1: ${sum}`;
    
        sum = 0;
        for (let index = 0; index < left.length; index++) {
            sum += left[index] * InstancesOf(right, left[index]);
        }
    
        const part2 = `Part 2: ${sum}`;
    
        return `${part1}\n${part2}`;
    };
    

    Not the most elegant solution but it works. Decided to reuse the array since it is sorted for both sides.

  • I’m quite inexperienced as a programmer, I learned most of the basic concepts from playing human resource machine and 7 billion humans. After mucking about writing some CLI utilities in Perl and python, I’ve decided to give rust a go.

    Part 1

    Part 2

  • TunaCowboy
    link
    fedilink
    1
    edit-2
    24 hours ago

    python

    I didn’t realize it was december until this afternoon. I’ve generally chosen a new or spartan lang to challenge myself, but I’m going easy mode this year with python and just focusing on meeting the requirement.

    solution
    import aoc
    
    def setup():
        lines = aoc.get_lines(1)
        l = [int(x.split()[0]) for x in lines]
        r = [int(x.split()[1]) for x in lines]
        return (l, r, 0)
    
    def one():
        l, r, acc = setup()
        for p in zip(sorted(l), sorted(r)):
            acc += abs(p[0] - p[1])
        print(acc)
    
    def two():
        l, r, acc = setup()
        for n in l:
            acc += n * r.count(n)
        print(acc)
    
    one()
    two()