akk's recent activity

  1. Comment on Day 4: Scratchcards in ~comp.advent_of_code

    akk
    Link
    Dayjob made me put this off until after work and other responsibilities. Kinda messy. Part 2 had me stumped for a while. I conceptually knew what to do, but couldn't figure out what to type into...

    Dayjob made me put this off until after work and other responsibilities. Kinda messy. Part 2 had me stumped for a while. I conceptually knew what to do, but couldn't figure out what to type into IntelliJ.

    Java Solution
    package com.michaeleisemann.aoc23.services;
    
    import com.michaeleisemann.aoc23.interfaces.DayInterface;
    import org.springframework.stereotype.Service;
    
    import java.util.*;
    
    // https://adventofcode.com/2023/day/4
    @Service
    public class Day4Service implements DayInterface {
    
        private class Card {
            private record Numbers (List<Integer> numbers) {
                public Numbers(String numbers) {
                    // there can be more than one space between numbers
                    this(Arrays.stream(numbers.split("\\s+")).map(Integer::parseInt).toList());
                }
            }
    
            private final int id;
    
            private final Numbers winningNumbers;
            private final Numbers actualNumbers;
    
            public Card(int id, String winningNumbers, String actualNumbers) {
                this.id = id;
                this.winningNumbers = new Numbers(winningNumbers);
                this.actualNumbers = new Numbers(actualNumbers);
            }
    
            public int getId() {
                return id;
            }
    
            public Numbers getWinningNumbers() {
                return winningNumbers;
            }
    
            public Numbers getActualNumbers() {
                return actualNumbers;
            }
    
            /**
             * Find which actual numbers are in the winning numbers
             * @return
             */
            public List<Integer> getMatchingNumbers() {
                List<Integer> matchingNumbers = new ArrayList<>();
                for (Integer actualNumber : actualNumbers.numbers) {
                    if (winningNumbers.numbers.contains(actualNumber)) {
                        matchingNumbers.add(actualNumber);
                    }
                }
                return matchingNumbers;
            }
    
            @Override
            public String toString() {
                return "Card{" +
                        "id=" + id +
                        ", winningNumbers=" + winningNumbers +
                        ", actualNumbers=" + actualNumbers +
                        '}';
            }
    
        }
    
    
        public String part1(String puzzleInput) {
            List<Card> cards = parsePuzzleInput(puzzleInput);
            int total = 0;
            for (Card card : cards) {
                List<Integer> matchingNumbers = card.getMatchingNumbers();
                if (matchingNumbers.isEmpty()) {
                    continue;
                }
                /* The first match makes the card worth one point and each match after the first doubles the point value of that card. */
                int points = 1;
                for (int i = 1; i < matchingNumbers.size(); i++) {
                    points *= 2;
                }
                total += points;
    
            }
            return String.valueOf(total);
        }
    
        public String part2(String puzzleInput) {
            List<Card> cards = parsePuzzleInput(puzzleInput);
            HashMap<Integer, Integer> cardCopies = new HashMap<>();
    
            // Add all the cardIds to the map with a value of 1 (base)
            for (Card card : cards) {
                cardCopies.put(card.getId(), 1);
            }
    
            for (int i = 0; i < cards.size(); i++) {
                Card card = cards.get(i);
                int copies = cardCopies.get(card.getId());
                int newCards = card.getMatchingNumbers().size();
                for (int j = 1; j <= newCards && i + j < cards.size(); j++) {
                    cardCopies.put(cards.get(i + j).getId(), cardCopies.getOrDefault(cards.get(i + j).getId(), 0) + copies);
                }
            }
    
            int totalCards = cardCopies.values().stream().mapToInt(Integer::intValue).sum();
            return String.valueOf(totalCards);
        }
    
    
        private List<Card> parsePuzzleInput(String puzzleInput) {
            List<Card> cards = new ArrayList<>();
            for (String line : puzzleInput.split("\n")) {
                // Split on the first colon
                String[] parts = line.split(":", 2);
                String id = parts[0].replaceAll("\\D+", "");
                String[] numbers = parts[1].split("\\|");
                cards.add(new Card(Integer.parseInt(id), numbers[0].trim(), numbers[1].trim()));
            }
            return cards;
        }
    
        private Card findCardById(List<Card> cards, int id) {
            for (Card card : cards) {
                if (card.getId() == id) {
                    return card;
                }
            }
            return null;
        }
    }
    
    1 vote
  2. Comment on Day 3: Gear Ratios in ~comp.advent_of_code

    akk
    Link
    Not too easy, not too hard. Had to take some breaks to help with my mother who is currently recovering from neck/back surgery. It's also a lot verbose than I've seen compared to others. I also...

    Not too easy, not too hard. Had to take some breaks to help with my mother who is currently recovering from neck/back surgery. It's also a lot verbose than I've seen compared to others. I also switched over to using JetBrains IntelliJ IDEA's built-in HTTP client for sending my input vs using the excellent RapidAPI for Mac (formerly Paw)

    Ran into a lot of issues with an off-by-one, but I solved it :-D

    Java
    package com.michaeleisemann.aoc23.services;
    
    import com.michaeleisemann.aoc23.interfaces.DayInterface;
    import org.springframework.stereotype.Service;
    
    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.HashMap;
    import java.util.List;
    
    // https://adventofcode.com/2023/day/3
    @Service
    public class Day3Service implements DayInterface {
    
        private static class Schematic {
    
            private record PartNumber(int partNumber, int startX, int endX, int y) {
            }
    
            private record PartSymbol(String symbol, int x, int y) {
            }
    
            private final List<String> schematic = new ArrayList<>();
    
            private final List<PartNumber> partNumbers = new ArrayList<>();
            private final List<PartSymbol> partSymbols = new ArrayList<>();
    
            public Schematic(String schematic) {
                String[] lines = schematic.split("\n");
                this.schematic.addAll(Arrays.asList(lines));
                parseSchematic();
            }
    
            public List<String> getSchematic() {
                return schematic;
            }
    
            public List<PartNumber> getPartNumbers() {
                return partNumbers;
            }
    
            public List<PartSymbol> getPartSymbols() {
                return partSymbols;
            }
    
            private void parseSchematic() {
                for (int y = 0; y < schematic.size(); y++) {
                    String line = schematic.get(y);
                    StringBuilder partNumber = new StringBuilder();
                    int startX = 0;
                    int endX = 0;
                    for (int x = 0; x < line.length(); x++) {
                        if (Character.isDigit(line.charAt(x))) {
                            if (partNumber.isEmpty()) {
                                startX = x;
                            }
                            partNumber.append(line.charAt(x));
                            // I hate off by one errors
                            if (x == line.length() - 1) {
                                endX = x - 1;
                                PartNumber part = new PartNumber(
                                        Integer.parseInt(partNumber.toString()),
                                        startX,
                                        endX,
                                        y
                                );
                                partNumber = new StringBuilder();
                                partNumbers.add(part);
                            }
                        } else {
                            // we are done collecting part numbers
                            if (!partNumber.isEmpty()) {
                                endX = x - 1;
                                PartNumber part = new PartNumber(
                                        Integer.parseInt(partNumber.toString()),
                                        startX,
                                        endX,
                                        y
                                );
                                partNumber = new StringBuilder();
                                partNumbers.add(part);
                            }
                            if (line.charAt(x) != '.') {
                                PartSymbol partSymbol = new PartSymbol(
                                        String.valueOf(line.charAt(x)),
                                        x,
                                        y
                                );
                                partSymbols.add(partSymbol);
                            }
                        }
                    }
                }
            }
        }
    
        public String part1(String puzzleInput) {
            Schematic schematic = new Schematic(puzzleInput);
    
            int partNumberSum = 0;
    
            for (Schematic.PartNumber partNumber : schematic.getPartNumbers()) {
                for (Schematic.PartSymbol partSymbol : schematic.getPartSymbols()) {
                    if (partNumber.y() == partSymbol.y()) {
                        if (partNumber.startX() - 1 <= partSymbol.x() && partNumber.endX() + 1 >= partSymbol.x()) {
                            logger.debug("Same line: {} {} {}", partNumber.partNumber(), partSymbol.symbol());
                            partNumberSum += partNumber.partNumber();
                        }
                    } else if (partNumber.y() - 1 <= partSymbol.y() && partNumber.y() + 1 >= partSymbol.y()) {
                        if (partNumber.startX() - 1 <= partSymbol.x() && partNumber.endX() + 1 >= partSymbol.x()) {
                            logger.debug("Different line: {} {} {}", partNumber.partNumber(), partSymbol.symbol());
                            partNumberSum += partNumber.partNumber();
                        }
                    }
                }
            }
    
            return String.valueOf(partNumberSum);
    
        }
    
        public String part2(String puzzleInput) {
    
            Schematic schematic = new Schematic(puzzleInput);
    
    
            HashMap<Schematic.PartSymbol, ArrayList<Schematic.PartNumber>> partSymbolPartNumberHashMap = new HashMap<>();
    
            for (Schematic.PartNumber partNumber : schematic.getPartNumbers()) {
                for (Schematic.PartSymbol partSymbol : schematic.getPartSymbols()) {
                    if (partNumber.y() == partSymbol.y()) {
                        addPartToSymbol((HashMap<Schematic.PartSymbol, ArrayList<Schematic.PartNumber>>) partSymbolPartNumberHashMap, partNumber, partSymbol);
                    } else if (partNumber.y() - 1 <= partSymbol.y() && partNumber.y() + 1 >= partSymbol.y()) {
                        addPartToSymbol((HashMap<Schematic.PartSymbol, ArrayList<Schematic.PartNumber>>) partSymbolPartNumberHashMap, partNumber, partSymbol);
                    }
                }
            }
    
            // go through the hashmap and see which * have exactly 2 part numbers
            int gearRatioSum = 0;
            for (Schematic.PartSymbol partSymbol : partSymbolPartNumberHashMap.keySet()) {
                if (partSymbol.symbol().equals("*")) {
                    if (partSymbolPartNumberHashMap.get(partSymbol).size() == 2) {
                        // multiply the part numbers together
                        int gearRatio = 1;
                        for (Schematic.PartNumber partNumber : partSymbolPartNumberHashMap.get(partSymbol)) {
                            gearRatio *= partNumber.partNumber();
                        }
                        gearRatioSum += gearRatio;
                    }
                }
            }
    
            return String.valueOf(gearRatioSum);
        }
    
        private void addPartToSymbol(HashMap<Schematic.PartSymbol, ArrayList<Schematic.PartNumber>> partSymbolPartNumberHashMap, Schematic.PartNumber partNumber, Schematic.PartSymbol partSymbol) {
            if (partNumber.startX() - 1 <= partSymbol.x() && partNumber.endX() + 1 >= partSymbol.x()) {
                // add the part number to the hashmap
                if (partSymbolPartNumberHashMap.containsKey(partSymbol)) {
                    partSymbolPartNumberHashMap.get(partSymbol).add(partNumber);
                } else {
                    ArrayList<Schematic.PartNumber> partNumbers = new ArrayList<>();
                    partNumbers.add(partNumber);
                    partSymbolPartNumberHashMap.put(partSymbol, partNumbers);
                }
            }
        }
    }
    
    3 votes
  3. Comment on Day 2: Cube Conundrum in ~comp.advent_of_code

    akk
    Link
    More Java. I didn't need to make a class or anything, but I figured why not. I'm still pretty noob at Java (< 12 months), so I'm not sure what counts as "idiomatic java" or not. I'm happy with it,...

    More Java. I didn't need to make a class or anything, but I figured why not. I'm still pretty noob at Java (< 12 months), so I'm not sure what counts as "idiomatic java" or not. I'm happy with it, though.

    Solution
    package com.michaeleisemann.aoc23.services;
    
    import com.michaeleisemann.aoc23.interfaces.DayInterface;
    import org.springframework.stereotype.Service;
    
    import java.util.ArrayList;
    import java.util.List;
    
    // https://adventofcode.com/2023/day/2
    @Service
    public class Day2Service implements DayInterface {
    
        private final static int RED_AMOUNT  = 12;
        private final static int GREEN_AMOUNT  = 13;
        private final static int BLUE_AMOUNT  = 14;
    
        private static class Game {
    
            private final List<Round> rounds = new ArrayList<>();
    
            private final int id;
    
            private static class Round {
    
                private int red;
                private int blue;
                private int green;
    
                public Round(int red, int blue, int green) {
                    this.red = red;
                    this.blue = blue;
                    this.green = green;
                }
    
                public Round(String round) {
                    String[] cubes = round.split(",");
                    for (String cube : cubes) {
                        cube = cube.trim();
                        String[] colors = cube.split(" ");
                        switch (colors[1]) {
                            case "red":
                                red = Integer.parseInt(colors[0]);
                                break;
                            case "blue":
                                blue = Integer.parseInt(colors[0]);
                                break;
                            case "green":
                                green = Integer.parseInt(colors[0]);
                                break;
                        }
                    }
                }
    
                public int getRed() {
                    return red;
                }
    
                public int getBlue() {
                    return blue;
                }
    
                public int getGreen() {
                    return green;
                }
    
                @Override
                public String toString() {
                    return "Round: " + red + " red, " + blue + " blue, " + green + " green";
                }
            }
    
            public Game(int id, String rounds) {
                // rounds are semi-colon delimited
                // cubes are comma delimited
                this.id = id;
                String[] roundStrings = rounds.split(";");
                for (String round : roundStrings) {
                    this.rounds.add(new Round(round.trim()));
                }
            }
    
            public int getId() {
                return id;
            }
    
            public int getMaxRed() {
                int max = 0;
                for (Round round : rounds) {
                    if (round.getRed() > max) {
                        max = round.getRed();
                    }
                }
                return max;
            }
    
            public int getMaxBlue() {
                int max = 0;
                for (Round round : rounds) {
                    if (round.getBlue() > max) {
                        max = round.getBlue();
                    }
                }
                return max;
            }
    
            public int getMaxGreen() {
                int max = 0;
                for (Round round : rounds) {
                    if (round.getGreen() > max) {
                        max = round.getGreen();
                    }
                }
                return max;
            }
    
            @Override
            public String toString() {
                StringBuilder sb = new StringBuilder();
                sb.append("Game: ").append(id).append("\n");
                for (Round round : rounds) {
                    sb.append(round).append("\n");
                }
                return sb.toString();
            }
        }
    
        public String part1(String puzzleInput) {
            String[] lines = puzzleInput.split("\n");
            List<Game> games = new ArrayList<>();
            for (String line : lines) {
                games.add(buildGame(line));
            }
            int gameSum = 0;
            for (Game game : games) {
                int reds = game.getMaxRed();
                int blues = game.getMaxBlue();
                int greens = game.getMaxGreen();
                if (reds <= RED_AMOUNT && blues <= BLUE_AMOUNT && greens <= GREEN_AMOUNT) {
                    logger.debug("Game {} is valid", game.getId());
                    gameSum += game.getId();
                }
            }
            return String.valueOf(gameSum);
        }
    
        public String part2(String puzzleInput) {
            String[] lines = puzzleInput.split("\n");
            List<Game> games = new ArrayList<>();
            for (String line : lines) {
                games.add(buildGame(line));
            }
            int powerSum = 0;
            for (Game game : games) {
                int reds = game.getMaxRed();
                int blues = game.getMaxBlue();
                int greens = game.getMaxGreen();
                int power = 1;
                power *= reds;
                power *= blues;
                power *= greens;
                powerSum += power;
            }
            return String.valueOf(powerSum);
        }
    
        private Game buildGame(String line) {
            String[] parts = line.split(":");
            // remove ervything that is not a number from the first part
            String id = parts[0].replaceAll("\\D+", "");
            String rounds = parts[1].trim();
            return new Game(Integer.parseInt(id), rounds);
        }
    }
    
    4 votes
  4. Comment on Day 1: Trebuchet?! in ~comp.advent_of_code

    akk
    (edited )
    Link
    I started using Java since the last year, so this year I did them in Java. Other people have posted a repo, so here's mine:...

    I started using Java since the last year, so this year I did them in Java. Other people have posted a repo, so here's mine: https://michaeleisemann.com/source/aoc23/browse/master/src/main/java/com/michaeleisemann/aoc23/services/

    If other people have pointers about my somewhat rudimentary Spring Boot webapp layout, I would love feedback on that, too.

    Everything I've done so far with Java has been spring boot, so my AoC this year is a web app using Spring Boot.

    Java
    package com.michaeleisemann.aoc23.services;
    
    import com.michaeleisemann.aoc23.interfaces.DayInterface;
    import org.apache.commons.lang3.ArrayUtils;
    import org.springframework.stereotype.Service;
    
    // https://adventofcode.com/2023/day/1
    
    @Service
    public class Day1Service implements DayInterface {
    
        private final String[] wordToNumbers = {
            "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine"
        };
    
        // Fundamentally, we have to just get the first and last digit of the String.
        // The first and last number can be the same. e.g. asdf1asdf produces the first and last number as 1.
        public String day1Part1(String puzzleInput) {
            logger.info("Day 1 Part 1");
            logger.debug("Puzzle Input:\n{}", puzzleInput);
            int sum = 0;
            for (String line : puzzleInput.split("\n")) {
                // remove all non-digits
                String digits = line.replaceAll("\\D+", "");
                int calibrationValue = getFirstAndLastDigits(digits);
                logger.debug("Calibration Value: {}", calibrationValue);
                sum += calibrationValue;
            }
            return String.valueOf(sum);
        }
    
        public String day1Part2(String puzzleInput) {
            logger.info("Day 1 Part 2");
            logger.debug("Puzzle Input:\n{}", puzzleInput);
            int sum = 0;
            for (String line : puzzleInput.split("\n")) {
                // search through the line for either a digit or the word for a digit
                StringBuilder realDigits = new StringBuilder();
                StringBuilder tempString = new StringBuilder();
                for (String letter : line.split("")) {
                    if (letter.matches("\\d")) {
                        realDigits.append(letter);
                        tempString = new StringBuilder();
                        continue;
                    }
                    tempString.append(letter);
                    for (String wordNumber : wordToNumbers) {
                        if (tempString.toString().contains(wordNumber)) {
                            realDigits.append(ArrayUtils.indexOf(wordToNumbers, wordNumber));
                            tempString = new StringBuilder();
                            tempString.append(letter);
                            break;
                        }
                    }
                }
                String digits = realDigits.toString();
                int calibrationValue = getFirstAndLastDigits(digits);
                logger.debug("Calibration Value: {}", calibrationValue);
                sum += calibrationValue;
            }
            return String.valueOf(sum);
        }
    
        private int getFirstAndLastDigits(String digits) {
            String firstDigit = String.valueOf(digits.charAt(0));
            String lastDigit = String.valueOf(digits.charAt(digits.length() - 1));
            return Integer.parseInt(firstDigit + lastDigit);
        }
    }
    
    4 votes
  5. Comment on Good, quality YouTube channels? in ~tech

    akk
    Link
    VWestlife is a really fun channel if you're into old computers or electronics I love the deep dives into whatever the creator is interested in making a video about. I am especially fascinated with...

    VWestlife is a really fun channel if you're into old computers or electronics I love the deep dives into whatever the creator is interested in making a video about. I am especially fascinated with the videos on various radios and radio technologies.

    1 vote
  6. Comment on What are you self-hosting currently? in ~tech

    akk
    Link
    I've got a couple different computers running several things, everything is tailnetted together and I have a VPS that acts as my public IP and funnels traffic to my home. Honestly, I love...

    I've got a couple different computers running several things, everything is tailnetted together and I have a VPS that acts as my public IP and funnels traffic to my home. Honestly, I love Tailscale

    My main stack looks like:

    Ubuntu 22.04 LTS Server box that lives in my basement closet

    • ZNC for IRC
    • Transmission for one-off torrents (linux ISOs, the Llama model when that leaked etc)
    • Paperless-ngx since I've been trying (and failing) to catalog all the paper I come into
    • Caddy websever for directing to the websites that live in my house
    • A private pastebin
    • Samba share for sharing files in my house

    OpenSUSE Tumbleweed running on the Framework laptop 11th gen

    • Currently it just runs Phorge that is my personal website, git host, blog, calendar, and it also does a ton of other stuff -- I find new features in Phorge almost every day!

    Debian 11 box

    • Runs Akkoma for my microblogging needs

    HTPC running Windows 10

    • This is my Plex box that gathers all the media. Use your imagine as to what software runs on it ;)
    2 votes
  7. Comment on Day 4: Camp Cleanup in ~comp

    akk
    (edited )
    Link
    Pretty similar to yesterday if you ask me. Still love Swift! Part 1 and 2 import Foundation var totalFullSubRanges: Int = 0 var totalAnySubRanges: Int = 0 while let line = readLine() { let...

    Pretty similar to yesterday if you ask me. Still love Swift!

    Part 1 and 2
    import Foundation
    
    var totalFullSubRanges: Int = 0
    var totalAnySubRanges: Int = 0
    
    while let line = readLine() {
        let sectionRanges = line.components(separatedBy: ",").map { $0.components(separatedBy: "-").map { Int($0) ?? -1 } }
        let rangeOne = Set(Array(sectionRanges[0][0]...sectionRanges[0][1]))
        let rangeTwo = Set(Array(sectionRanges[1][0]...sectionRanges[1][1]))
        if rangeOne.isSubset(of: rangeTwo) || rangeTwo.isSubset(of: rangeOne) {
            totalFullSubRanges += 1
        }
        
        if !rangeOne.intersection(rangeTwo).isEmpty {
            totalAnySubRanges += 1
        }
    }
    
    print(totalFullSubRanges)
    print(totalAnySubRanges)
    
    5 votes
  8. Comment on Day 3: Rucksack Reorganization in ~comp

    akk
    Link
    More swift! Parts 1 and 2 import Foundation // Source: https://www.hackingwithswift.com/example-code/language/how-to-split-an-array-into-chunks extension Array { func chunked(into size: Int) ->...

    More swift!

    Parts 1 and 2
    import Foundation
    
    // Source: https://www.hackingwithswift.com/example-code/language/how-to-split-an-array-into-chunks
    extension Array {
        func chunked(into size: Int) -> [[Element]] {
            return stride(from: 0, to: count, by: size).map {
                Array(self[$0 ..< Swift.min($0 + size, count)])
            }
        }
    }
    
    func checkPriority(for item: String.Element) -> Int {
        if item.isUppercase {
            return Int(item.asciiValue!) - 64 + 26
        } else {
            return Int(item.asciiValue!) - 96
        }
    }
    
    func partOne(_ input: [String]) {
        var totalPriority: Int = 0
    
        for line in input {
            let sacks = Array(line).chunked(into: line.count / 2).map { Set($0) }
            guard let uniqueCompartment = sacks[0].intersection(sacks[1]).first else {  break }
            totalPriority += checkPriority(for: uniqueCompartment)
        }
        print(totalPriority)
    }
    
    
    func partTwo(_ input: [String]) {
        let sackGroups = input.chunked(into: 3)
        var totalPriority: Int = 0
        for group in sackGroups {
            let sackSet = group.map { Set($0) }
            guard let uniqueItem = sackSet[0].intersection(sackSet[1].intersection(sackSet[2])).first else {
                break }
            totalPriority += checkPriority(for: uniqueItem)
        }
        print(totalPriority)
    }
    
    var puzzleInput: [String] = []
    
    while let line = readLine() {
        puzzleInput.append(line)
    }
    
    partOne(puzzleInput)
    partTwo(puzzleInput)
    
    4 votes
  9. Comment on Day 2: Dive! in ~comp

    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