Indie game developer 🇨🇦

Working on some games for game jams in my free time

Admin of programming.dev and frontend developer for sublinks

Account has automation for some scheduled posts

Site: https://ategon.dev/ Socials: https://ategon.carrd.co/

  • 36 Posts
  • 36 Comments
Joined 3 years ago
cake
Cake day: June 8th, 2023

help-circle













  • Alright ive modded you

    Heres my copy paste for the days (every day I switch the day and the title at the top (if I send it before the challenge drops I just do insert name here and then edit it later). When https://adventofcode.com/2023/stats hits 100 for both nums then I unlock the thread and put an edit at the bottom saying its unlocked

    (text here is slightly different since 0.19 dropped now so my warning about that is gone)

    # Day 15: Lens Library
    
    ## 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://topaz.github.io/paste/ if you prefer sending it through a URL
    
    ## FAQ
    - What is this?: Here is a post with a large amount of details: https://programming.dev/post/6637268
    - Where do I participate?: https://adventofcode.com/
    - Is there a leaderboard for the community?: We have a programming.dev leaderboard with the info on how to join in this post: https://programming.dev/post/6631465
    
    ---
    
    🔒 Thread is locked until there's at least 100 2 star entries on the global leaderboard
    

    I also add a link to the new post on the sidebar calendar when I post it

    Title is in the format

    🎄 - 2023 DAY 15 SOLUTIONS -🎄

    The title emojis ive been rotating through 7 different ones based on the day of the week, can see past days for ones ive used or you can do your own thing

    You should get options in the format

    When clicking on the three dots on a post (bar the local pin since thats admins only). Community pin pins it / unpins it and the lock locks / unlocks the thread to prevent people from posting in it

    Will unmod myself from here after I see its going fine

    (If I dont get a reply back by the stats hitting 100 for both puzzles today then ill just post the megathread to catch it for today)



  • For modding in general, baseline is checking and handling reports made by users. In addition to that though there can be looking over posts in the instance to make sure none break the rules (sometimes theres stuff like off topic posts made that arent reported)

    This community specifically in addition to the above has the solution threads that would require to be posted when the new puzzle drops while AoC runs throughout december

    Daily tasks:

    • checking reports once a day or something similar and dealing with them
    • while AoC is running at midnight ET post a solution megathread and lock it. When the two numbers for the day at https://adventofcode.com/2023/stats get above 100 unlock it (done to prevent cheating on the global leaderboard, only the first 100 scores count there). Usually takes at most 30 mins to reach 100, was much shorter in the early days of the month





  • The issue with that and reason why AoC doesnt use that for the leaderboard is they dont have access to the code people write, just the final result

    Adding that as an option would mean having something that takes into account differences in base runtimes of code for different languages (e.g. scripting languages taking longer) so that its feasible to code it in anything, and having the ability to execute many different kinds of code which can be a pain to set up (and would mean youre then running arbitrary code unless you sandbox it)

    I used that as the way to rank people in !challenges@programming.dev when I was running that and its been on hiatus for awhile due to the effort needed to run it since I havent had time due to building up things in the instance such as !pangora@programming.dev

    It could work if self reported but then its easy to cheat










  • JavaScript

    Ended up misreading the instructions due to trying to go fast. Built up a system to compare hand values like its poker before I realized its not poker

    Likely last day im going to be able to write code for due to exams coming up

    Code Link

    Code Block
    // Part 1
    // ======
    
    function part1(input) {
      const lines = input.replaceAll("\r", "").split("\n");
      const hands = lines.map((line) => line.split(" "));
    
      const sortedHands = hands.sort((a, b) => {
        const handA = calculateHandValue(a[0]);
        const handB = calculateHandValue(b[0]);
    
        if (handA > handB) {
          return -1;
        } else if (handA < handB) {
          return 1;
        } else {
          for (let i = 0; i < 5; i++) {
            const handACard = convertToNumber(a[0].split("")[i]);
            const handBCard = convertToNumber(b[0].split("")[i]);
            if (handACard > handBCard) {
              return 1;
            } else if (handACard < handBCard) {
              return -1;
            }
          }
        }
      });
    
      return sortedHands
        .filter((hand) => hand[0] != "")
        .reduce((acc, hand, i) => {
          return acc + hand[1] * (i + 1);
        }, 0);
    }
    
    function convertToNumber(card) {
      switch (card) {
        case "A":
          return 14;
        case "K":
          return 13;
        case "Q":
          return 12;
        case "J":
          return 11;
        case "T":
          return 10;
        default:
          return parseInt(card);
      }
    }
    
    function calculateHandValue(hand) {
      const dict = {};
    
      hand.split("").forEach((card) => {
        if (dict[card]) {
          dict[card] += 1;
        } else {
          dict[card] = 1;
        }
      });
    
      // 5
      if (Object.keys(dict).length === 1) {
        return 1;
      }
    
      // 4
      if (Object.keys(dict).filter((key) => dict[key] === 4).length === 1) {
        return 2;
      }
    
      // 3 + 2
      if (
        Object.keys(dict).filter((key) => dict[key] === 3).length === 1 &&
        Object.keys(dict).filter((key) => dict[key] === 2).length === 1
      ) {
        return 3;
      }
    
      // 3
      if (Object.keys(dict).filter((key) => dict[key] === 3).length === 1) {
        return 4;
      }
    
      // 2 + 2
      if (Object.keys(dict).filter((key) => dict[key] === 2).length === 2) {
        return 5;
      }
    
      // 2
      if (Object.keys(dict).filter((key) => dict[key] === 2).length === 1) {
        return 6;
      }
    
      return 7;
    }
    
    // Part 2
    // ======
    
    function part2(input) {
      const lines = input.replaceAll("\r", "").split("\n");
      const hands = lines.map((line) => line.split(" "));
    
      const sortedHands = hands.sort((a, b) => {
        const handA = calculateHandValuePart2(a[0]);
        const handB = calculateHandValuePart2(b[0]);
    
        if (handA > handB) {
          return -1;
        } else if (handA < handB) {
          return 1;
        } else {
          for (let i = 0; i < 5; i++) {
            const handACard = convertToNumberPart2(a[0].split("")[i]);
            const handBCard = convertToNumberPart2(b[0].split("")[i]);
            if (handACard > handBCard) {
              return 1;
            } else if (handACard < handBCard) {
              return -1;
            }
          }
        }
      });
    
      return sortedHands
        .filter((hand) => hand[0] != "")
        .reduce((acc, hand, i) => {
          console.log(acc, hand, i + 1);
          return acc + hand[1] * (i + 1);
        }, 0);
    }
    
    function convertToNumberPart2(card) {
      switch (card) {
        case "A":
          return 14;
        case "K":
          return 13;
        case "Q":
          return 12;
        case "J":
          return 1;
        case "T":
          return 10;
        default:
          return parseInt(card);
      }
    }
    
    function calculateHandValuePart2(hand) {
      const dict = {};
    
      let jokers = 0;
    
      hand.split("").forEach((card) => {
        if (card === "J") {
          jokers += 1;
          return;
        }
        if (dict[card]) {
          dict[card] += 1;
        } else {
          dict[card] = 1;
        }
      });
    
      // 5
      if (jokers === 5 || Object.keys(dict).length === 1) {
        return 1;
      }
    
      // 4
      if (
        jokers === 4 ||
        (jokers === 3 &&
          Object.keys(dict).filter((key) => dict[key] === 1).length >= 1) ||
        (jokers === 2 &&
          Object.keys(dict).filter((key) => dict[key] === 2).length === 1) ||
        (jokers === 1 &&
          Object.keys(dict).filter((key) => dict[key] === 3).length === 1) ||
        Object.keys(dict).filter((key) => dict[key] === 4).length === 1
      ) {
        return 2;
      }
    
      // 3 + 2
      if (
        (Object.keys(dict).filter((key) => dict[key] === 3).length === 1 &&
          Object.keys(dict).filter((key) => dict[key] === 2).length === 1) ||
        (Object.keys(dict).filter((key) => dict[key] === 2).length === 2 &&
          jokers === 1)
      ) {
        return 3;
      }
    
      // 3
      if (
        Object.keys(dict).filter((key) => dict[key] === 3).length === 1 ||
        (Object.keys(dict).filter((key) => dict[key] === 2).length === 1 &&
          jokers === 1) ||
        (Object.keys(dict).filter((key) => dict[key] === 1).length >= 1 &&
          jokers === 2) ||
        jokers === 3
      ) {
        return 4;
      }
    
      // 2 + 2
      if (
        Object.keys(dict).filter((key) => dict[key] === 2).length === 2 ||
        (Object.keys(dict).filter((key) => dict[key] === 2).length === 1 &&
          jokers === 1)
      ) {
        return 5;
      }
    
      // 2
      if (
        Object.keys(dict).filter((key) => dict[key] === 2).length === 1 ||
        jokers
      ) {
        return 6;
      }
    
      return 7;
    }
    
    export default { part1, part2 };
    
    



  • [JavaScript] Relatively easy one today

    Paste

    Part 1
    function part1(input) {
      const split = input.split("\n");
      const times = split[0].match(/\d+/g).map((x) => parseInt(x));
      const distances = split[1].match(/\d+/g).map((x) => parseInt(x));
    
      let sum = 0;
    
      for (let i = 0; i < times.length; i++) {
        const time = times[i];
        const recordDistance = distances[i];
    
        let count = 0;
    
        for (let j = 0; j < time; j++) {
          const timePressed = j;
          const remainingTime = time - j;
    
          const travelledDistance = timePressed * remainingTime;
    
          if (travelledDistance > recordDistance) {
            count++;
          }
        }
    
        if (sum == 0) {
          sum = count;
        } else {
          sum = sum * count;
        }
      }
    
      return sum;
    }
    
    Part 2
    function part2(input) {
      const split = input.split("\n");
      const time = parseInt(split[0].split(":")[1].replace(/\s/g, ""));
      const recordDistance = parseInt(split[1].split(":")[1].replace(/\s/g, ""));
    
      let count = 0;
    
      for (let j = 0; j < time; j++) {
        const timePressed = j;
        const remainingTime = time - j;
    
        const travelledDistance = timePressed * remainingTime;
    
        if (travelledDistance > recordDistance) {
          count++;
        }
      }
    
      return count;
    }
    

    Was a bit late with posting the solution thread and solving this since I ended up napping until 2am, if anyone notices theres no solution thread and its after the leaderboard has been filled (can check from the stats page if 100 people are done) feel free to start one up (I just copy paste the text in each of them)



  • [JavaScript] Well that was by far the hardest out of all of the days, part 1 was relatively fine but part 2 took me awhile of trying different things

    Ended up solving it by working backwards by trying different location values and seeing if that can become a valid seed. Takes around 3 secs to compute the answer.

    Link to code

    Part 1 Code Block
    // Part 1
    // ======
    
    function part1(input) {
      const split = input.split("\r\n\r\n");
    
      let pastValues = split[0].match(/\d+/g).map((x) => parseInt(x));
      let currentValues = [];
    
      for (const section of split.slice(1)) {
        for (const line of section.split("\r\n")) {
          const values = line.match(/\d+/g)?.map((x) => parseInt(x));
    
          if (!values) {
            continue;
          }
    
          const sourceStart = values[1];
          const destinationStart = values[0];
          const length = values[2];
    
          for (let i = 0; i < pastValues.length; i++) {
            if (
              pastValues[i] >= sourceStart &&
              pastValues[i] < sourceStart + length
            ) {
              currentValues.push(destinationStart + pastValues[i] - sourceStart);
              pastValues.splice(i, 1);
              i--;
            }
          }
        }
    
        for (let i = 0; i < pastValues.length; i++) {
          currentValues.push(pastValues[i]);
        }
    
        pastValues = [...currentValues];
        currentValues = [];
      }
    
      return Math.min(...pastValues);
    }
    
    Part 2 Code Block
    // Part 2
    // ======
    
    function part2(input) {
      const split = input.split("\r\n\r\n");
    
      let seeds = split[0].match(/\d+/g).map((x) => parseInt(x));
      seeds = seeds
        .filter((x, i) => i % 2 == 0)
        .map((x, i) => [x, seeds[i * 2 + 1]]);
    
      const maps = split
        .slice(1)
        .map((x) => {
          const lines = x.split("\r\n");
          return lines
            .map((x) => x.match(/\d+/g)?.map((x) => parseInt(x)))
            .filter((x) => x);
        })
        .reverse();
    
      for (let i = 0; true; i++) {
        let curValue = i;
    
        for (const map of maps) {
          for (const line of map) {
            const sourceStart = line[1];
            const destinationStart = line[0];
            const length = line[2];
    
            if (
              curValue >= destinationStart &&
              curValue < destinationStart + length
            ) {
              curValue = sourceStart + curValue - destinationStart;
              break;
            }
          }
        }
    
        for (const [seedRangeStart, seedRangeLength] of seeds) {
          if (
            curValue >= seedRangeStart &&
            curValue < seedRangeStart + seedRangeLength
          ) {
            return i;
          }
        }
      }
    }
    


  • [JavaScript] Swapped over to javascript from rust since I want to also practice some js. Managed to get part 1 in 4 minutes and got top 400 on the global leaderboard. Second part took a bit longer and took me 13 mins since I messed up by originally trying to append to the card array. (eventually swapped to keeping track of amounts in a separate array)

    Part 1
    // Part 1
    // ======
    
    function part1(input) {
      const lines = input.split("\n");
      let sum = 0;
    
      for (const line of lines) {
        const content = line.split(":")[1];
        const winningNums = content.split("|")[0].match(/\d+/g);
        const myNums = content.split("|")[1].match(/\d+/g);
    
        let cardSum = 0;
    
        for (const num of winningNums) {
          if (myNums.includes(num)) {
            if (cardSum == 0) {
              cardSum = 1;
            } else {
              cardSum = cardSum * 2;
            }
          }
        }
    
        sum = sum + cardSum;
      }
    
      return sum;
    }
    
    Part 2
    // Part 2
    // ======
    
    function part2(input) {
      let lines = input.split("\n");
      let amount = Array(lines.length).fill(1);
    
      for (const [i, line] of lines.entries()) {
        const content = line.split(":")[1];
        const winningNums = content.split("|")[0].match(/\d+/g);
        const myNums = content.split("|")[1].match(/\d+/g);
    
        let cardSum = 0;
    
        for (const num of winningNums) {
          if (myNums.includes(num)) {
            cardSum += 1;
          }
        }
    
        for (let j = 1; j <= cardSum; j++) {
          if (i + j >= lines.length) {
            break;
          }
          amount[i + j] += amount[i];
        }
      }
    
      return lines.reduce((acc, line, i) => {
        return acc + amount[i];
      }, 0);
    }
    

    Code Link



  • [Rust] Harder one today, for part 1 I ended up getting stuck for a bit since I wasnt taking numbers at the end of lines into account and in part 2 I defined my gears vector in the wrong spot and spent a bit debugging that

    Code

    (lemmy removes some chars, all chars are in code link)

    use std::fs;
    
    fn part1(input: String) -> u32 {
        let lines = input.lines().collect::>();
        let mut sum = 0;
    
        for i in 0..lines.len() {
            let mut num = 0;
            let mut valid = false;
            let chars = lines[i].chars().collect::>();
    
            for j in 0..chars.len() {
                let character = chars[j];
                let parts = ['*', '#', '+', '$', '/', '%', '=', '-', '&', '@'];
    
                if character.is_digit(10) {
                    num = num * 10 + character.to_digit(10).unwrap();
    
                    if i > 0 {
                        if parts.contains(&lines[i - 1].chars().collect::>()[j]) {
                            valid = true;
                        }
    
                        if j > 0 {
                            if parts.contains(&lines[i - 1].chars().collect::>()[j - 1]) {
                                valid = true;
                            }
                        }
    
                        if j < chars.len() - 1 {
                            if parts.contains(&lines[i - 1].chars().collect::>()[j + 1]) {
                                valid = true;
                            }
                        }
                    }
    
                    if i < lines.len() - 1 {
                        if parts.contains(&lines[i + 1].chars().collect::>()[j]) {
                            valid = true;
                        }
    
                        if j > 0 {
                            if parts.contains(&lines[i + 1].chars().collect::>()[j - 1]) {
                                valid = true;
                            }
                        }
    
                        if j < chars.len() - 1 {
                            if parts.contains(&lines[i + 1].chars().collect::>()[j + 1]) {
                                valid = true;
                            }
                        }
                    }
    
                    if j > 0 {
                        if parts.contains(&lines[i].chars().collect::>()[j - 1]) {
                            valid = true;
                        }
                    }
    
                    if j < chars.len() - 1 {
                        if parts.contains(&lines[i].chars().collect::>()[j + 1]) {
                            valid = true;
                        }
                    }
                }
                else {
                    if valid == true {
                        sum += num;
                    }
    
                    num = 0;
                    valid = false;
                }
    
                if j == chars.len() - 1 {
                    if valid == true {
                        sum += num;
                    }
    
                    num = 0;
                    valid = false;
                }
            }
        }
    
        return sum;
    }
    
    fn part2(input: String) -> u32 {
        let lines = input.lines().collect::>();
        let mut gears: Vec<(usize, usize, u32)> = Vec::new();
        let mut sum = 0;
    
        for i in 0..lines.len() {
            let mut num = 0;
            let chars = lines[i].chars().collect::>();
            let mut pos: (usize, usize) = (0, 0);
            let mut valid = false;
    
            for j in 0..chars.len() {
                let character = chars[j];
                let parts = ['*'];
    
                if character.is_digit(10) {
                    num = num * 10 + character.to_digit(10).unwrap();
    
                    if i > 0 {
                        if parts.contains(&lines[i - 1].chars().collect::>()[j]) {
                            valid = true;
                            pos = (i - 1, j);
                        }
    
                        if j > 0 {
                            if parts.contains(&lines[i - 1].chars().collect::>()[j - 1]) {
                                valid = true;
                                pos = (i - 1, j - 1);
                            }
                        }
    
                        if j < chars.len() - 1 {
                            if parts.contains(&lines[i - 1].chars().collect::>()[j + 1]) {
                                valid = true;
                                pos = (i - 1, j + 1);
                            }
                        }
                    }
    
                    if i < lines.len() - 1 {
                        if parts.contains(&lines[i + 1].chars().collect::>()[j]) {
                            valid = true;
                            pos = (i + 1, j);
                        }
    
                        if j > 0 {
                            if parts.contains(&lines[i + 1].chars().collect::>()[j - 1]) {
                                valid = true;
                                pos = (i + 1, j - 1);
                            }
                        }
    
                        if j < chars.len() - 1 {
                            if parts.contains(&lines[i + 1].chars().collect::>()[j + 1]) {
                                valid = true;
                                pos = (i + 1, j + 1);
                            }
                        }
                    }
    
                    if j > 0 {
                        if parts.contains(&lines[i].chars().collect::>()[j - 1]) {
                            valid = true;
                            pos = (i, j - 1);
                        }
                    }
    
                    if j < chars.len() - 1 {
                        if parts.contains(&lines[i].chars().collect::>()[j + 1]) {
                            valid = true;
                            pos = (i, j + 1);
                        }
                    }
                }
                else {
                    if valid == true {
                        let mut current_gear = false;
                        
                        for gear in &gears {
                            if gear.0 == pos.0 && gear.1 == pos.1 {
                                sum += num * gear.2;
                                current_gear = true;
                                break;
                            }
                        }
                        
                        if !current_gear {
                            let tuple_to_push = (pos.0.clone(), pos.1.clone(), num.clone());
                            gears.push((pos.0.clone(), pos.1.clone(), num.clone()));
                        }
                    }
    
                    num = 0;
                    valid = false;
                }
    
                if j == chars.len() - 1 {
                    if valid == true {
                        let mut current_gear = false;
                        
                        for gear in &gears {
                            if gear.0 == pos.0 && gear.1 == pos.1 {
                                sum += num * gear.2;
                                current_gear = true;
                                break;
                            }
                        }
                        
                        if !current_gear {
                            let tuple_to_push = (pos.0.clone(), pos.1.clone(), num.clone());
                            gears.push((pos.0.clone(), pos.1.clone(), num.clone()));
                        }
                    }
    
                    num = 0;
                    valid = false;
                }
            }
        }
    
        return sum;
    }
    
    fn main() {
        let input = fs::read_to_string("data/input.txt").unwrap();
    
        println!("{}", part1(input.clone()));
        println!("{}", part2(input.clone()));
    }
    

    Code Link


  • Rust (Rank 7421/6311) (Time after start 00:32:27/00:35:35)

    Extremely easy part 2 today, I would say easier than part 1 but they share the same sort of framework

    Code Block

    (Note lemmy removed some characters, code link shows them all)

    use std::fs;
    
    fn part1(input: String) -> i32 {
        const RED: i32 = 12;
        const GREEN: i32 = 13;
        const BLUE: i32 = 14;
    
        let mut sum = 0;
    
        for line in input.lines() {
            let [id, content] = line.split(": ").collect::>()[0..2] else { continue };
            let id = id.split(" ").collect::>()[1].parse::().unwrap();
    
            let marbles = content.split("; ").map(|x| { x.split(", ").collect::>() }).collect::>>();
            let mut valid = true;
    
            for selection in marbles {
                for marble in selection {
                    let marble_split = marble.split(" ").collect::>();
                    let marble_amount = marble_split[0].parse::().unwrap();
                    let marble_color = marble_split[1];
    
                    if marble_color == "red" && marble_amount > RED {
                        valid = false;
                        break;
                    }
    
                    if marble_color == "green" && marble_amount > GREEN {
                        valid = false;
                        break;
                    }
    
                    if marble_color == "blue" && marble_amount > BLUE {
                        valid = false;
                        break;
                    }
                }
            }
    
            if !valid {
                continue;
            }
    
            sum += id;
        }
    
        return sum;
    }
    
    fn part2(input: String) -> i32 {
        let mut sum = 0;
    
        for line in input.lines() {
            let [id, content] = line.split(": ").collect::>()[0..2] else { continue };
            let id = id.split(" ").collect::>()[1].parse::().unwrap();
    
            let marbles = content.split("; ").map(|x| { x.split(", ").collect::>() }).collect::>>();
            
            let mut red = 0;
            let mut green = 0;
            let mut blue = 0;
    
            for selection in marbles {
                for marble in selection {
                    let marble_split = marble.split(" ").collect::>();
                    let marble_amount = marble_split[0].parse::().unwrap();
                    let marble_color = marble_split[1];
    
                    if marble_color == "red" && marble_amount > red {
                        red = marble_amount;
                    }
    
                    if marble_color == "green" && marble_amount > green {
                        green = marble_amount;
                    }
    
                    if marble_color == "blue" && marble_amount > blue {
                        blue = marble_amount;
                    }
                }
            }
    
            sum += red * green * blue;
        }
    
        return sum;
    }
    
    fn main() {
        let input = fs::read_to_string("data/input.txt").unwrap();
    
        println!("{}", part1(input.clone()));
        println!("{}", part2(input.clone()));
    }
    

    Code Link