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

  • proved_unglue@programming.dev
    link
    fedilink
    arrow-up
    1
    ·
    3 months ago

    Kotlin

    No 💜 for Kotlin here?

    import kotlin.math.abs
    
    fun part1(input: String): Int {
        val diffs: MutableList<Int> = mutableListOf()
        val pair = parse(input)
        pair.first.sort()
        pair.second.sort()
        pair.first.forEachIndexed { idx, num ->
            diffs.add(abs(num - pair.second[idx]))
        }
        return diffs.sum()
    }
    
    fun part2(input: String): Int {
        val pair = parse(input)
        val frequencies = pair.second.groupingBy { it }.eachCount()
        var score = 0
        pair.first.forEach { num ->
            score += num * frequencies.getOrDefault(num, 0)
        }
        return score
    }
    
    private fun parse(input: String): Pair<MutableList<Int>, MutableList<Int>> {
        val left: MutableList<Int> = mutableListOf()
        val right: MutableList<Int> = mutableListOf()
        input.lines().forEach { line ->
            if (line.isNotBlank()) {
                val parts = line.split("\\s+".toRegex())
                left.add(parts[0].toInt())
                right.add(parts[1].toInt())
            }
        }
        return left to right
    }
    
    • the_beber@lemm.ee
      link
      fedilink
      English
      arrow-up
      0
      ·
      edit-2
      3 months ago

      I have another Kotlin (albeit similar) solution:

      import kotlin.math.abs
      
      fun main() {
      
          fun getLists(input: List<String>): Pair<List<Int>, List<Int>> {
              val unsortedPairs = input.map {
                  it.split("   ").map { it.toInt() }
              }
      
              val listA = unsortedPairs.map { it.first() }
              val listB = unsortedPairs.map { it.last() }
              return Pair(listA, listB)
          }
      
          fun part1(input: List<String>): Int {
              val (listA, listB) = getLists(input)
      
              return listA.sorted().zip(listB.sorted()).sumOf { abs(it.first - it.second) }
          }
      
          fun part2(input: List<String>): Int {
              val (listA, listB) = getLists(input)
      
              return listA.sumOf { number ->
                  number * listB.count { it == number }
              }
          }
      
          // Or read a large test input from the `src/Day01_test.txt` file:
          val testInput = readInput("Day01_test")
          check(part1(testInput) == 11)
          check(part2(testInput) == 31)
      
          // Read the input from the `src/Day01.txt` file.
          val input = readInput("Day01")
          part1(input).println()
          part2(input).println()
      }
      
      

      It’s a bit more compact. (If you take out the part that actually calls the functions on the (test-)input.)

      • proved_unglue@programming.dev
        link
        fedilink
        arrow-up
        1
        ·
        3 months ago

        Thanks! I like the Pair destruction and zip().sumOf() approach. I’m relatively new to Kotlin, so this is a good learning experience. 😅

  • lwhjp@lemmy.sdf.org
    link
    fedilink
    arrow-up
    1
    ·
    3 months 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
    
  • Sleepless One@lemmy.ml
    link
    fedilink
    English
    arrow-up
    0
    arrow-down
    1
    ·
    edit-2
    3 months ago

    Rust

    I’m doing it in Rust again this year. I stopped keeping up with it after day 3 last year, so let’s hope I last longer this time around.

    Solution Spoiler Alert
    use std::collections::HashMap;
    
    use crate::utils::read_lines;
    
    pub fn solution1() {
        let (mut id_list1, mut id_list2) = get_id_lists();
    
        id_list1.sort();
        id_list2.sort();
    
        let total_distance = id_list1
            .into_iter()
            .zip(id_list2)
            .map(|(left, right)| (left - right).abs())
            .sum::<i32>();
    
        println!("Total distance = {total_distance}");
    }
    
    pub fn solution2() {
        let (id_list1, id_list2) = get_id_lists();
    
        let id_count_map = id_list2
            .into_iter()
            .fold(HashMap::<_, i32>::new(), |mut map, id| {
                *map.entry(id).or_default() += 1i32;
    
                map
            });
    
        let similarity_score = id_list1
            .into_iter()
            .map(|id| id * id_count_map.get(&id).copied().unwrap_or_default())
            .sum::<i32>();
    
        println!("Similarity score = {similarity_score}");
    }
    
    fn get_id_lists() -> (Vec<i32>, Vec<i32>) {
        read_lines("src/day1/input.txt")
            .map(|line| {
                let mut ids = line.split_whitespace().map(|id| {
                    id.parse::<i32>()
                        .expect("Ids from input must be valid integers")
                });
    
                (
                    ids.next().expect("First Id on line must be present"),
                    ids.next().expect("Second Id on line must be present"),
                )
            })
            .unzip()
    }
    

    I’m keeping my solutions up on GitHub.