13 votes

Day 1: The Tyranny of the Rocket Equation

Today's problem description: https://adventofcode.com/2019/day/1


Join the Tildes private leaderboard! You can do that on this page, by entering join code 730956-de85ce0c.

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>

11 comments

  1. teaearlgraycold
    Link
    Gotta play catch up as well. Parts 1 and 2 with open("input.txt") as input: modules = [int(line) for line in input] def fuel_needed(mass, recurse=True): module_fuel = (mass // 3) - 2 if...

    Gotta play catch up as well.

    Parts 1 and 2
    with open("input.txt") as input:
        modules = [int(line) for line in input]
    
    def fuel_needed(mass, recurse=True):
        module_fuel = (mass // 3) - 2
    
        if module_fuel <= 0:
            return 0
    
        if not recurse:
            return module_fuel
    
        return module_fuel + fuel_needed(module_fuel)
    
    total_fuel_needed = sum([fuel_needed(module, recurse=False) for module in modules])
    print(f"Sum: {total_fuel_needed}")
    
    total_fuel_needed = sum([fuel_needed(module, recurse=True) for module in modules])
    print(f"Sum: {total_fuel_needed}")
    
    5 votes
  2. [2]
    bloup
    (edited )
    Link
    I'm using Python :) Part 1 input_file = open("input.txt", "r") # All we have to do is get a list of integers to sum. # We use map to convert the string list to an integer list. masses =...

    I'm using Python :)

    Part 1
    input_file = open("input.txt", "r")
    
    # All we have to do is get a list of integers to sum. 
    # We use map to convert the string list to an integer list.
    masses = list(map(int, input_file.read().splitlines()))
    # Once we have a list of integers, we can really start cooking.
    # Now all we have to do is use map to map each mass to its
    # fuel requirement and then sum the resulting list.
    print(sum(list(map(lambda x: (x // 3) - 2, masses))))
    input_file.close()
    
    Part 2
    input_file = open("input.txt", "r")
    # This time we need a little more power than a single line lambda.
    # Thankfully, Python lets you simply pass functions as arguments.
    # We define a recursive function that will account for the fuel for fuel.
    def fuel_for_fuel(x):
        if ((x // 3) - 2) < 0:
            return 0
        else:
            return ((x // 3) - 2) + fuel_for_fuel((x // 3) - 2)
    # Same procedure as above :)
    masses = list(map(int, input_file.read().splitlines()))
    print(sum(list(map(fuel_for_fuel, masses))))
    
    input_file.close()
    
    4 votes
    1. Deimos
      (edited )
      Link Parent
      Copy-pasting some suggestions I made for someone else's Day 1 Python solutions with some comments about cleaner/idiomatic ways to do some things. It should be useful for you too, if you want to be...

      Copy-pasting some suggestions I made for someone else's Day 1 Python solutions with some comments about cleaner/idiomatic ways to do some things. It should be useful for you too, if you want to be a little more "Pythonic" about it (I'll only do Part 1 since Part 2 is very similar):


      Part 1
      def mod_fuel(mass):
          return (mass // 3) - 2
      
      # This basically means "if they're running this file", so this code will run
      # when you do something like (if this file is day1.py): python day1.py
      # It's not really necessary for simple cases like this where you'll always be
      # running this file anyway, but it's a good habit to get into, since otherwise
      # the "top-level" code will run if something else was to import this file.
      if __name__ == "__main__":
          # Generally you should open files using a "with" statement like this, which
          # handles closing the file and other cleanup when its indented block ends.
          with open("day1input.txt") as input_file:
              # This is a "list comprehension", and will load all the lines of the
              # file into this list while also converting them all to integers.
              module_masses = [int(line) for line in input_file]
      
          # Another list comprehension, calling mod_fuel() on each item in the list.
          module_fuel_reqs = [mod_fuel(mass) for mass in module_masses]
      
          # There's a built-in sum() function you can use on lists and other
          # sequences, no need to do it manually.
          print(sum(module_fuel_reqs))
      
      3 votes
  3. [3]
    Gyrfalcon
    (edited )
    Link
    I'm doing these in Python! I am a little miffed that this challenge wasn't the ideal rocket equation. Parts 1 and 2 import math def calc_fuel(mass): return math.floor(mass / 3) - 2 def...

    I'm doing these in Python! I am a little miffed that this challenge wasn't the ideal rocket equation.

    Parts 1 and 2
    import math
    
    def calc_fuel(mass):
        return math.floor(mass / 3) - 2
    
    def calc_recursive_fuel(mass):
        fuel = calc_fuel(mass)
    
        if calc_fuel(fuel) > 0:
            return fuel + calc_recursive_fuel(fuel)
        else:
            return fuel
    
    input_file = "RocketEquationInput.txt"
    
    with open(input_file, "r") as fid:
        data = fid.readlines()
    
    for i in range(len(data)):
        data[i] = int(data[i].strip())
    
    output = []
    recursive_output = []
    
    for mass in data:
        output.append(calc_fuel(mass))
        recursive_output.append(calc_recursive_fuel(mass))
    
    print(sum(output))
    print(sum(recursive_output))
    
    4 votes
    1. [2]
      Crestwave
      Link Parent
      I think you need an empty line between the summary and the code block

      I think you need an empty line between the summary and the code block

      2 votes
      1. Gyrfalcon
        Link Parent
        Indeed I did. Thanks for the reminder!

        Indeed I did. Thanks for the reminder!

        1 vote
  4. krg
    Link
    Well, I'm already behind on the days...but here's Day 1. Part 1 + 2 Non-recursive function is part 1, recursive function is part 2. Hardest part was finding out how to read from a file and parse...

    Well, I'm already behind on the days...but here's Day 1.

    Part 1 + 2

    Non-recursive function is part 1, recursive function is part 2.
    Hardest part was finding out how to read from a file and parse the strings to numbers. I stole this person's solution, though I probably could make it slightly more efficient by not adding the numbers to a vector and just calculating the sum outright. I find that with these problems where efficiency isn't really a factor I like to store stuff in vectors as a kind of paper trail. I can print the vectors out and observe trends or note where things might be added wrong, etc.

    Anyhow, the code:

    use std::fs::File;
    use std::path::Path;
    use std::io::{BufRead, BufReader, Error, ErrorKind, Read};
    
    const DIVISOR: usize = 3;
    const SUBTRA: usize = 2;
    
    fn main() -> Result<(), Error>{
    	let path = Path::new("data/input.txt");
    	let vec = read(File::open(path)?)?;
    
    	let sum: usize = vec.iter()
    						.map(|&x| r_div_and_subt(x, DIVISOR, SUBTRA))
    						.sum();
    
    	println!("{:?}", sum);
    
    	Ok(())
    }
    
    fn div_and_subt(n: usize, x: usize, y: usize) -> usize {
    	n/x - y
    }
    
    fn r_div_and_subt(n: usize, x: usize, y: usize) -> usize {
    	let f = match n/x > y {
    		true => n/x - y,
    		false => return 0
    	};
    
    	f + r_div_and_subt(f, x, y)
    }
    
    fn read<R: Read>(io: R) -> Result<Vec<usize>, Error> {
    	let br = BufReader::new(io);
    	br.lines()
    		.map(|line| line.and_then(|v| v.parse().map_err(|e| Error::new(ErrorKind::InvalidData, e))))
    		.collect()
    }
    
    3 votes
  5. Crestwave
    Link
    Quick awk solution. Part 1 #!/usr/bin/awk -f { sum += int($0/3) - 2 } END { print sum } Part 2 #!/usr/bin/awk -f { mass = $0 for (;;) { mass = int(mass/3) - 2 if (mass < 0) break sum += mass } }...

    Quick awk solution.

    Part 1
    #!/usr/bin/awk -f
    { sum += int($0/3) - 2 }
    END { print sum }
    
    Part 2
    #!/usr/bin/awk -f
    {
        mass = $0
        for (;;) {
            mass = int(mass/3) - 2
            if (mass < 0)
                break
            sum += mass
        }
    }
    
    END { print sum }
    
    3 votes
  6. 9000
    Link
    Language: Rust I initially thought that we had to run the rocket equation on the total mass of fuel instead of each module's fuel, so my initial answer was high. But, that was just me misreading...

    Language: Rust

    I initially thought that we had to run the rocket equation on the total mass of fuel instead of each module's fuel, so my initial answer was high. But, that was just me misreading the instructions.

    Part 1 I got a little carried away with argument parsing in my main function... It's way too complicated. I should have just assumed there would be one file. Oh well.
    /* day_1
     *
     * USAGE
     *     cargo run [input files]
     * 
     * Input files must be a newline-separated list of positive integers greater 
     * than 5. For each input file listed, day_1 will return the answer for both
     * part one and part two.
     *
     */
    
    use std::env;
    use std::fs;
    use std::vec::Vec;
    
    fn main() {
        let args: Vec<String> = env::args().collect();
        if args.len() <= 1 {
            eprintln!("File name(s) required!");
            return;
        }
    
        for index in 1..args.len() {
            println!("{}", args[index]);
            println!("----------");
            let mut module_masses: Vec<u32> = Vec::new();
            for line in fs::read_to_string(&args[index]).unwrap().lines() {
                module_masses.push(line.parse().unwrap());
            }
            println!("Fuel required for modules (part 1): {}", calculate_fuel_required_for_part_one(&module_masses));
            println!("Fuel required for modules (part 2): {}", calculate_fuel_required_for_part_two(&module_masses));
            if index != args.len() - 1 {
                println!();
            }
        }
    }
    
    fn calculate_fuel_required_for_part_one(module_masses: &Vec<u32>) -> u32 {
        let mut total_fuel = 0;
        for module_mass in module_masses {
            total_fuel += (module_mass / 3) - 2;
        }
    
        total_fuel
    }
    
    fn calculate_fuel_required_for_part_two(module_masses: &Vec<u32>) -> u32 {
        let mut total_fuel = 0;
        for module_mass in module_masses {
            total_fuel += calculate_fuel_required_for_a_module(module_mass);
        }
    
        total_fuel
    }
    
    fn calculate_fuel_required_for_a_module(mass: &u32) -> u32 {
        let mut total_fuel = 0;
        let mut fuel_delta = (mass / 3) - 2;
    
        while fuel_delta > 6 {
            total_fuel += fuel_delta;
            fuel_delta = (fuel_delta / 3) - 2;
        }
    
        total_fuel + fuel_delta
    }
    
    3 votes
  7. unknown user
    Link
    Copy pasted from my comment in the original thread Day 1: The Tyranny of the Rocket Equation Part 1 import math with open('input','r') as f: data = f.read().splitlines() Total = 0 for i in...

    Copy pasted from my comment in the original thread

    Day 1: The Tyranny of the Rocket Equation

    Part 1
    import math
    
    with open('input','r') as f:
        data = f.read().splitlines()
    
    Total = 0
    for i in range(len(data)):
        Total = Total + (math.floor((int(data[i]) / 3)) - 2)
    
    print(Total)
    

    This was pretty simple. I'm sure it could be condensed down.

    Part 2
    import math
    
    def calculate(inamount):
        return math.floor((int(inamount) / 3)) - 2#divide by 3, round down, -2
    
    with open('input','r') as f:
        data = f.read().splitlines()
    
    Total = 0
    for i in range(len(data)):
        FuelArray = []    
        FuelArray.append(calculate(data[i]))
        if calculate(data[i]) <= 0:
            Total = Total + calculate(data[i])
        else:
            while calculate(FuelArray[-1]) > 0:
                FuelArray.append(calculate(FuelArray[-1]))#-1 means last entry
            FuelArraySum = 0
            for i in range(len(FuelArray)):
                FuelArraySum = FuelArraySum + FuelArray[i]
            Total = Total + FuelArraySum
            
    print(Total)
    

    I'm not entirely sure I needed to use a function here. But it was easier for my brain to work around it that way. This one made me think a little with the whole calculating the weight of fuel needed for fuel.

    3 votes
  8. heady
    Link
    It's not very pretty Both parts modulemassfile = open("modulemass", 'r') import math def calcfuel(mass): fuel = int(((math.floor(mass))/3)-2) return fuel def part1(): sumfuel = 0 for mass in...

    It's not very pretty

    Both parts
    modulemassfile = open("modulemass", 'r')
    import math
    
    def calcfuel(mass):
        fuel = int(((math.floor(mass))/3)-2)
        return fuel
    
    def part1():
        sumfuel = 0
        for mass in modulemassfile:
            fuel = calcfuel(int(mass))
            fuel = part2(fuel)
            sumfuel += fuel
        return sumfuel
    
    def part2(fuel):
        newfuel = calcfuel(fuel)
        sumfuel = fuel
        while newfuel > 0 :
            sumfuel = sumfuel + newfuel
            newfuel = calcfuel(newfuel)
        return sumfuel
      
    print("Total fuel required: " + str(part1()))
    
    3 votes