16 votes

Day 2: Dive!

Today's problem description: https://adventofcode.com/2021/day/2

Please post your solutions in your own top-level comment. Here's a template you can copy-paste into your comment to format it nicely, with the code collapsed by default inside an expandable section with syntax highlighting (you can replace python with any of the "short names" listed in this page of supported languages):

<details>
<summary>Part 1</summary>

```python
Your code here.
```

</details>

25 comments

  1. Crestwave
    Link
    Quite chill, seems simpler than day 1. Part 1 #!/usr/bin/awk -f /forward/ { x += $2 } /down/ { y += $2 } /up/ { y -= $2 } END { print x * y } Part 2 #!/usr/bin/awk -f /down/ { i += $2 } /up/ { i...

    Quite chill, seems simpler than day 1.

    Part 1
    #!/usr/bin/awk -f
    /forward/ { x += $2 }
    /down/ { y += $2 }
    /up/ { y -= $2 }
    
    END { print x * y }
    
    Part 2
    #!/usr/bin/awk -f
    /down/ { i += $2 }
    /up/ { i -= $2 }
    /forward/ {
    	x += $2
    	y += i * $2
    }
    
    END { print x * y }
    
    10 votes
  2. [4]
    deckard
    Link
    Trying to get better at golfing, day 2. LMK if you have any golf tips, especially for python. Part 1 import sys;x=y=0 for l in sys.stdin: r,M=l.split();m=int(M) if r[0]=='f': x+=m elif r[0]=='d':...

    Trying to get better at golfing, day 2. LMK if you have any golf tips, especially for python.

    Part 1
    import sys;x=y=0
    for l in sys.stdin:
     r,M=l.split();m=int(M)
     if r[0]=='f':
      x+=m
     elif r[0]=='d':
      y+=m
     else:
      y-=m
    print(x*y)
    
    Part 2
    import sys;x=y=a=0
    for l in sys.stdin:
     r,M=l.split();m=int(M)
     if r[0]=='f':
      x+=m;y+=a*m
     elif r[0]=='d':
      a+=m
     else:
      a-=m
    print(x*y)
    
    7 votes
    1. primordial-soup
      (edited )
      Link Parent
      Welcome to Tildes! For golfing, you could prune a few characters by placing the input in a file with a short name and hardcoding it: open("i") in place of sys.stdin. Edit: Even better, I just...

      Welcome to Tildes!

      For golfing, you could prune a few characters by placing the input in a file with a short name and hardcoding it: open("i") in place of sys.stdin.

      Edit: Even better, I just learned you can use open(0) to read stdin!

      5 votes
    2. [2]
      primordial-soup
      (edited )
      Link Parent
      I managed to golf your code down a bit more: Part 1 (chars -= 31) x=y=0 for l in open(0): r,M=l.split();m=int(M);exec('yx'[r[0]=='f']+'+-'[r[0]>'f']+'=m') print(x*y) Part 2 (chars -= 26) x=y=a=0...

      I managed to golf your code down a bit more:

      Part 1 (chars -= 31)
      x=y=0
      for l in open(0):
       r,M=l.split();m=int(M);exec('yx'[r[0]=='f']+'+-'[r[0]>'f']+'=m')
      print(x*y)
      
      Part 2 (chars -= 26)
      x=y=a=0
      for l in open(0):
       r,M=l.split();m=int(M);exec(('a','y+=a*m;x')[r[0]=='f']+'+-'[r[0]>'f']+"=m")
      print(x*y)
      

      Using booleans as indices to replace conditionals, exec, and seeing if == can be changed to >/< seem like they'd be pretty widely applicable tricks for one's Python golfing tool belt.

      3 votes
      1. deckard
        Link Parent
        That's clever... I'll try some of these going forward

        That's clever... I'll try some of these going forward

        1 vote
  3. JRandomHacker
    Link
    C# Part 1 public override string SolvePart1() { var x = 0; var y = 0; using (var fs = new StreamReader(Inputs.Year2021.Inputs2021.Input2)) { string line; while ((line = fs.ReadLine()) != null) {...

    C#

    Part 1
    public override string SolvePart1()
    {
    	var x = 0;
    	var y = 0;
    	using (var fs = new StreamReader(Inputs.Year2021.Inputs2021.Input2))
    	{
    		string line;
    		while ((line = fs.ReadLine()) != null)
    		{
    			var commands = line.Split();
    			switch (commands[0])
    			{
    				case "forward":
    					x += int.Parse(commands[1]);
    					break;
    				case "up":
    					y += int.Parse(commands[1]);
    					break;
    				case "down":
    					y -= int.Parse(commands[1]);
    					break;
    			}
    		}
    
    	}
    
    	return $"coords {x}, {y} - answer {x * y}";
    
    }
    
    Part 2
    public override string SolvePart2()
    {
    	var x = 0;
    	var y = 0;
    	var aim = 0;
    	using (var fs = new StreamReader(Inputs.Year2021.Inputs2021.Input2))
    	{
    		string line;
    		while ((line = fs.ReadLine()) != null)
    		{
    			var commands = line.Split();
    			switch (commands[0])
    			{
    				case "forward":
    					x += int.Parse(commands[1]);
    					y += aim * int.Parse(commands[1]);
    					break;
    				case "up":
    					aim -= int.Parse(commands[1]);
    					break;
    				case "down":
    					aim += int.Parse(commands[1]);
    					break;
    			}
    		}
    
    	}
    
    	return $"coords {x}, {y} - answer {x * y}";
    
    }
    
    Commentary Frustrated by leaderboard today - I was delayed by probably a minute because my inputs were still reading last year's input files. I also didn't bother getting the sign right for part 1 - I just removed the `-` myself when submitting.
    5 votes
  4. bhrgunatha
    (edited )
    Link
    Racket as usual - I'll ignore the reading of the input file because it's so trivial in Racket and I expect the same for most other languages. Part 1 (for/fold ([h 0] [d 0] #:result (* h d)) ([line...

    Racket as usual - I'll ignore the reading of the input file because it's so trivial in Racket and I expect the same for most other languages.

    Part 1
    (for/fold ([h 0] [d 0] #:result (* h d))
              ([line input])
        (match (string-split line)
          [(list "forward" (app string->number amount))
           (values (+ h amount) d)]
          [(list "down" (app string->number amount))
           (values h (+ d amount))]
          [(list "up" (app string->number amount))
           (values h (- d amount))]))
    
    Part 2
    (for/fold ([h 0] [d 0] #:result (* h d))
              ([line input])
        (match (string-split line)
          [(list "forward" (app string->number amount))
           (values (+ h amount) (+ d (* aim amount)) aim)]
          [(list "down" (app string->number amount))
           (values h (+ d amount))]
          [(list "up" (app string->number amount))
           (values h (- d amount))]))
    
    Notes I'm going to focus my notes on introducing some of the nice features of Racket and/or interesting things about the solutions.

    Today is match

    The nice thing about match is not only de-structuring and matching against types - including literal values, but you can both bind and transform the matched input in one go with app.

    • (match (split line)
      match the result of splitting line (by default on space)
    • [(list "up" (app string->number amount)) <body>]
      when you find (list "up" <exactly one other value>) bind amount to the result of string->number applied to that second value.
    5 votes
  5. spit-evil-olive-tips
    Link
    Part 1 with open('002.txt') as file: lines = file.readlines() position, depth = 0, 0 for line in lines: action, amount = line.split(' ') amount = int(amount) if action == 'forward': position +=...
    Part 1
    with open('002.txt') as file:
        lines = file.readlines()
    
    position, depth = 0, 0
    
    for line in lines:
        action, amount = line.split(' ')
        amount = int(amount)
        if action == 'forward':
            position += amount
        elif action == 'up':
            depth -= amount
        elif action == 'down':
            depth += amount
        else:
            raise ValueError(action)
    
    print(position * depth)
    
    Part 2
    with open('002.txt') as file:
        lines = file.readlines()
    
    position, depth = 0, 0
    aim = 0
    
    for line in lines:
        action, amount = line.split(' ')
        amount = int(amount)
        if action == 'forward':
            position += amount
            depth += (amount * aim)
        elif action == 'up':
            aim -= amount
        elif action == 'down':
            aim += amount
        else:
            raise ValueError(action)
    
    print(position * depth)
    
    diff
    --- 002a.py     2021-12-01 21:07:33.382776564 -0800
    +++ 002b.py     2021-12-01 21:08:25.628144136 -0800
    @@ -2,16 +2,18 @@
         lines = file.readlines()
     
     position, depth = 0, 0
    +aim = 0
     
     for line in lines:
         action, amount = line.split(' ')
         amount = int(amount)
         if action == 'forward':
             position += amount
    +        depth += (amount * aim)
         elif action == 'up':
    -        depth -= amount
    +        aim -= amount
         elif action == 'down':
    -        depth += amount
    +        aim += amount
         else:
             raise ValueError(action)
     
    
    4 votes
  6. PapaNachos
    (edited )
    Link
    For some reason my kernel was completely unresponsive when I booted up Jupyter. Weirdly restarting python didn't help, but closing out of chrome and opening it back up did Day 2 Part A – Python...

    For some reason my kernel was completely unresponsive when I booted up Jupyter. Weirdly restarting python didn't help, but closing out of chrome and opening it back up did

    Day 2 Part A – Python

    Like yesterday just a really simple text parser and some basic math, This one didn't even need a data structure.

    data = test_data
    #data = real_data
    data = data.split('\n')
    
    
    hoz = 0
    depth = 0
    
    for row in data:
        instruction, val, = row.split(' ')
        if instruction == "forward":
            hoz = hoz + int(val)
        elif instruction == "down":
            depth = depth + int(val)
        elif instruction == "up":
            depth = depth - int(val)
    print(depth)
    print(hoz)
    
    print(depth * hoz)
    
    Day 2 Part b – Python Not much to say here, just switch depth for aim and add an equation to handle the multiplication
    #data = test_data
    data = real_data
    data = data.split('\n')
    
    
    hoz = 0
    depth = 0
    aim = 0
    for row in data:
        instruction, val, = row.split(' ')
        if instruction == "forward":
            hoz = hoz + int(val)
            depth = depth + (aim * int(val))
        elif instruction == "down":
            aim = aim + int(val)
        elif instruction == "up":
            aim = aim - int(val)
    print(depth)
    print(hoz)
    
    print(depth * hoz)
    
    Tips
    • The real trick is making sure your text parser can handle the different instructions 'forward val', 'up val' and 'down val'. I'm using python, so I was able to use 'split' to identify which command and what value was tied to it

    • When parsing strings don't forget to cast it to a type of variable you can do math on

    4 votes
  7. tomf
    (edited )
    Link
    whooo! Google Sheets Day 2! Part 1 =ARRAYFORMULA( SUM( IFERROR( --REGEXEXTRACT( A2:A, "forward ([0-9]+)")))* (ABS( SUM( IFERROR( --REGEXEXTRACT( A2:A, "down ([0-9]+)"))))- SUM( IFERROR(...

    whooo! Google Sheets Day 2!

    Part 1
    =ARRAYFORMULA(
       SUM(
        IFERROR(
         --REGEXEXTRACT(
          A2:A,
          "forward ([0-9]+)")))*
        (ABS(
          SUM(
           IFERROR(
            --REGEXEXTRACT(
             A2:A,
             "down ([0-9]+)"))))-
          SUM(
           IFERROR(
            --REGEXEXTRACT(
            A2:A,
            "up ([0-9]+)")))))
    
    Part 2

    First I brought together the ups and downs (E2)

    =ARRAYFORMULA(
      IF(ISBLANK(A2:A),,
       IFERROR(
        VLOOKUP(
         REGEXEXTRACT(A2:A,"(.*) "),
         {"up",-1;
          "down",1},
         2,FALSE)*
        RIGHT(A2:A,1))))
    

    Next I ran the horizontal stuff (F2)

    =ARRAYFORMULA(
      IF(ISBLANK(A2:A),,
       IFERROR(
        --REGEXEXTRACT(
         A2:A,
         "forward ([0-9]+)"))))
    

    Lastly, I used a VLOOKUP with TRUE to align the horizontal values with a running total and brought it all together.

    =ARRAYFORMULA(
      SUM(
       IFERROR(
        --REGEXEXTRACT(
         A2:A,
         "forward ([0-9]+)")))*
      SUM(
       IFERROR(
        VLOOKUP(
         ROW(F2:F),
         FILTER(
          {ROW(A2:A),
           SUMIF(
            ROW(E2:E),"<="&ROW(E2:E),
            E2:E)},
           SUMIF(
            ROW(E2:E),"<="&ROW(E2:E),
            E2:E)<>""),
         2,TRUE)*
       IFERROR(
        --REGEXEXTRACT(
         A2:A,
         "forward ([0-9]+)")))))
    

    Not the prettiest thing, but it worked...

    4 votes
  8. asterisk
    Link
    Python commands = { "forward": 0, "up": 0, "down": 0, } with open("input.txt") as file: for line in file: position, number = line.split() commands[position] += int(number) print("Part One:",...
    Python
    commands = {
        "forward": 0,
        "up": 0,
        "down": 0,
    }
    
    with open("input.txt") as file:
        for line in file:
            position, number = line.split()
            commands[position] += int(number)
    
    print("Part One:", commands["forward"] * (commands["down"] - commands["up"]))
    
    aim = 0
    depth = 0
    forward = 0
    
    with open("input.txt") as file:
        for line in file:
            position, number = line.split()
            number = int(number)
    
            if position == "forward":
                forward += number
                depth += aim * number
            else:
                aim += number if position == "down" else -number
    
    
    print("Part Two:", forward * depth)
    
    4 votes
  9. [3]
    DataWraith
    Link
    This is what I came up with for day 2 (omitting Part one, because of the verbosity). Day 02 — Part 2 (Rust) The solution is quite verbose, but defining Position/Instruction as struct/enum makes...

    This is what I came up with for day 2 (omitting Part one, because of the verbosity).

    Day 02 — Part 2 (Rust) The solution is quite verbose, but defining Position/Instruction as struct/enum makes the actual solve function trivial -- a simple call to fold.
    pub enum Instruction {
        Forward(i64),
        Down(i64),
        Up(i64),
    }
    
    impl Instruction {
        fn parse(s: &str) -> Instruction {
            let parts: Vec<&str> = s.split(" ").collect();
            let num: i64 = parts[1].parse().unwrap();
    
            match parts[0] {
                "forward" => Instruction::Forward(num),
                "up" => Instruction::Up(num),
                "down" => Instruction::Down(num),
                _ => panic!("Invalid instruction: {}", s),
            }
        }
    }
    
    #[derive(Default)]
    struct Position {
        horizontal: i64,
        depth: i64,
        aim: i64,
    }
    
    impl Position {
        fn apply_instr(self, instr: Instruction) -> Self {
            match instr {
                Instruction::Forward(num) => Position {
                    horizontal: self.horizontal + num,
                    depth: self.depth + num * self.aim,
                    ..self
                },
                Instruction::Down(num) => Position {
                    aim: self.aim + num,
                    ..self
                },
                Instruction::Up(num) => Position {
                    aim: self.aim - num,
                    ..self
                },
            }
        }
    }
    
    fn solve(input: &str) -> i64 {
        let instr = input.lines().map(|l| Instruction::parse(l));
        let position = instr.fold(Position::default(), |acc, instr| acc.apply_instr(instr));
    
        return position.depth * position.horizontal;
    }
    
    fn main() {
        println!("{}", solve(include_str!("../input.txt")));
    }
    

    Now that I posted this, I can finally look at the other solutions in the thread. :)

    3 votes
    1. [2]
      blitz
      Link Parent
      If you wanted to get into implementing traits for your own types, I would recommend looking at FromStr. If you implement that on your Instruction type, you could then just call .parse() on a...

      If you wanted to get into implementing traits for your own types, I would recommend looking at FromStr. If you implement that on your Instruction type, you could then just call .parse() on a string and get a Position object, rather than having to build a constructor (though you might need the turbofish.

      Here's how I did mine
      #[derive(Debug, PartialEq, Eq, Copy, Clone)]
      enum Command {
          Forward(u16),
          Down(u16),
          Up(u16),
      }
      
      impl FromStr for Command {
          type Err = ();
      
          fn from_str(input: &str) -> Result<Command, Self::Err> {
              let parts: Vec<&str> = input
                  .split(' ')
                  .collect();
      
              let amount = parts[1].parse::<u16>().unwrap();
      
              match parts[0] {
                  "forward" => Ok(Command::Forward(amount)),
                  "down" => Ok(Command::Down(amount)),
                  "up" => Ok(Command::Up(amount)),
                  _ => Err(())
              }
          }
      }
      

      Full solution here

      4 votes
      1. DataWraith
        Link Parent
        Thanks, I'll keep that in mind for the remaining days -- I'm sure this won't be the last puzzle that requires parsing something into a convenient struct.

        Thanks, I'll keep that in mind for the remaining days -- I'm sure this won't be the last puzzle that requires parsing something into a convenient struct.

        3 votes
  10. blitz
    (edited )
    Link
    Here's my solution on Sourcehut (Rust)

    Here's my solution on Sourcehut (Rust)

    3 votes
  11. Eabryt
    (edited )
    Link
    My journey in to learning Rust continues. I found the logic for both parts to be easy, figuring out how to get the language to do what I wanted was a bit tougher (specifically for Part I). Part 1...

    My journey in to learning Rust continues. I found the logic for both parts to be easy, figuring out how to get the language to do what I wanted was a bit tougher (specifically for Part I).

    Part 1
        let file_name = "input.txt";
        let file = File::open(file_name)?;
        let text = BufReader::new(file);
    
        let mut loc = 0;
        let mut depth = 0;
    
        for line in text.lines() {
            let mut iter = line.as_ref().unwrap().split_whitespace();
            let dir = iter.next();
            let val = iter.next();
            if dir == Some("forward") {
                loc += val.unwrap().parse::<i32>().unwrap();
            } else if dir == Some("down") {
                depth += val.unwrap().parse::<i32>().unwrap();
            } else if dir == Some("up") {
                depth -= val.unwrap().parse::<i32>().unwrap();
            } else {
                println!("Unrecognized input!");
            }
        }
    
        Ok((loc,depth))
    
    }
    
    fn main() {
    
        match part1() {
            Ok((loc,depth)) => println!("Result: {:?}",loc*depth),
            Err(e) => eprintln!("Oh no! There's an error. \n {}", e),
        }
    }
    
    Part II
      fn part2() -> Result<(i32, i32), Error> {
        let file_name = "input.txt";
        let file = File::open(file_name)?;
        let text = BufReader::new(file);
    
        let mut loc = 0;
        let mut depth = 0;
        let mut aim = 0;
    
        for line in text.lines() {
            let mut iter = line.as_ref().unwrap().split_whitespace();
            let dir = iter.next();
            let val = iter.next();
            if dir == Some("forward") {
                let temp = val.unwrap().parse::<i32>().unwrap();
                loc += temp;
                if aim > 0 {
                    depth += temp * aim;
                }
            } else if dir == Some("down") {
                aim += val.unwrap().parse::<i32>().unwrap();
            } else if dir == Some("up") {
                aim -= val.unwrap().parse::<i32>().unwrap();
            } else {
                println!("Unrecognized input!");
            }
        }
    
        Ok((loc,depth))
    }
    

    Same main as above but with a call to part2

    So far my biggest "complaint" is that the rest of you guys are too smart and clever. I was struggling with Part II yesterday so I tried to see what other people were doing and nothing I saw remotely made sense, haha.

    3 votes
  12. Gyrfalcon
    Link
    Definitely looking at both Rust and Python solutions leads me to believe I am still using Nim like it's Python. I don't think that's wrong, exactly, since what I like about it is that it is a...

    Definitely looking at both Rust and Python solutions leads me to believe I am still using Nim like it's Python. I don't think that's wrong, exactly, since what I like about it is that it is a statically typed, compiled, fast Python-like language. Anyway, my solutions:

    Part 1
    import std/strutils, std/strformat, std/sequtils
    
    var input: seq[string] = strutils.split(readFile("input.txt"),  "\n")
    var directions: seq[string] = @[]
    var distances: seq[int] = @[]
    
    for line in input[0 .. ^2]:
        directions.add(strutils.split(strutils.strip(line), ' ')[0])
        distances.add(parseInt(strutils.split(strutils.strip(line), ' ')[1]))
    
    var position: int = 0
    var depth: int = 0
    
    for command in sequtils.zip(directions, distances):
        if command[0] == "forward":
            position += command[1]
        elif command[0] == "down":
            depth += command[1]
        elif command[0] == "up":
            depth -= command[1]
        else:
            echo "AAAAAA"
    
    echo &"Depth: {depth}\nPosition: {position}\nProduct: {depth*position}\n"
    
    Part 2
    position = 0
    depth = 0
    var aim: int = 0
    
    for command in sequtils.zip(directions, distances):
        if command[0] == "forward":
            position += command[1]
            depth += aim * command[1]
        elif command[0] == "down":
            aim += command[1]
        elif command[0] == "up":
            aim -= command[1]
        else:
            echo "AAAAAA"
    
    echo &"Depth: {depth}\nPosition: {position}\nProduct: {depth*position}\n".
    
    3 votes
  13. Kremor
    Link
    Day 2 in Go Part 1 func main () { data := ReadData() d := 0 f := 0 for _, r := range data { n, _ := strconv.Atoi(r[1]) if r[0] == "down" { d += n } else if r[0] == "up" { d -= n } else { f += n }...

    Day 2 in Go

    Part 1
    func main () {
    	data := ReadData()
    
    	d := 0
    	f := 0
    	for _, r := range data {
    		n, _ := strconv.Atoi(r[1])
    		if r[0] == "down" {
    			d += n
    		} else if r[0] == "up" {
    			d -= n
    		} else {
    			f += n
    		}
    	}
    
    	fmt.Println(d * f)
    }
    
    Part 2
    func main () {
    	data := ReadData()
    
    	a := 0
    	d := 0
    	f := 0
    	for _, r := range data {
    		n, _ := strconv.Atoi(r[1])
    		if r[0] == "down" {
    			a += n
    		} else if r[0] == "up" {
    			a -= n
    		} else {
    			d += a * n
    			f += n
    		}
    	}
    
    	fmt.Println(d * f)
    }
    
    2 votes
  14. wycy
    (edited )
    Link
    Rust My Rust skills are very rusty at the moment. I'll need to go back and see if I can make this code more idiomatically Rust. Solution use std::env; use std::io::{self, prelude::*, BufReader};...

    Rust

    My Rust skills are very rusty at the moment. I'll need to go back and see if I can make this code more idiomatically Rust.

    Solution
    use std::env;
    use std::io::{self, prelude::*, BufReader};
    use std::fs::File;
    
    fn main() {
        let args: Vec<String> = env::args().collect();
        let filename = &args[1];
        day02(&filename).unwrap();
    }
    
    #[derive(Debug, Clone)]
    enum SubmarineCommand {
        Forward(i64),
        Up(i64),
        Down(i64),
    }
    impl From<&String> for SubmarineCommand {
        fn from(input: &String) -> Self {
            use SubmarineCommand::*;
            let mut parts = input.split_ascii_whitespace();
            let direction = parts.next().unwrap();
            let magnitude = parts.next().unwrap().parse::<i64>().unwrap();
            match direction {
                "forward" => Forward(magnitude),
                "up"      => Up(magnitude),
                "down"    => Down(magnitude),
                other     => panic!("Unknown direction: {}", other),
            }
        }
    }
    
    fn day02(input: &str) -> io::Result<()> {
        let file = File::open(input).expect("Input file not found.");
        let reader = BufReader::new(file);
    
        // Input
        let input: Vec<String> = match reader.lines().collect() {
            Err(err) => panic!("Unknown error reading input: {}", err),
            Ok(result) => result,
        };
        
        let commands = input
            .iter()
            .map(SubmarineCommand::from)
            .collect::<Vec<SubmarineCommand>>();
    
        // Part 1
        let mut depth = 0;
        let mut pos = 0;
        for cmd in commands.clone() {
            match cmd {
                SubmarineCommand::Forward(mag) => { pos += mag },
                SubmarineCommand::Up(mag)      => { depth -= mag },
                SubmarineCommand::Down(mag)    => { depth += mag }, 
            }
        }
        println!("Part 1: {}", depth * pos); // 1893605
    
        // Part 2
        let mut depth = 0;
        let mut pos = 0;
        let mut aim = 0;
        for cmd in commands.clone() {
            match cmd {
                SubmarineCommand::Forward(mag) => { pos += mag; depth += aim * mag },
                SubmarineCommand::Up(mag)      => { aim -= mag },
                SubmarineCommand::Down(mag)    => { aim += mag },
            }
        }
        println!("Part 2: {}", depth * pos); // 2120734350
    
        Ok(())
    }
    
    2 votes
  15. Crespyl
    Link
    Another warm up day, only this time I didn't lose time to a self-inflicted input handling error. I'll probably try to get straight into day 3 when it releases tonight instead of waiting for the...

    Another warm up day, only this time I didn't lose time to a self-inflicted input handling error. I'll probably try to get straight into day 3 when it releases tonight instead of waiting for the morning.

    Part 1 (Ruby)

    I considered tucking the position/state into a hash or something and making it all part of a fold operation, but I was in a lazy mood.

    def compute_p1(input)
      pos_horizontal = 0
      pos_depth = 0
    
      input
        .lines
        .map { _1.match(/^(\w+)\s+(\d+)$/) }
        .map { [_1[1], _1[2].to_i] }
        .each do |command|
        case command[0]
        when "forward"
          pos_horizontal += command[1]
        when "down"
          pos_depth += command[1]
        when "up"
          pos_depth -= command[1]
        else
          raise "unknown command: #{command}"
        end
      end
    
      return pos_horizontal * pos_depth
    end
    
    Part 2 (Ruby)
    def compute_p2(input)
      pos_horizontal = 0
      pos_depth = 0
      aim = 0
    
      input
        .lines
        .map { _1.match(/^(\w+)\s+(\d+)$/) }
        .map { [_1[1], _1[2].to_i] }
        .each do |command|
        case command[0]
        when "forward"
          pos_horizontal += command[1]
          pos_depth += aim * command[1]
        when "down"
          aim += command[1]
        when "up"
          aim -= command[1]
        else
          raise "unknown command: #{command}"
        end
      end
    
      return pos_horizontal * pos_depth
    end
    
    2 votes
  16. kari
    Link
    Day 2 in Rust. I've got functions for reading the lines and doing the output but those are boring so not including the source. Both days (Rust) let lines = aoc::get_lines("./inputs/day2.in"); //...

    Day 2 in Rust. I've got functions for reading the lines and doing the output but those are boring so not including the source.

    Both days (Rust)
        let lines = aoc::get_lines("./inputs/day2.in");
    
        // Part 1 values
        let mut depth_1 = 0;
        let mut horizontal_pos_1 = 0;
    
        // Part 2 values
        let mut depth_2 = 0;
        let mut horizontal_pos_2 = 0;
        let mut aim = 0;
    
        for line in lines {
            let split = line.split(" ").collect::<Vec<_>>();
    
            let command = split[0];
            let value = split[1].parse::<i32>().unwrap();
            
            // Part 1
            match command {
                "forward" => horizontal_pos_1 += value,
                "down" => depth_1 += value,
                "up" => depth_1 -= value,
                _ => println!("{} is not a valid command", command),
            }
    
            // Part 2
            match command {
                "forward" => {
                    horizontal_pos_2 += value;
                    depth_2 += aim * value;
                }
                "down" => aim += value,
                "up" => aim -= value,
                _ => println!("{} is not a valid command", command),
            }
        }
    
        aoc::output(2, "multiplicand", depth_1 * horizontal_pos_1, depth_2 * horizontal_pos_2);
    

    I'm very much not great at Rust, but I think it's a cool language. If anything is particularly un-idiomatic in Rust feel free to let me know! :)

    2 votes
  17. akk
    Link
    Did mine in Swift! Solution import Foundation enum Heading: String { case up = "up" case down = "down" case forward = "forward" } struct Direction { let heading: Heading let magnitude: Int } class...

    Did mine in Swift!

    Solution
    import Foundation
    
    enum Heading: String {
      case up = "up"
      case down = "down"
      case forward = "forward"
    }
    
    struct Direction {
      let heading: Heading
      let magnitude: Int
    }
    
    class Submarine {
     var directions: [Direction] = []
     var depth: Int = 0
     var aim: Int = 0
     var horizontalPosition: Int = 0
     func processDirectionsAndResetPosition(calculateAim: Bool) {
       for direction in directions {
         switch direction.heading {
            case .up:
            if calculateAim {
              aim = aim - direction.magnitude
            } else {
              depth = depth - direction.magnitude
            }
            case .down:
            if calculateAim {
              aim = aim + direction.magnitude
            } else {
              depth = depth + direction.magnitude
            }
            case .forward:
            if calculateAim {
              horizontalPosition = horizontalPosition + direction.magnitude
              depth = depth + (aim * direction.magnitude)
            } else {
              horizontalPosition = horizontalPosition + direction.magnitude
            }
         }
       }
       print("\(self.depth * self.horizontalPosition)")
       self.resetPosition()
     }
     private func resetPosition() {
       self.aim = 0
       self.depth = 0
       self.horizontalPosition = 0
     }
    }
    
    var sub = Submarine()
    
    while let line = readLine() {
      let splitLine = line.components(separatedBy: " ")
      let direction = Direction(heading: Heading(rawValue: String(splitLine[0]))!, magnitude: Int(splitLine[1])!)
      sub.directions.append(direction)
    }
    
    sub.processDirectionsAndResetPosition(calculateAim: false)
    sub.processDirectionsAndResetPosition(calculateAim: true)
    
    Sorta wish I had a more elegant solution to the part 1 / part 2 in one function, but it works
    2 votes
  18. sentry
    Link
    I'm late but I wanted to give it a try anyway! Part 1 (Rust) fn main() { let mut x = 0; let mut y = 0; include_str!("../../input") .lines() .map(|line| line.split_once(' ').unwrap()...

    I'm late but I wanted to give it a try anyway!

    Part 1 (Rust)
    fn main() {
        let mut x = 0;
        let mut y = 0;
        include_str!("../../input")
            .lines()
            .map(|line| line.split_once(' ').unwrap()
            .for_each(|cmd| match cmd.0.chars().nth(0).unwrap()
                'u' => y = y - cmd.1.parse::<i32>().unwrap()
                'd' => y = y + cmd.1.parse::<i32>().unwrap()
                'f' => x = x + cmd.1.parse::<i32>().unwrap()
                _ => panic!("Invalid direction"),
            });
        println!("position = {}", x * y);
    }
    
    Part 2 (Rust)
    fn main() {
        let mut aim = 0;
        let mut x = 0;
        let mut y = 0;
        include_str!("../../input")
            .lines()
            .map(|line| line.split_once(' ').unwrap()
            .for_each(|cmd| match cmd.0.chars().nth(0).unwrap()
                'u' => aim = aim - cmd.1.parse::<i32>().unwrap()
                'd' => aim = aim + cmd.1.parse::<i32>().unwrap()
                'f' => {
                    x = x + cmd.1.parse::<i32>().unwrap()
                    y = y + aim * cmd.1.parse::<i32>().unwrap()
                }
                _ => panic!("Invalid direction"),
            });
        println!("position = {}", x * y);
    }
    
    2 votes
  19. ras
    (edited )
    Link
    Both of these felt too easy. Part 1 - Javascript // Get the data let x = 0; let y = 0; data.map((item) => item.split(" ")) .foreach((item) => { if (item[0] === "forward") { y += parseInt(item[1]);...

    Both of these felt too easy.

    Part 1 - Javascript
    // Get the data
    let x = 0;
    let y = 0;
    
    data.map((item) => item.split(" "))
      .foreach((item) => {
        if (item[0] === "forward") {
          y += parseInt(item[1]);
        }
        if (item[0] === "down") {
          x += parseInt(item[1]);
        }
        if (item[0] === "up") {
          x -= parseInt(item[1]);
        }
      });
    
    let result = x * y;
    
    Part 2 - Javascript
    let x = 0;
    let y = 0;
    let aim = 0;
    
    data.map((item) => item.split(" "))
      .forEach((item) => {
        if (item[0] === "down") {
          aim += parseInt(item[1]);
        }
        if (item[0] === "up") {
          aim -= parseInt(item[1]);
        }
        if (item[0] === "forward") {
          y += parseInt(item[1]);
          x += aim * parseInt(item[1]);
        }
      });
    
    let result = y * aim;
    
    1 vote
  20. 3d12
    Link
    I agree with everyone else, this one felt a little easy. Still, no compaints, I'm sure it will get more difficult quite quickly! Part 1 const fs = require('fs'); const readline =...

    I agree with everyone else, this one felt a little easy. Still, no compaints, I'm sure it will get more difficult quite quickly!

    Part 1
    const fs = require('fs');
    const readline = require('readline');
    
    let directionArr = [];
    
    async function openFileForReading(file) {
    	const fileStream = fs.createReadStream(file);
    
    	const rl = readline.createInterface({
    		input: fileStream,
    		crlfDelay: Infinity
    	});
    
    	for await (const line of rl) {
    		try {
    			//directionArr.push(parseInt(line));
    			directionArr.push(line);
    		} catch(e) {
    			console.error(e);
    		}
    	}
    }
    
    function interpretDirection(inputDirection) {
    	let hmodifier = 0;
    	let vmodifier = 0;
    	const regex = /(\w+) (\d+)/;
    	const found = inputDirection.match(regex);
    	const direction = found[1];
    	const distance = parseInt(found[2]);
    	switch (direction) {
    		case 'forward': hmodifier += distance;
    			break;
    		case 'down': vmodifier += distance;
    			break;
    		case 'up': vmodifier -= distance
    			break;
    	}
    	return { hmodifier: hmodifier, vmodifier: vmodifier };
    }
    
    (async function mainExecution() {
    	await openFileForReading('input.txt');
    	let hposition = 0;
    	let vposition = 0;
    	for (const direction of directionArr) {
    		let outcome = interpretDirection(direction);
    		console.log("hmodifier: " + outcome.hmodifier + ", vmodifier: " + outcome.vmodifier)
    		hposition += outcome.hmodifier;
    		if (vposition + outcome.vmodifier < 0) {
    			vposition = 0;
    		} else {
    			vposition += outcome.vmodifier;
    		}
    		console.log("Current position: " + hposition + "," + vposition);
    	}
    	console.log("Answer found! " + (hposition * vposition));
    })();
    
    Part 2
    const fs = require('fs');
    const readline = require('readline');
    
    let directionArr = [];
    
    async function openFileForReading(file) {
    	const fileStream = fs.createReadStream(file);
    
    	const rl = readline.createInterface({
    		input: fileStream,
    		crlfDelay: Infinity
    	});
    
    	for await (const line of rl) {
    		try {
    			//directionArr.push(parseInt(line));
    			directionArr.push(line);
    		} catch(e) {
    			console.error(e);
    		}
    	}
    }
    
    function interpretDirection(inputDirection) {
    	let command = 'null';
    	let value = 0;
    	const regex = /(\w+) (\d+)/;
    	const found = inputDirection.match(regex);
    	command = found[1];
    	value = parseInt(found[2]);
    	return { command: command, value: value };
    }
    
    (async function mainExecution() {
    	await openFileForReading('input.txt');
    	let hposition = 0;
    	let vposition = 0;
    	let aim = 0;
    	for (const direction of directionArr) {
    		let outcome = interpretDirection(direction);
    		console.log("command: " + outcome.command + ", value: " + outcome.value)
    		switch (outcome.command) {
    			case 'up': if (aim - outcome.value < 0) {
    					aim = 0;
    				} else {
    					aim -= outcome.value;
    				}
    				break;
    			case 'down': aim += outcome.value;
    				break;
    			case 'forward': hposition += outcome.value;
    				vposition += (aim * outcome.value);
    				break;
    		}
    	}
    	console.log("Answer found! " + (hposition * vposition));
    })();
    
    1 vote