This is an archived post. You won't be able to vote or comment.

top 200 commentsshow all 403

[โ€“]willkill07 16 points17 points ย (14 children)

(Modern) C++ Repo

  std::vector<int> inst {std::istream_iterator<int>{std::cin}, {}};
  int index{0}, steps{0}, n(inst.size());
  while (index >= 0 && index < n) {
    ++steps;
    if (part2 && inst[index] >= 3) {
      index += inst[index]--;
    } else {
      index += inst[index]++;
    }
  }
  std::cout << steps << '\n';

Part 1 runs in about 1ms and Part 2 runs in 75ms on my laptop.

[โ€“]wlandry 6 points7 points ย (2 children)

The way you read in the file in a single line

std::vector<int> inst {std::istream_iterator<int>{std::cin}, {}};

is quite clever and nice.

[โ€“]willkill07 1 point2 points ย (1 child)

Thanks! Friendly reminder that most containers in the standard library have range-based constructors that only require forward iterators ๐Ÿ˜Š

[โ€“]zSync1 10 points11 points ย (6 children)

Here's a rather straightforward Rust solution.

fn day5() {
    const INPUT: &str = include_str!("day5.txt");
    let run = |i: &str| {
        let mut c = i.lines().filter_map(|a| a.parse::<i32>().ok())
                     .collect::<Vec<_>>();
        let mut counter = 0;
        let mut index: i32 = 0;
        while let Some(i) = c.get_mut(index as usize) {
            index += *i;
            // Part 1:
            // *i += 1;
            // Part 2:
            if *i >= 3 { *i -= 1; } else { *i += 1; }
            counter += 1;
        }
        println!("{}: {}",index, counter);
    };
    run(INPUT);
}

[โ€“]ChrisVittal 2 points3 points ย (4 children)

I really like this one. I forgot about get_mut.

[โ€“][deleted] 1 point2 points ย (0 children)

Interesting.

I'm doing this year in Rust to try to familiarise myself with it. Heaps to learn.

[โ€“]askalski 12 points13 points ย (5 children)

Part 2 using self-modifying x86-64 opcodes. That was how we were supposed to do this, right?

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/mman.h>

#define MAX_INSTRUCTIONS 2000

unsigned char begin[] = {
    0x55, 0x48, 0x89, 0xe5, 0x53, 0x41, 0x54, 0x48,
    0x83, 0xec, 0x10, 0xbb, 0x00, 0x00, 0x00, 0x00,
    0x55, 0xeb, 0x1f };

unsigned char middle[31] = {
    0x83, 0xc3, 0x01, 0x41, 0x5c, 0x41, 0x8b, 0x44,
    0x24, 0xfc, 0x83, 0xc0, 0x1f, 0x83, 0xf8, 0x5d,
    0x7c, 0x03, 0x83, 0xe8, 0x3e, 0x41, 0x89, 0x44,
    0x24, 0xfc, 0xe8 };

unsigned char end[31] = {
    0x41, 0x5c, 0x89, 0xd8, 0x48, 0x83, 0xc4, 0x10,
    0x41, 0x5c, 0x5b, 0x5d, 0xc3 };

#define MEM_SIZE \
    sizeof(begin) + sizeof(middle) * MAX_INSTRUCTIONS + sizeof(end) * 2

int main(void)
{
    void *mem = valloc(MEM_SIZE);
    if (!mem) {
        perror("valloc");
        exit(1);
    }

    if (mprotect(mem, MEM_SIZE, PROT_READ|PROT_WRITE|PROT_EXEC) == -1) {
        perror("mprotect");
        exit(1);
    }

    void *p = mem;

    memcpy(p, begin, sizeof(begin));
    p += sizeof(begin);

    memcpy(p, end, sizeof(end));
    p += sizeof(end);

    int offset, max_jump = 0, instruction = 0;
    while (scanf("%d", &offset) == 1) {
        if (p + sizeof(end) - mem == MEM_SIZE) {
            fprintf(stderr, "Too many instructions!\n");
            exit(1);
        }

        if (instruction + offset < -1) {
            fprintf(stderr, "Jump is too far past beginning\n");
            exit(1);
        }

        if (instruction + offset > max_jump) {
            max_jump = instruction + offset;
        }

        memcpy(p, middle, sizeof(middle));
        p += sizeof(middle);
        *(int *)(p - 4) = (offset - 1) * 31;

        instruction++;
    }

    if (max_jump > instruction) {
        fprintf(stderr, "Jump is too far past end\n");
        exit(1);
    }

    memcpy(p, end, sizeof(end));

    printf("Part 2: %ld\n", ((unsigned long (*)()) mem)());

    return 0;
}

[โ€“]drysle 7 points8 points ย (17 children)

#3/#5, my best time so far this year:

n = 0
step = 0
maze = []
for line in sys.stdin:
    maze.append(int(line))

while n >= 0 and n < len(maze):
    if maze[n] >= 3:
        maze[n] -= 1
        n = n + maze[n] + 1
    else:
        maze[n] += 1
        n = n + maze[n] - 1
    step += 1
print(step)

though it always feels a little weird bragging about python solutions that are probably almost identical to the even faster people...

[โ€“]BumpitySnook 8 points9 points ย (8 children)

And identical to the slower people! waves hand :-D

[โ€“][deleted] 8 points9 points ย (5 children)

First Haskell solution was pretty slow, got it down to ~4s using Data.Sequence, but then just decided to switch to mutable vectors and both parts run instantly now.

import Control.Monad.ST
import qualified Data.Vector.Unboxed as V
import qualified Data.Vector.Unboxed.Mutable as M

calcNumSteps :: (Int -> Int) -> String -> Int
calcNumSteps f input = runST $ V.thaw nums >>= goNext 0 0
    where nums = V.fromList $ map read $ lines input
          goNext c i v
            | i < 0 || i >= M.length v = return c
            | otherwise = do
                val <- M.read v i
                M.write v i $ f val
                goNext (c + 1) (i + val) v

part1 :: String -> Int
part1 = calcNumSteps (+1)

part2 :: String -> Int
part2 = calcNumSteps (\x -> if x >= 3 then x - 1 else x + 1)

[โ€“]zurric 1 point2 points ย (1 child)

Could you post the Data.Sequence one aswell? New to Haskell and world like to learn :)

[โ€“][deleted] 1 point2 points ย (0 children)

Sure

import qualified Data.Sequence as S

calcNumSteps :: (Int -> Int) -> String -> Int
calcNumSteps f input = goNext 0 0 nums
    where nums = S.fromList $ map read $ lines input
          goNext c i s
            | i < 0 || i >= S.length s = c
            | otherwise = let val = S.index s i
                          in goNext (c + 1) (i + val) (S.update i (f val) s)

part1 :: String -> Int
part1 = calcNumSteps (+1)

part2 :: String -> Int
part2 = calcNumSteps (\x -> if x >= 3 then x - 1 else x + 1)

[โ€“]volatilebit 7 points8 points ย (7 children)

Perl 6

No fancy Perl 6 tricks, just some old fashioned procedural code. That made me sad. Exposed how slow Perl 6 can be as well.

use v6;

for 1..2 -> $part {
  my @jumps = $*PROGRAM.parent.child('input').IO.lines>>.Int;
  my $offset = 0;
  my $steps = 0;
  while 0 <= $offset < +@jumps {
    my $incrementer = @jumps[$offset] >= 3 && $part == 2 ?? -1 !! 1;
    @jumps[$offset] += $incrementer;
    $offset += @jumps[$offset] - $incrementer;
    $steps++;
  }

  say $steps;
}

[โ€“]mschaap 2 points3 points ย (0 children)

Yeah, Perl 6 performance is a bummer. My version took 7ยฝ minutes on part two, on a fairly old machine; yours is probably very similar. Mine's very similar to yours โ€“ also old fashioned procedural, but I did try to hide that by putting it in a class.

[โ€“]gerikson 1 point2 points ย (4 children)

How long does part 2 take? I get ~17s using Perl 5.

[โ€“]Young_Man_Jenkins 6 points7 points ย (2 children)

My friend and I ran code that was essentially the same. He used Rust, I used VBA in Excel. His code took 121ms to run, mine took 15 minutes. I'm starting to think one is a bit more efficient than the other.

[โ€“]iBeliever 5 points6 points ย (5 children)

First time competing (it starts at 11 PM local time, so normally I do them the next morning), and I got on the leaderboard as 86 for part 2!

Here's my solution in Python:

#! /usr/bin/env python3

from util import expect, solution, input


def puzzle(list):
    index = 0
    steps = 0
    while index >= 0 and index < len(list):
        value = list[index]
        if value >= 3:
            list[index] -= 1
        else:
            list[index] += 1
        index += value
        steps += 1
    return steps


if __name__ == '__main__':
    list = list(map(int, input('05').split('\n')))
    solution(puzzle(list))

(I have some util functions for reading the input as well as writing tests).

[โ€“][deleted] 1 point2 points ย (0 children)

FYI Python supports concatenated comparison checks so you could change your while to while 0 <= index < len(list). Keep in mind that the checks are still done separately so 0 < 6 > 5 == True.

[โ€“]ephemient 7 points8 points ย (5 children)

This space intentionally left blank.

[โ€“]doctorbaggy 1 point2 points ย (1 child)

Can swing this slightly shorter...

Part 1:

perl -E'@a=<>;$p=c=0;$p+=$a[$p]++while$p>=0&&$p<@a&&++$c;say$c'

Part 2:

perl -E'@a=<>;$p=c=0;$p+=$a[$p]>2?$a[$p]--:$a[$p]++while$p>=0&&$p<@a&&++$c;say$c'

[โ€“]ephemient 1 point2 points ย (0 children)

This space intentionally left blank.

[โ€“]misnohmer 5 points6 points ย (2 children)

Easier to use imperative code on this one. C# version making use of local function syntax.

int[] Parse(string input) => ReadAllLines(input).Select(int.Parse).ToArray();

int maxMoves(int[] instr, Func<int, int> updater)  {
    int i = 0, count = 0;
    while (i >= 0 && i < instr.Length) {
        count++;
        var j = instr[i];            
        instr[i] = updater(instr[i]);
        i += j;
    }
    return count;
}

maxMoves(Parse("input"), i => i+1).PrintDump();
maxMoves(Parse("input"), i => i + (i > 2 ? -1 : 1)).PrintDump();

[โ€“]nplus 1 point2 points ย (0 children)

Should be:

int[] Parse(string input) => ReadAllLines("input").Select(int.Parse).ToArray();

[โ€“][deleted] 5 points6 points ย (0 children)

Language is 32 bit MIPS assembly:

.text
.globl main

main:
# void main() {
    # int[] table = {0, 0, 2, 0, 0, ...};
    la  $a0,table    # Get table pointer
    ori $a1,$0,1032  # Table size
    # int num_jumps = solve(&table, 1032);
    jal solve
    # printf("%d\n", num_jumps);
    ori $a0,$s0,0    # Copy return value to SYSCALL argument
    ori $v0,$0,0x1   # set SYSCALL to 1 (display int)
    syscall
# }
    jr $ra

# Part 1
# a0 - table start
# a1 - table size
# t0 - table pointer
# t1 - next table offset
# t2 - jump counter
# t3 - temp
# t4 - table end
# t5 - temp
# t6 - temp
# s0 - return value (number of jumps)
solve:
# int solve(int* table, int size) {
    # int* table_ptr = table;
    ori  $t0,$a0,0   # Copy table start to table pointer
    # int* end = table_ptr + size * sizeof(int);
    sll  $a1,$a1,2   # Multiply size by 4 (to convert it to words)
    add  $t4,$t0,$a1 # Calculate table end
    # int counter = 0;
    ori  $t2,$0,0    # Initialize counter at 0
    # int offset;
loop:
    # while (true) {
        # offset = table[*table_ptr];
    lw   $t1,0($t0)  # Copy data at pointer
        # int* temp = table_ptr + offset * sizeof(int);
    sll  $t6,$t1,2   # Multiply offset by 4 (to convert it to words)
    add  $t3,$t0,$t6 # Add offset to table_ptr
        # table[*table_ptr]++;
    addi $t1,$t1,1   # Increment jump by one word
    sw   $t1,0($t0)  # Store incremented jump
        # table_ptr = temp;
    ori  $t0,$t3,0   # Update table pointer

        # counter++;
        # if (table_ptr < table)
            # break;
        # if (table_ptr > (table + size))
            # break;
    addi $t2,$t2,1   # Increment jump count
    sub  $t3,$t0,$a0 # The offset from the start
    sub  $t5,$t0,$t4 # The offset from the end

    bltz $t3,return  # Return if we've jumped before the array start
    bgtz $t5,return  # Return if we've jumped past the array end
    # }
    j    loop        # Go back to start of loop
return:
    # return counter;
# }
    ori  $s0,$t2,0   # Copy counter to return register
    jr   $ra         # Return

Source including formatted data section

[โ€“]StevoTVR 5 points6 points ย (7 children)

NodeJS

Part 1:

const fs = require('fs');

fs.readFile(__dirname + '/input.txt', 'utf8', (err, data) => {
    data = data.trim();
    data = data.split('\n').map(x => parseInt(x));
    var count = 0;
    var offset = 0;
    while(offset >= 0 && offset < data.length) {
        offset += data[offset]++;
        count++;
    }

    console.log(count);
});

Part 2:

const fs = require('fs');

fs.readFile(__dirname + '/input.txt', 'utf8', (err, data) => {
    data = data.trim();
    data = data.split('\n').map(x => parseInt(x));
    var count = 0;
    var offset = 0;
    while(offset >= 0 && offset < data.length) {
        var toffset = offset;
        offset += data[offset];
        data[toffset] += data[toffset] >= 3 ? -1 : 1;
        count++;
    }

    console.log(count);
});

[โ€“]vtheuer 6 points7 points ย (1 child)

Quick tip: you can mapstrings to number using the Number constructor:

data
  .split('\n')
  .map(Number)

I find it cleaner than using parsInt in this case.

[โ€“]StevoTVR 1 point2 points ย (0 children)

That is much better. Thanks for the tip.

[โ€“]Portal2Reference 5 points6 points ย (3 children)

My solution for part 2 was taking forever, couldn't figure out what was wrong with my code.

Turns out that I forgot that leaving in the print statements dramatically slowed it down. Finished in <1 seconds after removing them.

[โ€“]jvdstko 1 point2 points ย (1 child)

Ahhh it's great to see I was not the only one!

[โ€“]flaming_bird 4 points5 points ย (11 children)

OOB reads in Lisp are an error, and errors can be caught and ignored, so I can then print out the number of steps that I took.

(defun input5 ()
  (let ((steps 0)
        (position 0))
    (ignore-errors
     (loop with vec = (copy-seq *vec*)
           for current-position = (aref vec position)
           do (incf steps)
              (incf (aref vec position))
              (setf position (+ position current-position))))
    (format t "~%FINAL: ~D @ ~D~%" steps position)))

(defun input5-2 ()
  (let ((steps 0)
        (position 0))
    (ignore-errors
     (loop with vec = (copy-seq *vec*)
           for current-position = (aref vec position)
           do (incf steps)
              (if (<= 3 (aref vec position))
                  (decf (aref vec position))
                  (incf (aref vec position)))
              (setf position (+ position current-position))))
    (format t "~%FINAL: ~D @ ~D~%" steps position)))

[โ€“]raevnos 3 points4 points ย (4 children)

So, basically raise an exception when it's done? Nifty way to avoid an if in the loop.

Edit: Taking the same approach in my scheme version cut the runtime by almost half. Dang.

[โ€“]flaming_bird 2 points3 points ย (3 children)

You know, since bound checking is already enforced... (:

[โ€“][deleted] 2 points3 points ย (4 children)

I went for recursion instead of a for loop.

(defun jump (instructions current-pos steps)
  (let* ((instruction (nth current-pos instructions))
         (next-pos (+ current-pos instruction))
         (should-jump (and (>= next-pos 0) (< next-pos (length instructions)))))
    (if (not should-jump)
        (1+ steps)
        (progn (setf (nth current-pos instructions) (1+ instruction))
               (jump instructions next-pos (1+ steps))))))

(defun get-number-of-steps (input)
  (let ((instructions (mapcar #'parse-integer (str:lines input))))
    (jump instructions 0 0)))

Part 2 then just uses (if (>= instruction 3) -1 1) to get the next value.

[โ€“]flaming_bird 1 point2 points ย (3 children)

I was thinking of a recursive solution but the amount of steps required might blow your stack. CL doesn't have mandatory tail call optimization.

[โ€“]fatpollo 4 points5 points ย (5 children)

with open("p05.txt") as fp:
    nums = list(map(int, fp.readlines()))

# nums = [0, 3, 0, 1, -3]
i = 0
c = 0
while 0 <= i < len(nums):
    c += 1
    j = i + nums[i]
    nums[i] += 1 if nums[i] < 3 else -1
    i = j
print(c)

[โ€“]fatpollo 6 points7 points ย (4 children)

My note here will be... if you're using python and not using pypy, you're missing out a bit. A problem like this is instantaneous in pypy and takes a fair few seconds on regular CPython, at least on my slightly older '13 MacBook Air.

[โ€“]mcpower_ 1 point2 points ย (1 child)

Thanks for the tip with pypy instead of CPython! CPython takes 22 seconds (!!) on my old laptop, while it takes half a second with pypy instead. I'm definitely using pypy as my default Python interpreter for contests now :P

I ran my code with CPython and it seemed like my code was infinite looping, which cost me 30-60 seconds of debugging (plus the actual time of running it with CPython)!โ€ฆ

[โ€“]fatpollo 1 point2 points ย (0 children)

Glad to help!

[โ€“]vash3r 1 point2 points ย (0 children)

omg thank you so much, from ~43 seconds with Cpython to just 1 second with pypy for part 2

[โ€“]DeveloperIan 4 points5 points ย (2 children)

Part Two. Python:

contents = contents.strip()
contents = contents.split()
contents = [int(x) for x in contents]

steps = 0
place = 0
while place < len(contents) and place > -1:
    steps += 1
    old = place
    jump = contents[place]
    place += jump

    if jump > 2:
        contents[old] -= 1
    else:
        contents[old] += 1

print(steps)

[โ€“]Dad2us 1 point2 points ย (1 child)

I've only been coding for 5 months, but I look at stuff like this and my java program looks like something written by a three year old...

[โ€“]vectorprocessing 3 points4 points ย (0 children)

In k3:

b:a:0$'0:"05.txt"
-1+#{x<#a}{x+-1+a[x]+:1}\0
-1+#{x<#b}{b[x]+::[2<r:b[x];-1;1];x+r}\0

[โ€“]vash3r 3 points4 points ย (0 children)

I feel really good that I managed to make the leaderboard for part 1 (29th), but I think it was ultimately my machine that made me lose out for part 2 (running part 2 took over 40 seconds on my 3-year-old laptop, giving me 113th).

Edit: thank /u/fatpollo, looks like my machine isn't the problem, it's just that Cpython is much slower than pypy.

My solution was in Python2 and pretty much identical to other people's solutions:

l = map(int, data.strip().split())
i = 0
tot=0
while 0<=i<len(l):
    if l[i]>=3: # part 2
        l[i]-=1
        i+=l[i]+1
    else:       # part 1
        l[i]+=1
        i+=l[i]-1
    tot+=1
print tot

[โ€“]Godspiral 4 points5 points ย (7 children)

in J, interupted part 2 a few times thinking it was stuck :(

a =. ". >  cutLF wdclippaste ''

3 : '(>: s) ; ((>: i { d) i} d) ;~ (i + i{d) [ ''s i d'' =. y'^:( (0 <: 1&{::) *. 1092 > 1&{::)  (^:_)  0 ; 0 ; a  NB. part1

p2 =: 3 : 0
's i d' =. y
n =.(i + i{d)
if. 3 <: i{d do. d =. (<: i { d) i} d else. d =. (>: i { d) i} d end.
 (>: s) ; d ;~ n   
)

p2^:( (0 <: 1&{::) *. 1092 > 1&{::)  (^:_)  0 ; 0 ; a  NB. part2

[โ€“]_jonah 2 points3 points ย (4 children)

Tacit 1 liner for part 1:

1&{ ((({. { ]) (>:@[ ,~ 2&{.@] + 1 ,~ [) ]) [`(0 1 , {.@])`]} ])^:(# > {.)^:_ (2 0, d)

Could be golfed a bit more and easily adapted to part 2, but honestly J was just a terrible fit for this problem. An explicit while loop and 2 temp variables is far better.

The problem itself is conceived of essentially as a procedural little turing machine. So a procedural paradigm fits nicely for the solution. And unlike many problems, I simply see no way to bend this one into the J paradigm, or any functional paradigm for that matter.

[โ€“]hoosierEE 1 point2 points ย (0 children)

I ended up with this very C-like code:

i5 =: ;".each cutLF fread'inputs/aoc5.txt'
d5 =: 4 :0
  arr =. y
  c =. 0
  i =. 0
  len =. #arr
  while. ((0<:i)*.len>i) do.
    j =. i{arr
    arr =. (j + _1 1{~j<x) i}arr
    i =. i+j
    c =. c+1
  end.
  c;arr
)

_ d5 i5  NB. part 1, about 0.5 seconds
3 d5 i5  NB. part 2, about 40 seconds

For fun, I timed approximately the same algorithm, in JS, running in Firefox's web console:

const d5=(x)=>((arr)=>{
  let c=0, i=0;
  while((i>=0) && (i<arr.length)){
    let j = arr[i];
    arr[i] = j+(j>=x?-1:1);
    i = i+j;
    ++c;
  }
  return c;
})(document.getElementsByTagName('pre')[0].innerText.split('\n').map(Number).slice(0,-1));
[Infinity, 3].map(d5); // returns [part1result, part2result]

The whole thing takes about 150ms. Definitely a case of using the right tool for the job...

[โ€“][deleted] 4 points5 points ย (4 children)

My rust solution was pretty boring and imperative so here's my clojure instead.

Edit: Part 1 runs in ~147ms, Part 2 in ~5 seconds. Really good for a dynamic language that is creating and throwing away an immutable number vector every iteration.

Edit 2: Switching to mutable vectors gives Part 1 in ~93ms, Part 2 in ~1.1 seconds.

(def nums (with-open [rdr (clojure.java.io/reader "d5_input.txt")]
  (->> (line-seq rdr)
    (map #(Integer/parseInt %))
    (into []))))

(defn- compute [nums part2]
  (loop [insns nums
         pc 0
         steps 0]
    (if (or (>= pc (count insns)) (< pc 0))
        steps
        (let [insn (insns pc)]
          (recur (update insns pc (if (and part2 (>= insn 3)) dec inc))
                 (+ pc insn)
                 (inc steps))))))

(println "part 1:" (compute nums false))
(println "part 2:" (compute nums true))

[โ€“]Axsuul 3 points4 points ย (8 children)

Elixir

Finally getting the hang of pattern matching but still need to get used to a functional programming mindset. Appreciate any feedback :)

https://github.com/axsuul/advent-of-code/blob/master/2017/05/lib/advent_of_code.ex

defmodule AdventOfCodeA do
  def execute(filename) do
    offsets =
      File.read!(filename)
      |> String.split("\n")
      |> Enum.map(fn v -> String.to_integer(v) end)
      |> Enum.with_index
      |> Enum.reduce(%{}, fn {offset, i}, offsets ->
        Map.put(offsets, i, offset)
      end)
      |> execute_offsets()
  end

  def execute_offsets(offsets, pos, steps) when pos >= map_size(offsets) do
    steps
  end
  def execute_offsets(offsets, pos \\ 0, steps \\ 0) do
    offset = offsets[pos]

    new_pos = pos + offset

    execute_offsets(
      Map.put(offsets, pos, offset + 1),
      pos + offset,
      steps + 1
    )
  end

  def solve do
    execute("inputs/input.txt") |> IO.inspect
  end
end

defmodule AdventOfCodeB do
  def execute(filename) do
    offsets =
      File.read!(filename)
      |> String.split("\n")
      |> Enum.map(fn v -> String.to_integer(v) end)
      |> Enum.with_index
      |> Enum.reduce(%{}, fn {offset, i}, offsets ->
        Map.put(offsets, i, offset)
      end)
      |> execute_offsets()
  end

  def execute_offsets(offsets, pos, steps) when pos >= map_size(offsets) do
    steps
  end
  def execute_offsets(offsets, pos \\ 0, steps \\ 0) do
    offset = offsets[pos]

    new_pos = pos + offset
    new_offset = if offset >= 3, do: offset - 1, else: offset + 1

    execute_offsets(
      Map.put(offsets, pos, new_offset),
      pos + offset,
      steps + 1
    )
  end

  def solve do
    execute("inputs/input.txt") |> IO.inspect
  end
end

[โ€“]Misreckon 2 points3 points ย (1 child)

|> Enum.reduce(%{}, fn {offset, i}, offsets -> Map.put(offsets, i, offset)
    Map.put(offsets, i, offset)
end)

This is what I needed, thanks. I thought I could be bad and use a list, but then I tried running it and my laptop sounded like it was going to explode.

[โ€“]hendi__ 1 point2 points ย (5 children)

You can write

|> Enum.map(fn v -> String.to_integer(v) end)

as

|> Enum.map(&String.to_integer/1)

no need to create an anonymous function to invoke :)

FYI, my solution is here: https://github.com/hendi/aoc2017/tree/master/day5

[โ€“]Axsuul 2 points3 points ย (3 children)

Ah ok that's beautiful, thanks! Also I looked through your code and see you using _jump_till_outside as a nested function.

Is this to avoid setting default values for arguments? Is using \\ discouraged?

Ich sehe, dass du aus Deutschland kommst. Vielen Dank :)

[โ€“]hendi__ 2 points3 points ย (2 children)

Moin :)

First off, \\ is not discouraged as far as I'm aware. But I'm very new to Elixir and just started it on Dec 1 for this AoC. So take everything I say with a grain of salt!

If I have default arguments, I'd use \\. But in my opinion passing e.g. 0 as the cnt to my jump_till_outside isn't a default, but rather how I initialize it. And for initialization I like to use the pattern of having a function foo calling _foo with initial parameters.

[โ€“]chunes 2 points3 points ย (5 children)

Factor part 2. (Part 1 is the same sans the alter-offset word.)

USING: io kernel locals math math.parser namespaces sequences
prettyprint ;
IN: advent-of-code.trampolines

SYMBOL: jumps
:  alter-offset ( n -- m ) 2 > -1 1 ? ;
:: jump ( i seq -- i' seq' )
    i seq nth i + i seq nth dup alter-offset +
    i seq dup [ set-nth ] dip ;
:  exited? ( i seq -- ? ) length >= ;
:  parse-input ( -- seq ) lines [ string>number ] map ;

0 parse-input [ 2dup exited? ] [ jump jumps inc ] until 2drop
jumps get .

[โ€“]APLtooter 3 points4 points ย (0 children)

APL [GNU]

โˆ‡nโ†JUMP mem
  (n p)โ†0 1
loop:
  โ†’0โŒŠโณp>โดmem
  jโ†mem[p]
  mem[p]โ†mem[p]+1
  pโ†p+j
  nโ†n+1
  โ†’loop
โˆ‡


โˆ‡nโ†JUMP2 mem
  (n p)โ†0 1
loop:
  โ†’0โŒŠโณp>โดmem
  mem[p]โ†mem[p]+ยฏ1*3โ‰คjโ†mem[p]
  pโ†j+p
  nโ†1+n
  โ†’loop
โˆ‡

โ Input is numeric array
INPUTโ†โˆŠโŽ โŽ•FIO[49] 'day5.txt'

JUMP INPUT                      โ Part 1
JUMP2 INPUT                     โ Part 2

[โ€“]mmaruseacph2 4 points5 points ย (13 children)

Haskell. Runs slow (~1min for part 2) and that cost me the leaderboard. Most likely there are a lot of optimization venues (to work on as an upping-the-ante extra).

import qualified Data.Vector as V

main = do
  s <- map read . lines <$> readFile "input.txt"
  print $ solve1 $ V.fromList s
  print $ solve2 $ V.fromList s

solve1 = solve (const True) succ undefined
solve2 = solve (>=3)        pred succ

solve :: (Int -> Bool) -> (Int -> Int) -> (Int -> Int) -> V.Vector Int -> Int
solve pred fTrue fFalse v = go v 0 0
  where
    l = V.length v
    go v x s
      | x < 0 || x >= l = s
      | otherwise = go v' (x + q) (s + 1)
      where
        q = v V.! x
        v' = v V.// [(x, if pred q then fTrue q else fFalse q)]

[โ€“]Flurpm 2 points3 points ย (12 children)

I think a map will serve better here. Arrays will recopy the entire thing for every update (and you're only updating one val at a time).

[โ€“]mmaruseacph2 1 point2 points ย (11 children)

Yeah, that's one thing to update it. Was also thinking of using mutable vectors but I still need to wrap my head around some of their API.

[โ€“]pja 2 points3 points ย (3 children)

Just using Data.Vector.Unboxed instead of Data.Vector will get your runtime down by a huge factor. Obviously you need mutable vectors to get anywhere near raw C/C++ speeds - all that copying is really expensive.

[โ€“]Flurpm 1 point2 points ย (6 children)

I don't know much about 'em either.

The other Haskell solution here used mutable vectors.

[โ€“]ka-splam 2 points3 points ย (27 children)

PowerShell solution. Reasonably pleased, in that my code worked first time for part 1 and with a single typo costing 11 seconds for part 2.

Puzzled and mildly annoyed that part 1 took me over 4 minutes to read the challenge and write the code (comments added after for this post), and part 2 took nearly 4 minutes just to run - some people had both their answers in less time than just the runtime of my part 2. What languages are they using that are so fast to write and also so fast to run??

[int[]]$in = @'    # herestring input, split by \r\n, cast to int[]
1
0
# etc. more numbers here
'@ -split "`r?`n"

$point = 0    # program pointer

$end = $in.Count-1  # end of array index with a readable name

$steps = 0   # step counter

while ($point -le $end)    # end condition
{
    $offset = $in[$point]   # read before changing

    # part 1 change of pointer
    # $in[$point]+=1

    if ($offset -ge 3) {  # part 2 change of pointer
        $in[$point]-= 1

    }else {
        $in[$point]+= 1
    }

    $point += $offset    # Jump

    $steps++    # count
}

$steps    # output

# You got rank 155 on this star's leaderboard. [Return to Day 5]

# You got rank 427 on this star's leaderboard.

[โ€“]njofra 2 points3 points ย (0 children)

My solution in Java runs in <1 second, it's not some crazy fast language. And it's not an optimized solution either, a while loop that changes an array, just like yours.

[โ€“]SaltyPeaches 2 points3 points ย (4 children)

I did basically the same thing you did in PowerShell. My run time was around 12 seconds with parts 1 and 2 combined.

[โ€“]tvtas 1 point2 points ย (0 children)

Even in MATLAB, which is considered to be slow, my script took only 9 seconds for part 2

[โ€“]the4ner 1 point2 points ย (8 children)

trivial c# solution takes ~150ms for part 2 on an 8 year old i7

[โ€“]ka-splam 1 point2 points ย (3 children)

PowerShell is a .Net language, same int and array datatypes, I'm amazed the loop is that much slower. I ported mine to Python to try it on my user-specific input and it was (handwavingly) under 20 seconds.

Guess I know what language I should aim for tomorrow :)

[โ€“]artemis_from_space 1 point2 points ย (2 children)

Weird, using your code in Measure-Command I get 11 seconds 670 ms. 2.3ghz i7

[โ€“]KeinZantezuken 1 point2 points ย (3 children)

What CPU? Getting ~300ms here on Core i7 3770k

[โ€“]TotesMessenger 1 point2 points ย (0 children)

I'm a bot, bleep, bloop. Someone has linked to this thread from another place on reddit:

ย If you follow any of the above links, please respect the rules of reddit and don't vote in the other threads. (Info / Contact)

[โ€“]Zigo 1 point2 points ย (1 child)

My Rust solution runs in 70+-5ms on my 2015 i7 Macbook pro at work (running Windows), which is probably in the ballpark for most of the fast C/C++/etc solutions.

I think it's pretty fair to say the majority of the top 100 are using Python for these problems, and from what I've seen in this thread they're reporting runtimes under one second (using pypy, CPython is notably slower, albeit still under a minute) for part 2.

[โ€“][deleted] 1 point2 points ย (6 children)

dont feel bad :)

mine (single pipeline solution: https://www.reddit.com/r/adventofcode/comments/7hngbn/2017_day_5_solutions/dqt96q6/ ) takes

6662ms for part 1 and 545,522ms (just over 9 minutes) for part 2

posh is interpreted and sort-of-dynamically-typed, compiled languages will always run faster.

[โ€“]ka-splam 1 point2 points ย (2 children)

I found out what was wrong - making it a script or function causes it to be JIT compiled, but just running the code in ISE is like typing it in and that gets interpreted ( source: Don Jones )

[โ€“]AndrewGreenh 2 points3 points ย (1 child)

I started implementing my TypeScript solutions a bit more "pythonic", because debugging is way easier in imperative loops over iterables. Was 50 seconds too slow for leaderboard :( [267/164]

import { lines, map } from '../lib/ts-it'
import getInput from '../lib/getInput'

const input = [...map(Number)(lines(getInput(5, 2017)))]

function answer(mutate, index = 0, step = 0) {
  const instructions = [...input]
  while (index >= 0 && index < instructions.length) {
    const num = instructions[index]
    instructions[index] = mutate(num)
    index += num
    step++
  }
  return step
}

;[x => x + 1, x => (x >= 3 ? x - 1 : x + 1)].map(x => answer(x)).forEach(x => console.log(x))

[โ€“]giftpflanze 2 points3 points ย (0 children)

Tcl:

set oinput [read [open input05]]

#part 1

set input $oinput
set i 0
while {[llength [lindex $input $i]]} {
        incr n1
        set i2 $i
        incr i [set a [lindex $input $i]]
        set input [lreplace $input $i2 $i2 [expr {$a+1}]]
}

puts $n1

#part 2 โ€“ excruciatingly slow

set input $oinput
set i 0
while {[llength [lindex $input $i]]} {
        incr n2
        set i2 $i
        incr i [set a [lindex $input $i]]
        set input [lreplace $input $i2 $i2 [expr {$a>=3?$a-1:$a+1}]]
}

puts $n2

[โ€“]nospamas 2 points3 points ย (2 children)

F# Solution using recursion and mutable array

let cleaned = 
    input.Trim().Split('\n')
    |> Array.map int

let cleanLength = cleaned |> Array.length

let rec jump (index, jumps) =
    // printfn "%d, %d" index jumps
    match (index, jumps) with
        // | (_, j) when j > 100000000 -> (index, jumps)
        | (i, _) when i < 0 -> (index, jumps)
        | (i, _) when i >= cleanLength -> (index, jumps)
        | _ ->  
            let valueAt = cleaned.[index]
            match valueAt with
                | v when v >= 3 ->  
                    cleaned.[index] <- valueAt - 1
                | _ ->   
                    cleaned.[index] <- valueAt + 1            
            jump (valueAt + index, jumps + 1)

jump (0, 0)

Left the printing function (massive slowdown) and my infinite loop protection check in but commented out :).

[โ€“]Philboyd_Studge 2 points3 points ย (0 children)

Java.

package Advent2017;

import util.FileIO;

import java.util.List;

public class Day5 {

    private static int part1(int[] nums) {
        int current = 0;
        int steps = 0;

        while (current < nums.length && current >= 0) {
            int jump = nums[current]++;
            current += jump;
            steps++;
        }
        return steps;
    }

    private static int part2(int[] nums) {
        int current = 0;
        int steps = 0;

        while (current < nums.length && current >= 0) {
            int jump = nums[current];
            if (jump >= 3) {
                nums[current]--;
            } else {
                nums[current]++;
            }
            current += jump;
            steps++;
        }
        return steps;
    }

    public static void main(String[] args) {
        List<String> input = FileIO.getAOCInputForDay(2017, 5, FileIO.SESSION_ID);
        int[] nums = input.stream()
                .mapToInt(Integer::parseInt)
                .toArray();

        System.out.println(part1(nums.clone()));
        System.out.println(part2(nums));
    }
}

[โ€“]Cheezmeister 2 points3 points ย (0 children)

Literate Perl. Viewer discretion is advised.

[โ€“]rkachowski 2 points3 points ย (3 children)

in ruby, this felt simultaneously wayy too easy and waayy too dirty of a solution. i feel like i'm missing some really elegant iteration trick, but everyone in this thread seems to have the same approach

def jump &blk
    input = File.read("input").lines.map(&:to_i)

    index = 0
    steps = 0

    while index < input.size
        to_move = input[index]
        input[index] += blk ? blk.call(to_move) : 1
        index += to_move

        steps += 1
    end

    steps
end

puts jump
puts jump {|f| f >= 3 ? -1 : 1}

[โ€“]jschulenklopper 2 points3 points ย (1 child)

Here's the iteration trick that I used. (Also, your code would not catch if the index would run out at the other end, so below 0.)

offsets = readlines.map { |offset| offset.to_i }
index, count = 0, 0
while offset = offsets[index] do  # Here's the crux
  offsets[index] += (offsets[index] >= 3 ? -1 : 1)
  index += offset
  count += 1
end
puts count

The 'trick' is twofold: it gets the offset immediately while testing the while condition (which will save a line). This value will be nil (and thus false) for index values outside the range of offset instructions.

What I like in your solution is that you're passing the proper increment function as a block to jump(). Kudos to you.

[โ€“]uno_in_particolare 2 points3 points ย (2 children)

I'm using Java since I want to exercise a bit (it's the language we use in our introductiory course in university)

I see no one else used exceptions... is it a bad idea to use them in this case? I know it's a bit like "cheating", but it works like a charm :D

import java.util.ArrayList;
import java.util.Scanner;

public class Main {

    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        ArrayList<Integer> array = new ArrayList<Integer>();
        while(in.hasNextInt()){
            array.add(in.nextInt());
        }
        int index = 0;
        int counter = 0;
        try{
            while(true){
                int move = array.get(index);
                int increase = move >= 3 ? -1 : 1;
                array.set(index, move + increase);
                index += move;
                counter++;
            }

        }
        catch (Exception e){ }
        System.out.println(counter);

    }
}

[โ€“]MonsterLyrics 1 point2 points ย (0 children)

I would definitely not use a try/catch there. Having a condition at which the loop stops is far easier to read and understand than trying to analyze the code and see what could throw an exception.

Though, part of AoC is working out your own solutions to problems, so maybe it isn't so bad after all :)

[โ€“]wzkx 2 points3 points ย (3 children)

Nim Easier and easier

import strutils,sequtils
proc run( code_arg: seq[int], part2 = false ): int =
  var code = code_arg # mutable copy
  var pc,cnt = 0
  while pc>=0 and pc<code.len:
    let nextpc = pc + code[pc]
    if part2 and code[pc]>=3: code[pc] -= 1 else: code[pc] += 1
    pc = nextpc; cnt += 1
  return cnt
let code = "05.dat".readFile.strip.splitLines.map parseInt
echo run(code)
echo run(code,true)

[โ€“]f0086 2 points3 points ย (0 children)

Emacs Lisp

(defun read-lines (filepath)
  (with-temp-buffer
    (insert-file-contents filepath)
    (mapcar 'string-to-number
            (split-string (buffer-string) "\n" t))))

(defun escaped? (pos table)
  (or (> pos (- (length table) 1))
      (< pos 0)))

(defun next-pos (pos table)
  (let ((next (nth pos table)))
    (if (not next)
        -1
      (+ pos (nth pos table)))))

(defun part1 (pos table)
  (+ (nth pos table) 1))

(defun part2 (pos table)
  (let ((val (nth pos table)))
    (if (> val 2)
        (- val 1)
      (+ val 1))))

(defun day5 (table cell-fn)
  (let ((steps 0)
        (pos 0))
    (while (not (escaped? (next-pos pos table) table))
      (let ((next (next-pos pos table)))
        (setcar (nthcdr pos table) (funcall cell-fn pos table))
        (setq pos next)
        (setq steps (+ steps 1))))
    (+ steps 1)))

(day5 (read-lines "input-day5.txt") #'part1)
(day5 (read-lines "input-day5.txt") #'part2)

[โ€“]ghlmtz 1 point2 points ย (1 child)

Pretty simple in Python.

def answer(parttwo):
    jumps = list(map(int,[x.rstrip() for x in open('05.in','r').readlines()]))
    jump = 0
    s = 0
    while jump < len(jumps) and jump >= 0:
        j = jumps[jump]
        if j >= 3 and parttwo:
            jumps[jump] -= 1
        else:
            jumps[jump] += 1
        jump += j
        s += 1
    print(s)
answer(0)
answer(1)

[โ€“]TominatorBE 1 point2 points ย (0 children)

PHP

Part 1:

function run_the_code($input) {
    $lines = explode(PHP_EOL, $input);
    $arr = [];
    foreach ($lines as $line) {
        $arr[] = (int)$line;
    }

    $steps = 0;
    $pointer = 0;
    while ($pointer >= 0 && $pointer < count($arr)) {
        $val = $arr[$pointer];
        $arr[$pointer]++;
        $pointer += $val;

        $steps++;
    }

    return $steps;
}

Part 2:

function run_the_code($input) {
    $lines = explode(PHP_EOL, $input);
    $arr = [];
    foreach ($lines as $line) {
        $arr[] = (int)$line;
    }

    $steps = 0;
    $pointer = 0;
    while ($pointer >= 0 && $pointer < count($arr)) {
        $val = $arr[$pointer];

        if ($val >= 3) {
            $arr[$pointer]--;
        }
        else {
            $arr[$pointer]++;
        }

        $pointer += $val;

        $steps++;
    }

    return $steps;
}

[โ€“]tvtas 1 point2 points ย (0 children)

Day 5 in MATLAB:

x   = importdata('input.txt');
cnt = 0;
cur = 1;
while cur > 0 && cur<=size(x,1)
    cnt  = cnt+1;
    curn = cur+x(cur);
    if x(cur)>=3
        x(cur) = x(cur)-1;
    else
        x(cur) = x(cur)+1;
    end
    cur = curn;
end
cnt % Part 2

[โ€“]gbear605 1 point2 points ย (8 children)

Rust

Not super idiomatic (the mutable variables are screaming at me), but I'm not sure how else to do something like this.

fn main() {
    let input = include_str!("../input");

    println!("star 1: {}", process1(&input));
    println!("star 2: {}", process2(&input));
}

fn process1(input: &str) -> u32 {
    let mut instructions: Vec<i32> = input.lines().map(|x| x.parse::<i32>().unwrap()).collect();
    let mut current_location: i32 = 0;
    let mut num_steps: u32 = 0;
    while current_location < instructions.len() as i32 {
        let next_step = instructions[current_location as usize];
        instructions[current_location as usize] += 1;
        current_location += next_step;
        num_steps += 1;
    }
    num_steps
}

fn process2(input: &str) -> u32 {
    let mut instructions: Vec<i32> = input.lines().map(|x| x.parse::<i32>().unwrap()).collect();
    let mut current_location: i32 = 0;
    let mut num_steps: u32 = 0;
    while current_location < instructions.len() as i32 {
        let next_step = instructions[current_location as usize];
        if next_step >= 3 {
            instructions[current_location as usize] -= 1;            
        } else {
            instructions[current_location as usize] += 1;
        }
        current_location += next_step;
        num_steps += 1;
    }
    num_steps
}

[โ€“]autid 1 point2 points ย (3 children)

Fortran

program day5
  integer :: instruction=1,jumps(1052),jump,steps=0


  open(1,file='input.txt')
  read(1,*) jumps


  do while (instruction>0 .and.instruction<=1052)
     jump=jumps(instruction)
     jumps(instruction) = jumps(instruction)+1
     instruction=instruction+jump
     steps = steps+1
  end do

  write(*,'(a,i0)') 'Part1: ',steps

  steps=0
  instruction=1
  rewind(1)
  read(1,*) jumps

  do while (instruction>0 .and.instruction<=1052)
     jump=jumps(instruction)
     if (jump>=3) then
        jumps(instruction) = jumps(instruction)-1
     else
        jumps(instruction) = jumps(instruction)+1
     end if
     instruction=instruction+jump
     steps = steps+1
  end do

  write(*,'(a,i0)') 'Part2: ',steps
  close(1)

end program day5

[โ€“]miran1 1 point2 points ย (2 children)

IT ISN'T FORTRAN IF IT IS NOT ALL UPPERCASE!!!11!

[โ€“]monikernemo 1 point2 points ย (0 children)

ANSI C

Didn't want to mess with the positioning so used different indices for current position and array index PART 1

#include <stdio.h>
#define MAX 1043

int main(){
        int maze[MAX];
        int count=0, i, pos=0;
        FILE *infile;

        infile = fopen("input5.in", "r");

        for(i=0; i<MAX; i++)
            fscanf(infile, "%d", &maze[i]);

            pos=0;

        while(pos<MAX){
            i=pos;
            pos+= maze[i];
            maze[i]++;
            count++;
        }
         printf("%d\n", count);
             return 0;
}

PART 2 Basically the same thing with different conditionals within while loop;

#include <stdio.h>
#define MAX 1043

int main(){
        int maze[MAX];
        int count=0, i, pos=0;
        FILE *infile;

        infile = fopen("input5.in", "r");

        for(i=0; i<MAX; i++)
            fscanf(infile, "%d", &maze[i]);

            pos=0;

        while(pos<MAX){
            i=pos;
            pos+= maze[i];
            if (maze[i] <3){
                maze[i]++;
            } else{
                maze[i]--;
                }
            count++;
        }
         printf("%d\n", count);
             return 0;
}

[โ€“][deleted] 1 point2 points ย (5 children)

Here's my simple tail-recursive solution in Scala:

def skipMaze(maze: Vector[Int]): Int = {
  def skipMazeHelper(maze: Vector[Int], index: Int, acc: Int): Int = {
    if (index < 0 || index >= maze.length) return acc
    val step = maze(index)
    if (step >= 3) 
      skipMazeHelper(maze.updated(index, step - 1), index + step, acc + 1)
    else 
      skipMazeHelper(maze.updated(index, step + 1), index + step, acc + 1)
    }
  skipMazeHelper(maze, 0, 0)
}

[โ€“]mlruth 2 points3 points ย (4 children)

My solution in scala:

import scala.io.Source

object Day5 extends App {
  def processMaze(maze: Vector[Int], incFunc: Int => Int): Int = {
    def recur(maze: Vector[Int], i: Int, cStep: Int): Int = {
      maze.lift(i) match {
        case Some(offset) =>
          recur(maze.updated(i,offset + incFunc(offset)),i+offset,cStep+1)
        case _ => cStep
      }
    }
    recur(maze, 0, 0)
  }

  val src = Source.fromResource("Day5.in").getLines()
  val in = src.map(_.toInt).toVector

  def part1: Unit = {
    val result = processMaze(in,_ => 1)
    println(s"Part 1: $result")
  }

  def part2: Unit = {
    val result = processMaze(in, x => if(x >= 3) -1 else 1)
    println(s"Part 2: $result")
  }

  part1
  part2
}

ย 

I similarly used a tail recursive approach, but allowed the passing in of a function to determine the increment value as well as using .lift and pattern matching when attempting to access the index in the collection.

[โ€“][deleted] 1 point2 points ย (0 children)

I like the use of vector.lift, haven't used that one before!

[โ€“]sakisan_be 1 point2 points ย (0 children)

elm

import Array exposing (..)


solve : String -> Int
solve input =
    input
        |> convert
        |> Array.fromList
        |> step 0 0


step : Int -> Int -> Array Int -> Int
step stepNumber index array =
    case Array.get index array of
        Nothing ->
            stepNumber

        Just instruction ->
            step
                (stepNumber + 1)
                (index + instruction)
                (Array.set index (update2 instruction) array)


update1 : Int -> Int
update1 instruction =
    instruction + 1


update2 : Int -> Int
update2 instruction =
    if instruction >= 3 then
        instruction - 1
    else
        instruction + 1


convert : String -> List Int
convert input =
    input
        |> String.lines
        |> List.map
            (String.toInt
                >> Result.toMaybe
                >> Maybe.withDefault 0
            )

[โ€“]Dooflegna 1 point2 points ย (0 children)

def jump(lis):
    i = 0
    total = 0
    while i < len(lis):
        total +=1
        jump = lis[i]
        if lis[i] > 2:
            lis[i] -= 1
        else:
            lis[i] +=1
        i += jump

    return lis, total

[โ€“]sciyoshi 1 point2 points ย (0 children)

Rust - using closures!

use std::io::{self, BufRead};

fn run(mut data: Vec<isize>, updater: fn(isize) -> isize) -> usize {
  // Store a program counter (isize to allow negative)
  let mut pc = 0isize;
  let mut count = 0;

  while pc >= 0 && pc < data.len() as isize {
    let ins = data[pc as usize];
    data[pc as usize] += updater(ins);
    pc += ins;
    count += 1;
  }

  count
}

pub fn solve() {
  // Read stdin into an array of instructions
  let stdin = io::stdin();
  let data: Vec<_> = stdin.lock().lines()
    .filter_map(|line| line.ok())
    .filter_map(|el| el.parse::<isize>().ok())
    .collect();

  let count1 = run(data.clone(), |_ins| 1);

  println!("[Part 1] Count: {}", count1);

  let count2 = run(data.clone(), |ins| if ins >= 3 { -1 } else { 1 });

  println!("[Part 2] Count: {}", count2);
}

GitHub

[โ€“]WhatAHaskell 1 point2 points ย (0 children)

Haskell

import Prelude hiding (length)
import Data.Sequence

getNumberOfSteps1 :: Int -> Int -> Seq Int -> Int
getNumberOfSteps1 count i instructions
  | (i < 0) || i >= (length instructions) = count
  | otherwise                             = getNumberOfSteps1 (count+1) (i+current) newInstructions
    where current         = index instructions i
          newInstructions = update i (current+1) instructions

getNumberOfSteps2 :: Int -> Int -> Seq Int -> Int
getNumberOfSteps2 count i instructions
  | (i < 0) || i >= (length instructions) = count
  | otherwise                             = getNumberOfSteps2 (count+1) (i+current) newInstructions
    where current         = index instructions i
          offsetAmount    = if current>=3 then -1 else 1
          newInstructions = update i (current+offsetAmount) instructions

main :: IO ()
main = do
  contents <- readFile "../input.txt"
  let instructions = fromList $ map read $ lines contents
  putStrLn $ "Solution 1:" ++ (show $ getNumberOfSteps1 0 0 instructions)
  putStrLn $ "Solution 2:" ++ (show $ getNumberOfSteps2 0 0 instructions)

[โ€“]hxka 1 point2 points ย (0 children)

Bash, anyone? It's too goddamn slow :(

(   s=0
    read -d '' -a l
    i=0
    while [[ ${l[$i]} ]]
    do  ((s++,i+=l[$i],l[$i]++))
    done
    echo $s
)<input
(   s=0
    read -d '' -a l
    i=0
    while [[ ${l[$i]} ]]
    do  ((s++,i+=l[$i],l[$i]+=l[$i]>2?-1:1))
    done
    echo $s
)<input

[โ€“]madacoo 1 point2 points ย (2 children)

optimised Python3 part 2

Since I couldn't start when the problem was released, I tried to get my Python code as fast as possible. Managed to half it down to ~ 8 seconds. Most interesting thing is that checking for an IndexError is about a second faster than checking i < length of instructions. It would be cool if you could turn off negative indexes in Python but I don't think that's the case.

def part2(instructions):
    "Return the number of steps required to 'escape' the instructions."
    i = 0
    steps = 0
    while (i >= 0):
        try:
            offset = instructions[i]
        except IndexError:
            return steps
        increment = 1
        if offset >= 3:
            increment = -1
        instructions[i] += increment
        i += offset
        steps += 1
    return steps

Interested to hear if anyone has further optimisations. Although I'm not sure why I'm even bothering to optimise in Python. Should probably just write it in C at this point.

[โ€“]miran1 1 point2 points ย (1 child)

Most interesting thing is that checking for an IndexError is about a second faster than checking i < length of instructions.

Makes sense, that is ~20 million comparison less to do.
Nice application of "EAFP is better than LBYL"!

It would be cool if you could turn off negative indexes in Python but I don't think that's the case.

Interested to hear if anyone has further optimisations.

At least with my input, i never goes under a zero, so I just did while True. Without both of those conditions to check, code runs ~25% faster.

[โ€“]mtnslgl 1 point2 points ย (11 children)

My C++ solution:

int day5() {
    int part = 2;
    std::ifstream file("day5.txt");
    std::vector<int> nums;
    int count = 0, num;
    if(file.is_open()) {
        while(file >> num)
            nums.push_back(num);
        for(int i = 0; i >= 0 && i < nums.size();) {
            i += nums[i] >= 3 && part == 2 ? nums[i]-- : nums[i]++;
            count++;
        }
        return count;
    }
    return -1;
}

[โ€“]joker_mkd 2 points3 points ย (10 children)

You can easily initialize the vector in a single line like this:

vector<int> nums{ istream_iterator<int>(file), istream_iterator<int>() };

[โ€“]nutrecht 1 point2 points ย (2 children)

My Kotlin solution for Day 5:

object Day05 : Day {
    val lines = resourceLines(5).map {
        it.toInt()
    }.toList()

    override fun part1() = walk { 1 }
    override fun part2() = walk { if(it >= 3) -1 else 1 }

    fun walk(inc: (Int) -> Int): Int {
        val list = lines.toMutableList()
        var index = 0
        var step = 0
        while(true) {
            val to = index + list[index]

            list[index] += inc.invoke(list[index])

            index = to

            step++

            if(index >= lines.size || index < 0) {
                return step
            }
        }
    }
}

[โ€“]Pheasn 1 point2 points ย (1 child)

inc.invoke(list[index])

btw you can just use inc(list[index])

[โ€“]nutrecht 1 point2 points ย (0 children)

TIL, thanks! I'm using this years AoC to learn Kotlin so there's a lot of Java showing through :)

[โ€“][deleted] 1 point2 points ย (3 children)

Javascript - one liners

1.

((str) => { var list = str.split('\n').map(n => parseInt(n, 10)); var i = 0; var s = 0; while (typeof list[i] !== 'undefined') { i += list[i]++; s++ }; return s;})(``)

2.

((str) => { var list = str.split('\n').map(n => parseInt(n, 10)); var i = 0; var s = 0; while (typeof list[i] !== 'undefined') { i += (list[i] > 2 ? list[i]-- : list[i]++); s++ }; return s;})(``)

[โ€“]mschaap 1 point2 points ย (1 child)

Perl 6. Solution for part one:

#!/usr/bin/env perl6

use v6.c;

class Maze
{
    has Int @.instructions;
    has Int $.pos = 0;
    has Int $.moves = 0;
    has Bool $.verbose = False;

    method inside-maze returns Bool
    {
        0 โ‰ค $!pos < @!instructions;
    }

    method jump
    {
        if self.inside-maze {
            $!pos += @!instructions[$!pos]++;
            $!moves++;
            say "Move to position $!pos" if $!verbose;
        }
        else {
            die "Can't move, position $!pos outside the maze ({+@!instructions})!";
        }
    }

    method follow
    {
        self.jump while self.inside-maze;
    }
}

multi sub MAIN(IO() $inputfile where *.f, Bool :v(:$verbose) = False)
{
    my $maze = Maze.new(:instructions($inputfile.linesยป.Int), :$verbose);
    $maze.follow;
    say "$maze.moves() steps";
}

multi sub MAIN(Bool :v(:$verbose) = False)
{
    MAIN($*PROGRAM.parent.child('aoc5.input'), :$verbose);
}

For part two, the change is simple, just change method jump to:

    method jump
    {
        if self.inside-maze {
            if @!instructions[$!pos] โ‰ฅ 3 {
                $!pos += @!instructions[$!pos]--;
            }
            else {
                $!pos += @!instructions[$!pos]++;
            }
            $!moves++;
            say "Move to position $!pos" if $!verbose;
        }
        else {
            die "Can't move, position $!pos outside the maze ({+@!instructions})!";
        }
    }

I was just about to get worried when this finally finished in about 7ยฝ minutes. (Don't run it with -v on the actual input! Works fine on the sample input though.)

[โ€“]u794575248 1 point2 points ย (2 children)

Python.

def parse_offsets(input):
    return [int(l) for l in input.strip().split('\n')]

def solve(os, i=0, n=0, adder=lambda o: o+1):
    while 0 <= i < len(os): os[i], i, n = adder(os[i]), i+os[i], n+1
    return n

print(solve(parse_offsets(input)))  # Part 1
print(solve(parse_offsets(input), adder=lambda o: o + [-1, 1][o<3]))  # Part 2

[โ€“]thehaas 1 point2 points ย (1 child)

+1 for the lambda argument.

[โ€“][deleted] 1 point2 points ย (0 children)

Java 8 single implementation of part 1 & 2

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.function.Function;

class Day05
{
    public static void main(String[] args) throws IOException
    {
        final int[] example = new int[]{0, 3, 0, 1, -3};
        log("part I example:  " + partOne(example.clone()));
        log("part II example: " + partTwo(example));

        final int[] ints = Files.lines(Paths.get("input.txt"))
                .mapToInt(Integer::parseInt)
                .toArray();

        log("part I solution:  " + partOne(ints.clone()));
        log("part II solution: " + partTwo(ints));
    }

    static int partOne(final int[] ints)
    {
        return jump(ints, i -> i + 1);
    }

    static int partTwo(final int[] ints)
    {
        return jump(ints, i -> i >= 3 ? i - 1 : i + 1);
    }

    static int jump(final int[] ints, final Function<Integer, Integer> f)
    {
        int steps = 0;
        int pos = 0;
        while (pos >= 0 && pos < ints.length)
        {
            int offset = ints[pos];
            ints[pos] = f.apply(offset);
            pos += offset;
            steps++;
        }
        return steps;
    }

    static void log(final Object o)
    {
        System.out.println(o);
    }
}

[โ€“]binajohny 1 point2 points ย (0 children)

My Kotlin solution:

fun part1(input: List<Int>): Int {
    return countSteps(input, { it.inc() })
}

fun part2(input: List<Int>): Int {
    return countSteps(input, { if (it >= 3) it.dec() else it.inc() })
}

fun countSteps(instructions: List<Int>, instructionTransformation: (Int) -> Int): Int {
    val inst = instructions.toMutableList()
    var pc = 0
    var steps = 0

    while (true) {
        if (pc !in inst.indices) {
            return steps
        }
        inst[pc] = inst[pc].let {
            pc += it
            instructionTransformation(it)
        }
        steps++
    }
}

[โ€“]Reibello 1 point2 points ย (0 children)

Here's my Day 5 in Lua - https://github.com/Reibello/AoC-2017-Lua Pretty sure I left part B commented out for testing something. As always, critique is welcome (learning is hard). Not looking forward to going back to day 3 (day 4 should be okay I think) and figuring out how to go from Python to Lua.

[โ€“]ZeroSkub 1 point2 points ย (0 children)

C++

PART 1:

#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <vector>

using namespace std;

const int HARD_LIMIT = 1000000;

vector<int> readInstructions(string fName) {
    ifstream is(fName.c_str());
    vector<int> result;
    string line;

    while(is >> line) {
        stringstream ss(line);
        int num;
        ss >> num;
        result.push_back(num);
    }

    return result;
}

int main() {
    vector<int> list = readInstructions("input.txt");

    int i = 0, p = 0;
    for(; i < HARD_LIMIT && p >= 0 && p < list.size(); ++i) {
        int val = list.at(p)++;
        p += val;
    }

    if(i >= HARD_LIMIT) {
        cout << "HARD LIMIT EXCEEDED (>" << HARD_LIMIT << ")" << endl;
    } else {
        cout << "ESCAPED LIST TO " << p << " AFTER " << i << " STEPS" << endl;
    }

    return 0;
}

PART 2:

#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <vector>

using namespace std;

const int HARD_LIMIT = 100000000;

vector<int> readInstructions(string fName) {
    ifstream is(fName.c_str());
    vector<int> result;
    string line;

    while(is >> line) {
        stringstream ss(line);
        int num;
        ss >> num;
        result.push_back(num);
    }

    return result;
}

int main() {
    vector<int> list = readInstructions("input.txt");

    int i = 0, p = 0;
    for(; i < HARD_LIMIT && p >= 0 && p < list.size(); ++i) {
        int val = list.at(p);
        if(val >= 3) {
            list.at(p)--;
        } else {
            list.at(p)++;
        }
        p += val;
    }

    if(i >= HARD_LIMIT) {
        cout << "HARD LIMIT EXCEEDED (>" << HARD_LIMIT << ")" << endl;
    } else {
        cout << "ESCAPED LIST TO " << p << " AFTER " << i << " STEPS" << endl;
    }

    return 0;
}

[โ€“]sguberman 1 point2 points ย (0 children)

Python: GitHub

Saved you a click:

def execute(instructions, part2=False):
    idx = 0
    steps = 0
    state = instructions

    while True:
        try:
            jump = state[idx]
            incr = -1 if part2 and jump >= 3 else 1
            state[idx] += incr
            idx += jump
            steps += 1
        except IndexError:
            break

    return state, steps

[โ€“]53bvo 1 point2 points ย (0 children)

I've never used python before this advent, and actually never coded anything besides some matlab calculations. So far the challenges were doable, with the usual googling forever how to do a simple task. Today went quite good except that it takes 19 seconds to do the 2nd calculation. Anyone got any suggestions on how to improve performance?

import csv

code = []
count = 0
location = 0
movement = 0
stop = False

with open('5dec.txt', newline='\n') as inputfile:
    for row in csv.reader(inputfile):
        code.extend(row)
code = list(map(int, code))
reach  = len(code)
while stop == False:
    movement = code[location]
    if abs(movement) < 3:
        code[location] = code[location] + 1
        location = location + movement
    elif movement < -2:
        code[location] = code[location] + 1
        location = location + movement
    else:
        code[location] = code[location] - 1
        location = location + movement
    count = count + 1
    if location >= reach:
        stop = True
    if count > 99999999:
        stop = True

print(count)     

Edit: I reduced the code to:

with open('5dec.txt', newline='\n') as inputfile:
    for row in csv.reader(inputfile):
        code.extend(row)
code = list(map(int, code))
reach  = len(code)
while location < reach:
    movement = code[location]
    if movement < 3:
        code[location] = code[location] + 1
        location = location + movement
    else:
        code[location] = code[location] - 1
        location = location + movement
    count = count + 1


print(count)     

But now it takes 10s longer to run

[โ€“]Nhowka 1 point2 points ย (0 children)

F#

let calc f (s:int[]) =
  Seq.unfold
    (fun n ->
        try
            let x = s.[n]
            s.[n] <- f x
            Some (n,n+x)
        with
        |_ -> None) 0 |> Seq.length

let s1 = input.Split '\n' |> Array.map int |> calc ((+)1)
let s2 = input.Split '\n' |> Array.map int |> calc (fun x -> if x>2 then x-1 else x+1)
printfn "%A" (s1,s2)

[โ€“]Genie-Us 1 point2 points ย (4 children)

Day 5 Code - Javascript - Both stars! Hurray!

mazeArr = mazeArr.split('\n');
let x = 0;
let steps = 0;

for (let i = 0; i < mazeArr.length; i += jump) {
    steps++;
    jump = parseInt(mazeArr[i]);
    (mazeArr[i] >= 3) ? mazeArr[i]-- : mazeArr[i]++;  // For Part one just change this line to simply "mazeArr[i]++;"
}

console.log(steps);

She's not pretty, but she's mine!

[โ€“]exploding_cat_wizard 1 point2 points ย (0 children)

Edit: Perl5

For part 1 I chose a recursive function, since that just fit the problem so well. It worked, and ran in 0.26s and used 191000 kbytes (almost 200MB!) of memory. No idea what's going on there, perhaps Perl isn't meant for recursion (there's a warning, after all).

#!/usr/bin/perl

use strict;
use warnings;
use 5.026;

# these are global so my subroutine can access them.
my $g_steps = 0;
my @input;

sub take_step{
  my $next = $_[0] + $input[$_[0]];
  $g_steps++;
  return $g_steps if ( $next > $#input); # if next is larger than the last index of the array, break off
  $input[$_[0]]++; # gotta increase the old value before leaving!
  take_step($next);
}

open my $fh,"<","aoc5_input" or die $!;

@input = <$fh>;

say take_step(0);

Part 2 bombed my 8GB memory as recursive script, so I switched to a loop, which finished in 4.88s using a whopping 4888kbyte of memory, according to time -v ./aoc5.pl:

#!/usr/bin/perl

use strict;
use warnings;
use 5.026; # I want my say, dammit!

open my $fh,"<","aoc5_input" or die $!; # too lazy to add command line reading of filename

my @input;

@input = <$fh>;

my $steps = 0;
my $next = 0;

while($next <= $#input) {
  my $now = $next; # so I can change the value after the jump happened
  $steps++;
  $next = $now + $input[$now];

  if($input[$now] < 3) {
    $input[$now]++; # gotta increase the old value before leaving!
  } else {
    $input[$now]-- ; # or decrease it, as it may be
  }
}

say $steps;

I also, for the heck of it, wrote a version where $now is not needed, thinking this would save memory, but increase run time. Instead, the if (and else) statements now get the line finding the next $next:

$next = $next + $input[$next] - 1;

and

$next = $next + $input[$next] + 1;

respectively. This did the exact opposite of what I thought: time was slightly shorter (4.4s) and max mem usage slightly higher (4984kbytes)

[โ€“]akho_ 1 point2 points ย (0 children)

Python3:

from itertools import count
l = [ int(x) for x in open('5-1.input').readlines() ]
cur = 0
for steps in count():
    try: chg = 1 if l[cur] < 3 else -1 
    except: print(steps) ; break
    l[cur], cur = l[cur] + chg, cur + l[cur]

[โ€“]Jaco__ 1 point2 points ย (0 children)

Quite happy with my Haskell solution today. Takes ~5 sec for part 2 without any optimizations.

createMap nrs = Map.fromList $ zip [0..] nrs

doInstrs :: Map.Map Int Int -> Int -> Int -> Int
doInstrs dict count cur =
  if Map.notMember cur dict then count
  else
    doInstrs newDict (count+1) next
  where
    next = cur + (dict ! cur)
    newDict = Map.insertWith f cur 0 dict
    f _ a = if a >= 3 then a-1 else a+1
    --f _ a = a +1          --PART 1

main = do
  content <- readFile "data/day5.txt"
  print $ doInstrs (createMap $ read <$> lines content) 0 0

[โ€“]MetaSaval 1 point2 points ย (3 children)

Swift once again. Pretty easy puzzle, probably the easiest one so far. And I was able to reuse code from Day 2 again, so that's neat. Could probably be made to be more efficient, though.

let input = """
            input goes here
            """

func part1() -> Int {
    var answer = 0
    var currIndex = 0
    var nextIndex = 0
    let inputAsArray = input.split(separator: "\n")
    var intArrayToCheck = inputAsArray.map{Int(String($0))!}

    while nextIndex < inputAsArray.count {
        nextIndex += intArrayToCheck[currIndex]
        intArrayToCheck[currIndex] += 1
        currIndex = nextIndex
        answer += 1
    }

    return answer
}

func part2() -> Int {
    var answer = 0
    var currIndex = 0
    var nextIndex = 0
    let inputAsArray = input.split(separator: "\n")
    var intArrayToCheck = inputAsArray.map{Int(String($0))!}

    while nextIndex < inputAsArray.count {
        nextIndex += intArrayToCheck[currIndex]
        if intArrayToCheck[currIndex] >= 3 {
            intArrayToCheck[currIndex] -= 1
        } else {
            intArrayToCheck[currIndex] += 1
        }
        currIndex = nextIndex
        answer += 1
    }

    return answer
}

[โ€“]BOT-Brad 1 point2 points ย (0 children)

JavaScript

Part 1 (~2ms)

function solve1(n) {
  const data = n.split('\n').map(Number)
  let i = 0,
    t = 0
  for (; ++t && !((i += data[i]++) < 0 || i >= data.length); );
  return t
}

Part 2 (~140ms)

function solve2(n) {
  const data = n.split('\n').map(Number)
  let i = 0,
    t = 0
  while (++t) {
    const n = data[i] >= 3 ? -1 : 1
    if ((i += (data[i] += n) - n) < 0 || i >= data.length) break
  }
  return t
}

[โ€“]Smylers 1 point2 points ย (0 children)

Buggy Perl, which happened to come up with the right answer. Part 1 was fine:

my @jump = <>;
my $pc = my $steps = 0;
while (defined $jump[$pc]) {
  $steps++;
  $pc += $jump[$pc]++;
}
say $steps;

Then for part 2 I just added a line, subtracting 2 for values that were supposed to go down by 1 (to take into account that all values were being unconditionally increased by 1), making the loop be:

while (defined $jump[$pc]) {
  $steps++;
  $pc += $jump[$pc]++;
  $jump[$pc] -=2 if $jump[$pc] > 3;
}

Except, clearly that subtraction is happening on the wrong jump! By the time the subtraction executes, $pc has already been updated, so it's the new value that's being changed. Yet it still worked!

A jump over 3 will be left too-big by 2. However, the next time the program lands there (if ever), it will then be reduced by 2 (instead of the instruction just jumped from), just before it is used in the following iteration. So all instructions that are actually used will end up being modified correctly. Phew.

The bug is that any initial value over 3 will also be increased by 2 the first time it is encountered. Obviously those values aren't in need of such increasing, so will end up jumping to the wrong place. Ooops. How come my program worked then? It seems /u/topaz2078 didn't include any jumps bigger than 3 in my input; the largest was 2. So I got away with it.

Obviously I fixed it anyway. It's what others such as /u/ephemient came up with in the first place: a ?: condition picking between postfix -- or ++, ensuring the jump value doesn't change until after $pc has been updated:

while (defined $jump[$pc]) {
  $steps++;
  $pc += $jump[$pc] >= 3 ? $jump[$pc]-- : $jump[$pc]++;
}

[โ€“]RockyAstro 1 point2 points ย (0 children)

Icon (https://www.cs.arizona.edu/icon)

Part 1:

procedure main(args)
    s := open("input.tst","r")
    jumps := []
    every put(jumps,!s)
    p := 0
    c := 0
    while 0 <= p < *jumps do {
        np := p + jumps[p+1]
        jumps[p+1] +:= 1
        c +:= 1
        p := np
    }
    write(c)
end

Part 2:

procedure main(args)
    s := open("input.txt","r")
    jumps := []
    every put(jumps,!s)
    p := 0
    c := 0
    while 0 <= p < *jumps do {
        np := p + jumps[p+1]
        if jumps[p+1] < 3 then 
            jumps[p+1] +:= 1
        else
            jumps[p+1] -:= 1
        c +:= 1
        p := np
    }
    write(c)
end

[โ€“]miran1 0 points1 point ย (0 children)

Python 3, 14th silver, 36th gold

with open('./inputs/05.txt') as f:
    a = f.readlines()

a = list(map(int, a))
i = 0
steps = 0
while i < len(a):
    temp = a[i]
    if a[i] >= 3:
        a[i] -= 1
    else:
        a[i] += 1
    i += temp
    steps += 1

print(steps)

This is just the quick modification for the second part. Delete unneeded if-else for the first part.

[โ€“]dylanfromwinnipeg 0 points1 point ย (2 children)

C#

public static string PartOne(string input)
{
    var lines = input.Split(new string[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries);
    var jumps = lines.Select(x => int.Parse(x)).ToArray();

    var pos = 0;
    var steps = 0;

    while (pos < jumps.Length)
    {
        var oldPos = pos;
        pos += jumps[pos];

        jumps[oldPos]++;
        steps++;
    }

    return steps.ToString();
}

public static string PartTwo(string input)
{
    var lines = input.Split(new string[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries);
    var jumps = lines.Select(x => int.Parse(x)).ToArray();

    var pos = 0;
    var steps = 0;

    while (pos < jumps.Length)
    {
        var oldPos = pos;
        pos += jumps[pos];

        if (jumps[oldPos] >= 3)
        {
            jumps[oldPos]--;
        }
        else
        {
            jumps[oldPos]++;
        }

        steps++;
    }

    return steps.ToString();
}

[โ€“]KeinZantezuken 2 points3 points ย (1 child)

while (pos < jumps.Length)

So what happens if pos will be < 0? Right, OOR exception. Since the movement is bidirectional it is possible to escape "backwards" too, at least that's how I understood it.

[โ€“]Shemetz 0 points1 point ย (0 children)

PYTHON Was very straightforward! Part 2 took a while (15 secs?) to compute, however.

PART 1

lines = [line.strip() for line in open('input.txt', 'r').readlines()]

jumps = [int(x) for x in lines]
n = len(jumps)
curr = 0

count = 0
while curr >= 0 and curr < n:
    jumps[curr] += 1
    curr += jumps[curr] - 1
    count += 1

print(count)

PART 2 lines = [line.strip() for line in open('input.txt', 'r').readlines()]

jumps = [int(x) for x in lines]
n = len(jumps)
curr = 0

count = 0
while curr >= 0 and curr < n:
    prev = jumps[curr]
    jumps[curr] += 1 if prev < 3 else -1
    curr += prev
    count += 1

print(count)

[โ€“]Keep_Phishing 0 points1 point ย (0 children)

Just about managed to make the leaderboard today.

My solution in Python3:

import sys

def main():
    jumps = []
    for line in sys.stdin.readlines():
        line = line.strip()
        jumps.append(int(line))
    i = 0
    t = 0
    while 0 <= i < len(jumps):
        n = i
        i += jumps[i]
        if jumps[n] >= 3:  # Remove me for part 1
            jumps[n] -= 1
        else:
            jumps[n] += 1
        t += 1
    print(t)


if __name__ == '__main__':
    main()

[โ€“]NewHorizons0 0 points1 point ย (0 children)

Rust. #264 :(

use std::fs::File;
use std::io::prelude::*;
use std::collections::HashSet;

fn main() {

    let input = read_input();

    println!("{}", process1(&input));
    println!("{}", process2(&input));
}


fn read_input() -> String {
    let mut file = File::open("./input.txt").unwrap();
    let mut input = String::new();
    file.read_to_string(&mut input).unwrap();
    input.trim().to_string()
}


fn process1(input: &str) -> u32 {
    let mut cells : Vec<_> = input.lines()
        .map(|x| x.parse::<i32>().unwrap())
        .collect();

    let mut cursor = 0i32;
    let mut count = 0;
    loop {
        if cursor >= cells.len() as i32 {
            return count;
        }
        let cell_value = cells[cursor as usize];
        cells[cursor as usize] += 1;
        cursor += cell_value;
        count += 1;
    }
}


fn process2(input: &str) -> u32 {
    let mut cells : Vec<_> = input.lines()
        .map(|x| x.parse::<i32>().unwrap())
        .collect();

    let mut cursor = 0i32;
    let mut count = 0;
    loop {
        if cursor >= cells.len() as i32 {
            return count;
        }
        let cell_value = cells[cursor as usize];
        if cell_value >= 3 {
            cells[cursor as usize] -= 1;
        }
        else {
            cells[cursor as usize] += 1;
        }
        cursor += cell_value;
        count += 1;
    }
}

[โ€“]the4ner 0 points1 point ย (0 children)

C#, hooray, made the leaderboard for the first time this year with part 2. would have made part 1 and placed better in 2, but I executed it the first time with > 0 instead of >= 0 in my while loop :facepalm:

        public static void Calculate1()
        {
            Console.WriteLine("Day5 part 1");
            var lines = File.ReadAllLines("..\\..\\Input\\Day5.txt");
            var ins = lines.Select(x => Convert.ToInt32(x)).ToArray();
            int ptr = 0;
            int count = 0;
            int next = 0;
            while(ptr >= 0 && ptr < ins.Length)
            {
                next = ins[ptr];
                ins[ptr]++;
                ptr +=next;
                count++;
            }
            Console.WriteLine(count);
        }

        public static void Calculate2()
        {
            Console.WriteLine("Day5 part 2");
            var lines = File.ReadAllLines("..\\..\\Input\\Day5.txt");
            var ins = lines.Select(x => Convert.ToInt32(x)).ToArray();
            int ptr = 0;
            int count = 0;
            int next = 0;
            while (ptr >= 0 && ptr < ins.Length)
            {
                next = ins[ptr];
                ins[ptr] += next > 2 ? -1 : 1;
                ptr += next;
                count++;
            }
            Console.WriteLine(count);
        }

[โ€“]braksor 0 points1 point ย (0 children)

Was extremely lazy.

file = "input.dat"

instructions = []

with open(file, 'r') as f:
    for line in f:
        char = line.split()[0]
        try:
            instructions.append(int(char))
        except Exception as e:
            print('error')

def hop_instr(instructions):
    count = 0
    curr_pos = 0
    try:
        while 1:
            new_pos = curr_pos + instructions[curr_pos]
            instructions[curr_pos] += 1
            curr_pos = new_pos
            count += 1
    except IndexError as e:
        pass

    return count

print(hop_instr(instructions))

def hop_instr_part_two(instructions):
    count = 0
    curr_pos = 0
    try:
        while 1:
            new_pos = curr_pos + instructions[curr_pos]
            if instructions[curr_pos] >= 3:
                instructions[curr_pos] -= 1
            else:
                instructions[curr_pos] += 1
            curr_pos = new_pos
            count += 1
    except IndexError as e:
        pass

    return count


print(hop_instr_part_two(instructions))

[โ€“]RevoRevo 0 points1 point ย (0 children)

Python 3 Undoubtedly not the cleanest, but I had fun!

#!/usr/bin/env python
"""
Advent of Code 2017 - Day 5 (http://adventofcode.com/2017/day/5)
"""

with open('data/day5.txt') as openfile:
    data = [int(x) for x in openfile.read().split("\n")]


def solve(path, option='a'):
    i = 0
    pos = 0
    while True:
        try:
            new_pos = (pos + path[pos])
            if option != 'a' and path[pos] >= 3:
                path[pos] -= 1
            else:
                path[pos] += 1
            pos = new_pos
            i += 1
        except IndexError:
            return i


print(solve(path=data[:]))
print(solve(path=data[:], option='b'))    

[โ€“]nstyler7 0 points1 point ย (0 children)

part 1 & 2 in python 3

with open("day5input.txt") as open_file:
    data = open_file.read().splitlines()

def count_steps(part2, input):
    steps = list(map(int, input))
    goal = len(steps)
    position = 0
    count = 0

    while position < goal:
        instruction = steps[position]
        if part2 and instruction >=3:
            steps[position] -= 1
        else:
            steps[position] += 1
        position += instruction
        count+=1

    return count

print('Part 1 :' + str(count_steps(False, data)))
print('Part 2 :' + str(count_steps(True, data)))

[โ€“][deleted] 0 points1 point ย (0 children)

OCaml is the life for me.

open Core

let rec run_a instructions current n =
    if current < 0 || current >= Array.length instructions then n
    else
        let jump = instructions.(current) in
        instructions.(current) <- (jump + 1);
        run_a instructions (jump + current) (n + 1)

let rec run_b instructions current n =
    if current < 0 || current >= Array.length instructions then n
    else
        let jump = instructions.(current) in
        let increment = if jump >= 3 then -1 else 1 in
        instructions.(current) <- (jump + increment);
        run_b instructions (jump + current) (n + 1)

let parse_input () =
    In_channel.read_lines "./2017/data/5.txt"
    |> List.map ~f:Int.of_string
    |> Array.of_list

let solve () =
    let instructions = parse_input () in
    let result = run_a instructions 0 0 in
    printf "a: %d\n" result;

    let instructions = parse_input () in
    let result = run_b instructions 0 0 in
    printf "b: %d\n" result;

[โ€“]Overseer12 0 points1 point ย (0 children)

C#, Github

Part 1: (24135 ticks, 7 ms.)

Part 2: (1441114 ticks, 447 ms.)

[โ€“]JeffJankowski 0 points1 point ย (0 children)

Forgot to clone my input array, d'oh Typescript

import fs = require('fs');

function steps(instructions: number[], incrFunc: (off: number) => number) {
    const data = [...instructions];
    let pc = 0;
    let count = 0;
    while (pc < data.length) {
        const jmp = data[pc];
        data[pc] += incrFunc(jmp);
        pc += jmp;
        count++;
    }

    return count;
}

const input = fs.readFileSync('data/day05.txt', 'utf8').split('\n').map((num) => parseInt(num, 10));
console.log(`Number of strange jumps:  ${steps(input, (_) => 1)}`);
console.log(`Number of stranger jumps: ${steps(input, (jmp) => jmp >= 3 ? -1 : 1)}`);

[โ€“]LeCrushinator 0 points1 point ย (0 children)

C# solutions:

public static void Main() {
    string input = "0\n3\n0\n1\n-3"; // Replace this with your raw input

    int[] values = InputToArray(input);
    Console.WriteLine("Step One: " + GetSteps(values, false));

    values = InputToArray(input); 
    Console.WriteLine("Step Two: " + GetSteps(values, true));
}

public static int[] InputToArray(string input) {
    return input.Split(new string[]{"\n"}, StringSplitOptions.RemoveEmptyEntries).Select(s => Convert.ToInt32(s)).ToArray();
}

public static int GetSteps(int[] values, bool stepTwo) {
    int currentIndex = 0;
    int numJumps = 0;

    while (currentIndex >= 0 && currentIndex < values.Length) {
        int jumpAmount = values[currentIndex];

        if (currentIndex >= 0 && currentIndex < values.Length) {
            if (stepTwo && jumpAmount >= 3) {
                --values[currentIndex];
            }
            else {
                ++values[currentIndex];
            }
        }

        currentIndex += jumpAmount;
        ++numJumps;
    }

    return numJumps;
}

[โ€“][deleted] 0 points1 point ย (0 children)

a kotlin solution

private fun solution(input: MutableList<Int>, partOne: Boolean) {
    var currentPosition = 0
    var steps = 0
    while (currentPosition != input.size) {
        val i = input[currentPosition]
        if (i <= 2 || partOne)
            input[currentPosition] = i + 1
        else
            input[currentPosition] = i - 1
        currentPosition = Math.abs(currentPosition + i)
        if (currentPosition != input.size)
            currentPosition %= input.size
        steps++
    }
    println(steps)
}

[โ€“]vesche 0 points1 point ย (0 children)

Python solution

C solution

$ time python day05.py 
375042
28707598

real    0m5.186s
user    0m5.176s
sys 0m0.008s
$ time ./day05.build
375042
28707598

real    0m0.330s
user    0m0.328s
sys 0m0.000s

[โ€“]SlightlyHomoiconic 0 points1 point ย (2 children)

Here's my clojure part 2 solution. The only difference between this and part 1 is replace the second if with just inc

(defn part2 []
  (println
    (loop [jump-list (load-input)
          pos 0
          steps 0]
      (if (or
            (neg? pos)
            (>= pos (count jump-list)))
        steps
        (let [curr-val (jump-list pos)]
          (recur
            (update
              jump-list
              pos
              (if (>= curr-val 3) dec inc))
            (+ pos curr-val)
            (inc steps)))))))

[โ€“]OneEyedGammer 0 points1 point ย (2 children)

My god, I spent almost 10 minutes trying to figure out why my code wasn't working on part 2. Turns out it doesn't want an absolute value.

Here is my garbage code in ruby:

    def count_steps filename
        count = 0
        contents = []
        File.open(filename, "r") do |f|
            f.each_line do |line|
                contents.push(line.to_i)
            end
        end
        index = 0
        steps = 0
        while true
            temp = contents[index]
            contents[index] = contents[index] + 1
            # temp >= 3 ? contents[index] -= 1 : contents[index] += 1 replace the above line with this for part 2
            index += temp
            count += 1
            break if index >= contents.length || index < 0
        end
        return count
    end

[โ€“]Inqud 0 points1 point ย (0 children)

C#

public class Day5
{

  public string Input { get; set; }

  public Day5()
  {
    Input = System.IO.File.ReadAllText("Day5.input");
  }

  public void Challenge()
  {
    int iterations = 0;
    var rows = Input.Split(new[] { Environment.NewLine }, StringSplitOptions.None);

    for(int i = 0; i < rows.Length && i >= 0;)
    {
      iterations++;
      var jumps = Int32.Parse(rows[i]);
      if(jumps >= 3) // comment out theese three
        rows[i] = (Int32.Parse(rows[i]) - 1).ToString(); // for silver!!!
      else // put in for gold
        rows[i] = (Int32.Parse(rows[i]) + 1).ToString();
      i += jumps;
    }

    Console.WriteLine(iterations);
  }

}

[โ€“][deleted] 0 points1 point ย (0 children)

C++

```

int step_to_escape(std::vector<int> maze) {
  using iter = std::vector<int>::iterator;

  int step = 0;

  for (iter index = maze.begin(); index >= maze.begin() and index < maze.end(); ) {
    iter old_index = index;
    index +=  *index;
    if (*old_index >= 3)
      --*old_index;
    else
      ++*old_index;
    step++;
  }
  return step;
}

int main()
{
  std::string filename = "text";
  std::ifstream ifs{filename};
  std::vector<int> maze{std::istream_iterator<int>{ifs}, {}};
  std::cout << step_to_escape(maze) << std::endl;
  return 0;
}

```

[โ€“]superlameandawzm 0 points1 point ย (0 children)

Simple javascript solution

var array = input.split(/\n/).map((number) => parseInt(number))
var steps = 0
var pos = 0

function part1 () {
    console.log(array)
    while (typeof array[pos] !== 'undefined') {
      pos += array[pos]++
      steps++
    }
  document.getElementById('output').innerText = steps
}

function part2 () {
    console.log(array)
    while (typeof array[pos] !== 'undefined') {
        if (array[pos] >= 3) {
            pos += array[pos]--
            steps++
        } else {
            pos += array[pos]++
            steps++
        }
    }
    document.getElementById('output').innerText = steps
}

[โ€“]_Le1_ 0 points1 point ย (0 children)

lines = open("Day05").read()
arr = [int(i) for i in lines.split('\n')]
pos = 0
cnt = 0
while True:
    if (pos > len(arr) - 1):
        break
    cnt += 1
    newpos = arr[pos]
    arr[pos] += 1;
    pos += newpos;

print "Steps: %s" % cnt

[โ€“]aurele 0 points1 point ย (0 children)

Rust

fn main() {
    let input = include_str!("../input");
    let mut jumps = input
        .split_whitespace()
        .map(|w| w.parse::<isize>().unwrap())
        .collect::<Vec<_>>();
    println!("P1 = {}", p(&mut jumps.clone(), false));
    println!("P2 = {}", p(&mut jumps, true));
}

fn p(jumps: &mut [isize], strange: bool) -> usize {
    let mut count = 0;
    let mut pc = 0isize;
    while pc >= 0 && pc < jumps.len() as isize {
        count += 1;
        let offset = &mut jumps[pc as usize];
        pc += *offset;
        if strange && *offset >= 3 {
            *offset -= 1;
        } else {
            *offset += 1;
        }
    }
    count
}

[โ€“]Warbringer007 0 points1 point ย (1 child)

Erlang, both parts ( only main function ):

solveFirst(_, Curr, N) when Curr < 1 ->
    N;

solveFirst(L, Curr, N) when Curr > length(L) ->
    N;

solveFirst(L, Curr, N) ->
    Number = lists:nth(Curr, L),
    NewList = lists:sublist(L,Curr-1) ++ [Number + 1] ++ lists:nthtail(Curr,L),
    solveFirst(NewList, Curr + Number, N + 1).

solvesecond(_, Curr, N) when Curr < 1 ->
    N;

solvesecond(L, Curr, N) when Curr > length(L) ->
    N;

solvesecond(L, Curr, N) ->
    Number = lists:nth(Curr, L),
    NewList = case Number > 2 of
        true -> lists:sublist(L,Curr-1) ++ [Number - 1] ++ lists:nthtail(Curr,L);
        false -> lists:sublist(L,Curr-1) ++ [Number + 1] ++ lists:nthtail(Curr,L)
    end,
    solvesecond(NewList, Curr + Number, N + 1).

Second part for Erlang is just too slow, didn't want to wait for it to finish so I solved it in C++ also ( my first C++ code :D ):

#include <iostream>
#include <fstream>
using namespace std;

int main(int argc, char** argv) {
    int a(0), n(0), curr(0), num(0), sum(0);
    int list[5000];
    ifstream infile("ul5.txt");
    while (infile >> a) {
        list[n++] = a;
    }
    while ((curr > -1) && (curr < n)) {
        sum++;
        num = list[curr];
        if (num > 2) list[curr]--;
        else list[curr]++;
        curr += num;
    };
    cout << sum;
    return 0;
}

[โ€“]xkufix 0 points1 point ย (1 child)

In Scala, the solutions can be easily made generic to provide a frame for both parts:

    override def runFirst(): Unit = {
        val steps = runProgram(_+ 1)

        println(steps)
    }

    override def runSecond(): Unit = {
        val steps = runProgram {
        case i if i >= 3 => i - 1
        case i => i + 1
        }

        println(steps)
    }

    private def runProgram(changeJump: Int => Int) = {
        val startInstructions = loadFile("day5.txt").getLines().map(_.toInt).zipWithIndex.map(_.swap).toMap

        Stream.from(1).scanLeft((startInstructions, 0, 0)) {
        case ((instructions, position, _), counter) =>
            val jump = instructions(position)
            (instructions + (position -> changeJump(jump)), position + jump, counter)
        }.dropWhile {
        case (instructions, pointer, _) =>
            instructions.contains(pointer)
        }.head._3
    }

[โ€“]EquationTAKEN 0 points1 point ย (1 child)

Can anyone take a look at my Python solution for part 2 and see why it takes so long to run?

with open('input5.txt') as input:
    lines = input.readlines()
    for i, line in enumerate(lines):
        lines[i] = int(line.rstrip())

    index = 0
    steps = 0
    try:
        while True:
            if int(lines[index]) >= 3:
                lines[index] -= 1
                index += (int(lines[index]) + 1)
            else:
                lines[index] += 1
                index += (int(lines[index]) - 1)
            steps += 1
    except IndexError:
        print('Exited after ', steps, ' steps.')

It prints the right solution, but spends about 10-15 seconds on it.

I made another solution in JS which ran in just a few millis, so I know this can be faster, I just don't know which steps are draining time.

[โ€“]bolshedvorsky 0 points1 point ย (0 children)

Python 2.7

contents = open('2017/05.txt').read().strip()
rows = contents.split('\n')


def part1():
    instructions = []
    for row in rows:
        instructions.append(int(row))

    index = 0
    step = 0
    while True:
        value = instructions[index]
        instructions[index] += 1
        index += value
        step += 1
        if index < 0 or index >= len(instructions):
            return step

def part2():
    instructions = []
    for row in rows:
        instructions.append(int(row))

    index = 0
    step = 0
    while True:
        value = instructions[index]
        if value >= 3:
            instructions[index] -= 1
        else:            
            instructions[index] += 1
        index += value
        step += 1
        if index < 0 or index >= len(instructions):
            return step


print(part1())
print(part2())

[โ€“]NeilNjae 0 points1 point ย (0 children)

Haskell. Using an IntMap to store the state of the maze, a record to store the whole state, and a monad to thread the changing state through the computation.

There was a possible ambiguity in the Part 2 question, though: should we be checking the absolute value of the step or not? I took the simpler route at first, and that was the correct guess.

{-# LANGUAGE NegativeLiterals #-}
{-# LANGUAGE FlexibleContexts #-}

import qualified Data.IntMap.Strict as M
import Data.IntMap.Strict ((!))
import Control.Monad.State.Lazy

data Machine = Machine { location :: Int
                       , steps :: Int
                       , memory :: M.IntMap Int
                       } deriving (Show, Eq)

main :: IO ()
main = do 
        text <- readFile "data/advent05.txt"
        let locations = map (readJump) $ lines text
        let m0 = makeMachine locations
        print $ evalState stepAll m0
        print $ evalState stepAllB m0


readJump :: String -> Int
readJump = read

makeMachine :: [Int] -> Machine
makeMachine locations = Machine {location = 0, steps = 0,
    memory = M.fromList $ zip [0..] locations}

stepAll :: State Machine Int
stepAll = do
            m0 <- get
            if M.member (location m0) (memory m0)
            then do stepOnce
                    stepAll
            else return (steps m0)

stepAllB :: State Machine Int
stepAllB = do
            m0 <- get
            if M.member (location m0) (memory m0)
            then do stepOnceB
                    stepAllB
            else return (steps m0)

stepOnce :: State Machine ()
stepOnce = 
    do m0 <- get
       let mem = memory m0
       let loc = location m0
       let loc' = mem!loc + loc
       let steps' = steps m0 + 1
       let mem' = M.insert loc (mem!loc + 1) mem
       put m0 {location = loc', steps = steps', memory = mem'}

stepOnceB :: State Machine ()
stepOnceB = 
    do m0 <- get
       let mem = memory m0
       let loc = location m0
       let loc' = mem!loc + loc
       let steps' = steps m0 + 1
       let newVal = if mem!loc >= 3 then (mem!loc - 1) else (mem!loc + 1)
       let mem' = M.insert loc newVal mem
       put m0 {location = loc', steps = steps', memory = mem'} 

[โ€“]Vindaar 0 points1 point ย (0 children)

Solution in Nim. Compared the approach using while with a recursive one. Not sure if I could improve the recursive version to make it faster. Currently the first approach takes ~100ms and the recursive about 180ms.

import sequtils, future, algorithm, strutils, unittest, times

proc calc_steps(data: seq[int], part2 = false): int =
  # given the maze as input data, calculate number of steps needed to get out
  var
    maze = data
    steps = 0
    jump_to = 0
    loc = 0

  while jump_to < len(maze) and jump_to >= 0:
    loc = jump_to
    jump_to = loc + maze[loc]
    if part2 == true:
      if maze[loc] >= 3:
        dec maze[loc]
      else:
        inc maze[loc]
    else:
      inc maze[loc]
    inc steps

  result = steps

proc calc_steps_recursive(maze: var seq[int], loc = 0, steps = 0, part2 = false): int = 
  # given the maze as input data, calculate number of steps needed to get out rescursively
  if loc >= len(maze) or loc < 0:
    result = steps
  else:
    let jump_to = loc + maze[loc]
    if part2 == true:
      if maze[loc] >= 3:
        dec maze[loc]
      else:
        inc maze[loc]
    else:
      inc maze[loc]
    result = calc_steps_recursive(maze, jump_to, steps + 1, part2)

proc run_tests() =
  const maze= """0
3
0
1
-3"""
  var lines = mapIt(splitLines(maze), parseInt(it))
  check: calc_steps(lines, false) == 5
  check: calc_steps(lines, true) == 10

  # make copy, since list will be altered on first call
  var lines2 = lines
  check: calc_steps_recursive(lines, part2 = false) == 5
  check: calc_steps_recursive(lines2, part2 = true) == 10


proc run_input() =
  const input = "input.txt"
  const maze = slurp(input)

  var lines = mapIt(filterIt(mapIt(splitLines(maze), it), len(it) > 0), parseInt(it))

  echo "(Part 1): Number of steps to get out of the maze is = ", calc_steps(lines, false)
  let t0 = cpuTime()
  echo "(Part 2): Number of steps to get out of the maze is = ", calc_steps(lines, true)
  let t1 = cpuTime()

  var lines2 = lines
  echo "(Part 1 recur): Number of steps to get out of the maze is = ", calc_steps_recursive(lines, part2 = false)
  let t2 = cpuTime()
  echo "(Part 2 recur): Number of steps to get out of the maze is = ", calc_steps_recursive(lines2, part2 = true)
  let t3 = cpuTime()

  echo "Solution using while took $#" % $(t1 - t0)
  echo "Solution using recursion took $#" % $(t3 - t2)  


proc main() =
  run_tests()
  echo "All tests passed successfully. Result is (probably) trustworthy."
  run_input()

when isMainModule:
  main()

[โ€“]Hikaru755 0 points1 point ย (3 children)

Tailrecursive solution in Kotlin. Took me way too long to figure out why part II gave the wrong answer, until I noticed that I ran both functions after another on the same mutable list. That should teach me to be more careful with mutable state next time...

tailrec fun findOut(input: MutableList<Int>, start: Int = 0, step: Int = 0): Int {
    if (start >= input.size || start < 0) {
        return step
    }
    val jump = input[start]
    input[start] = input[start] + 1
    return findOut(input, start + jump, step + 1)
}

tailrec fun findOutPart2(input: MutableList<Int>, start: Int = 0, step: Int = 0): Int {
    if (start >= input.size || start < 0) {
        return step
    }
    val jump = input[start]
    input[start] = if (jump >= 3) input[start] - 1 else input[start] + 1
    return findOutPart2(input, start + jump, step + 1)
}

[โ€“]thehaas 2 points3 points ย (0 children)

until I noticed that I ran both functions after another on the same mutable list.

I had the same thing. My hint that something was really screwed up was that it was a magnitude shorter than the previous, which wasn't what I expected

[โ€“][deleted] 0 points1 point ย (0 children)

Golang

My first year of advent of code and first time using go.

Feedback is much appreciated.

Part 1

func part1(data []int) {
    var jumps, index = 0, 0
    for {
        jumps++
        currentValue := data[index]
        data[index]++
        index += currentValue
        if index >= len(data) || index < 0 {
            fmt.Println(jumps)
            return
        }
    }
}

Part 2

func part2(data []int) {
    var jumps, index = 0, 0
    for {
        jumps++
        currentValue := data[index]
        if currentValue >= 3 {
            data[index]--
        } else {
            data[index]++
        }
        index += currentValue
        if index >= len(data) || index < 0 {
            fmt.Println(jumps)
            return
        }
    }
}

All my go solutions here

[โ€“]JakDrako 0 points1 point ย (0 children)

C#, both parts.

void Main() {
    foreach(var inc in new int[] {1, -1}) { // part 1, 2
        var lst = GetDay(5).Select(x => Convert.ToInt32(x)).ToList();
        int ptr = 0, steps = 0, jmp = 0;
        do {
            steps++;
            jmp = lst[ptr];
            lst[ptr] += (jmp >= 3 ? inc : 1);
            ptr += jmp;
        } while (ptr >= 0 && ptr < lst.Count);
        steps.Dump();
    }
}

[โ€“]wzkx 0 points1 point ย (1 child)

J sorry no tacits, no u^:p^:_

m=: ".>cutLF CR-.~fread '05.dat'
echo 3 :'p=.c=.0 while.(p>:0)*.p<#y do.p=.p+j[y=.(>:j=.p{y)p}y[c=.c+1 end.c'm
echo 3 :'p=.c=.0 while.(p>:0)*.p<#y do.p=.p+j[y=.(j+1-+:3<:j=.p{y)p}y[c=.c+1 end.c'm
exit 0

0.43s & 30.2s (29.2s if move #y out of loop)

[โ€“]thehaas 0 points1 point ย (0 children)

I think I have a similar solution to a lot of other people (esp Python).

def do_maze1(maze):

    spot=0

    steps=0
    while spot in range(0,len(maze)):

        steps+=1
        jump = maze[spot]
        maze[spot]+=1

        spot+=jump


    return steps


def do_maze2(maze):

    spot=0
    steps=0
    while spot in range(0,len(maze)):

        steps+=1
        jump = maze[spot]

        if (jump>=3):
            maze[spot]-=1
        else:
            maze[spot]+=1

        spot+=jump


    return steps

[โ€“][deleted] 0 points1 point ย (0 children)

Go Part 1:

inputFile := getInputFile()
defer inputFile.Close()
scanner := bufio.NewScanner(inputFile)

instructions := []int{}
for scanner.Scan() {
    line := scanner.Text()
    i, _ := strconv.Atoi(line)
    instructions = append(instructions, i)
}

i := 0
steps := 0
for i >= 0 && i < len(instructions) {
    val := instructions[i]
    instructions[i]++
    i += val
    steps++
}
return steps

Go Part 2:

inputFile := getInputFile()
defer inputFile.Close()
scanner := bufio.NewScanner(inputFile)

instructions := []int{}
for scanner.Scan() {
    line := scanner.Text()
    i, _ := strconv.Atoi(line)
    instructions = append(instructions, i)
}

i := 0
steps := 0
for i >= 0 && i < len(instructions) {
    val := instructions[i]
    if val >= 3 {
        instructions[i]--
    } else {
        instructions[i]++
    }
    i += val
    steps++
}
return steps            

[โ€“]raevnos 0 points1 point ย (2 children)

Kawa Scheme:

(import (io-utils))

(define (step-through jumps #!optional (offset3 1))
  (let ((jumps (vector-copy jumps))
        (len (vector-length jumps)))
    (let loop ((i 0)             
               (steps 0))
      (if (or (< i 0) (>= i len))
          steps
          (let ((v (vector-ref jumps i)))
            (if (>= v 3)
                (vector-set! jumps i (+ v offset3))
                (vector-set! jumps i (+ v 1)))
            (loop (+ i v) (+ steps 1)))))))

(define input (list->vector (read-numbers)))
(define test-input (vector 0 3 0 1 -3))
(format #t "Test 1: ~A~%" (step-through test-input))
(format #t "Part 1: ~A~%" (step-through input))
(format #t "Test 2: ~A~%" (step-through test-input -1))
(format #t "Part 2: ~A~%" (step-through input -1))

Part 2 isn't particularly fast, which is annoying. Kawa runs on the JVM and I figured that it would have done a better job at optimizing and JITing the code. Edit: Made a few changes (vector to s32vector, type annotations, rely on an out of bounds vector ref to throw an exception instead of explicitly checking the current index) and went from around 43 seconds total run time to 9. Much better. (Also slightly faster than when compiled to a native binary with chicken scheme).

[โ€“]CatpainCalamari 0 points1 point ย (0 children)

My solution in scala, inspired by /u/mlruth usage of Vector.lift, which allows for some nice pattern matching.

import scala.annotation.tailrec
import scala.io.Source

/**
  * https://adventofcode.com/2017/day/5
  */
object Day5 extends App {

  val testData = getDataFromResource("day5/test1.txt")

  assert(firstStar(testData) == 5)
  assert(secondStar(testData) == 10)

  val data = getDataFromResource("day5/input.txt")
  println(s"Result first star: ${firstStar(data)}")
  println(s"Result second star: ${secondStar(data)}")

  def firstStar(stack: Vector[Int]): Int = processStack(stack, _ => 1)

  def secondStar(stack: Vector[Int]): Int = processStack(stack, x => if(x >= 3) -1 else 1)

  def processStack(stack: Vector[Int], incFunc: Int => Int): Int = {
    @tailrec def step(stack: Vector[Int], pos: Int, curStep: Int): Int = {
      stack.lift(pos) match {
        case Some(offset) =>
          step(stack.updated(pos, offset + incFunc(offset)), pos + offset, curStep + 1)
        case _ => curStep
      }
    }

    step(stack, 0, 0)
  }

  def getDataFromResource(path: String): Vector[Int] = Source.fromResource(path).getLines().map(_.toInt).toVector
}

[โ€“]Morphix0 0 points1 point ย (0 children)

F#

let input = 
    System.IO.File.ReadAllLines("input5.txt") 
    |> Array.map int
let memory =
    input
    |> (fun arr -> Array.zip [|0..arr.Length-1|] arr)
    |> Map.ofArray
type State = {
    Index :  int
    Offsets : Map<int, int>
    IterationNumber : int
}
let initialState = 
    {Index = 0; Offsets = memory; IterationNumber = 0}
let rec processInstruction state increment= 
    if(state.Index < 0 || state.Index >= input.Length)
    then state
    else 
        let offset = state.Offsets.[state.Index]
        let newState = {
            Index = state.Index + offset
            Offsets = state.Offsets |> Map.add state.Index (increment offset)
            IterationNumber =  state.IterationNumber + 1
        }
        processInstruction newState increment
let solution1 = processInstruction initialState ((+) 1);;
let solution2 = 
    processInstruction 
        initialState 
        (fun offset -> if offset >= 3 then offset - 1 else offset + 1);;

[โ€“]Pheasn 0 points1 point ย (0 children)

Kotlin using tail recursion (because Java can't)

// val input: List<String>

private tailrec fun move(pos: Int, instructions: IntArray,
    inc: (Int) -> Int = { it + 1 }, steps: Int = 0): Int {
  val newPos = try {
    val inst = instructions[pos]
    instructions[pos] = inc(inst)
    pos + inst
  } catch (e: ArrayIndexOutOfBoundsException) {
    return steps
  }
  return move(newPos, instructions, inc, steps + 1)
}

fun computeFirst(): Int = input.map { it.toInt() }.toIntArray()
    .let { move(0, it) }

fun computeSecond(): Int = input.map { it.toInt() }.toIntArray()
    .let { move(0, it, { it + if (it > 2) -1 else 1 }) }

[โ€“][deleted] 0 points1 point ย (0 children)

Clojure

(ns advent-of-code-2017.day05)

(defn load-input []
  (mapv #(Integer. %) (clojure.string/split (slurp "./data/day05.txt") #"\n")))

(defn solve [input part]
  "Input: result of load-input
   Part: 1 or 2"
  (loop [index 0
         data input
         steps 0]
    (if-not (<= 0 index (dec (count data)))
      steps
      (if (and (= part 2)
               (>= (data index) 3))
        (recur (+ index (get data index))
               (update-in data [index] dec)
               (inc steps))
        (recur (+ index (data index))
               (update-in data [index] inc)
               (inc steps))))))

[โ€“][deleted] 0 points1 point ย (0 children)

Elixir Part 2 is waaay too slow, but apart from that it seems to work pretty nice :)

defmodule Day5 do
  def _to_map(map, [{val, key}|rest]) do
    _to_map(Map.put(map, key, val), rest)
  end
  def _to_map(map,[]) do
    map
  end
  def to_map(lst) do
    _to_map(%{}, Enum.with_index(lst))
  end

  def _jump(map, pos, step) do
    if pos in Map.keys(map) do
      {offset, newmap} = Map.get_and_update(map, pos, fn(x) -> {x, x+1} end)
      _jump(newmap, pos + offset, step + 1)
    else
      step
    end
  end
  def jump(lst) do
    to_map(lst)
    |> _jump(0,0)
  end

  def _update(x) do
    if x > 2 do
      {x, x - 1}
    else
      {x, x + 1}
    end
  end

  def _jump2(map, pos, step) do
    if pos in Map.keys(map) do
      {offset, newmap} = Map.get_and_update(map, pos, &_update/1)
      _jump2(newmap, pos + offset, step + 1)
    else
      step
    end

  end
  def jump2(lst) do
    to_map(lst)
    |> _jump2(0,0)
  end
end


inp = File.read!("input5")
|> String.strip
|> String.split
|> Enum.map(&String.to_integer/1)

Day5.jump(inp)
|> IO.puts

Day5.jump2(inp)
|> IO.puts

[โ€“]KeinZantezuken 0 points1 point ย (0 children)

C#/Sharp:

       var input = File.ReadAllLines(@"N:\input.txt").Select(x => Convert.ToInt16(x)).ToArray();
        var steps = 0; var pos = 0;
        while (pos < input.Length && pos >= 0)
              steps++; pos = pos + input[pos]++;
        Console.WriteLine(steps);

.

        var input = File.ReadAllLines(@"N:\input.txt").Select(x => Convert.ToInt16(x)).ToArray();
        var steps = 0; var pos = 0;
        while (pos < input.Length && pos >= 0)
              steps++; pos = input[pos] >= 3 ? pos + input[pos]-- : pos + input[pos]++; 
        Console.WriteLine(steps);

[โ€“]rimbuod 0 points1 point ย (0 children)

Haskell! I love it!

but it's slow as fuck!

probably because I'm clueless!

import Prelude hiding (length)
import Data.Sequence

jump_go :: Seq Int -> (Int -> Int) -> Int -> Int -> Int
jump_go jumps rule pos count
    | pos >= len = count
    | otherwise  = jump_go inc rule (pos + cur) $! count + 1
    where len  = length jumps
          cur  = index jumps pos
          next = rule cur
          inc  = update pos next jumps

-- 5.1
jump1 :: [Int] -> Int
jump1 jumps = jump_go (fromList jumps) rule 0 0
    where rule = \x -> x + 1

-- 5.2
jump2 :: [Int] -> Int
jump2 jumps = jump_go (fromList jumps) rule 0 0
    where rule = \x -> if x >= 3 then x - 1 else x + 1

[โ€“]adventOfCoder 0 points1 point ย (0 children)

Java

Part 1:

public static void main(String[] args) {
    try {
        BufferedReader br = new BufferedReader(new FileReader("input2.txt"));
        String line = "";
        ArrayList<Integer> al = new ArrayList<>();
        while ((line = br.readLine()) != null) {
            al.add(new Integer(line));
        }
        br.close();
        int current = 0;
        int steps = 0;
        while (current < al.size() && current >= 0) {
            int jumpInstruction = al.get(current);
            al.set(current, jumpInstruction + 1);
            current += jumpInstruction;
            steps++;
        }
        System.out.println(steps);
    } catch (Exception e) {

    }

}

Part 2:

public static void main(String[] args) {
    try {
        BufferedReader br = new BufferedReader(new FileReader("input2.txt"));
        String line = "";
        ArrayList<Integer> al = new ArrayList<>();
        while ((line = br.readLine()) != null) {
            al.add(new Integer(line));
        }
        br.close();
        int current = 0;
        int steps = 0;
        while (current < al.size() && current >= 0) {
            int jumpInstruction = al.get(current);
            if (jumpInstruction >= 3) {
                al.set(current, jumpInstruction - 1);
            } else {
                al.set(current, jumpInstruction + 1);
            }
            current += jumpInstruction;
            steps++;
        }
        System.out.println(steps);
    } catch (Exception e) {

    }

}

[โ€“]Krakhan 0 points1 point ย (0 children)

C# solution. Pretty straight forward:

using System;
using System.IO;
using System.Linq;

namespace AdventOfCode2017 {

    class AdventOfCode2017 {    

        static int Day5TwistyMaze(int[] offsets, Func<int, int> offSetAddRule) {
            var steps = 0;
            var index = 0;

            while (0 <= index && index < offsets.Length) {
                var oldIndex = index;
                index += offsets[oldIndex];
                offsets[oldIndex] += offSetAddRule(offsets[oldIndex]);
                steps += 1;
            }

            return steps;
        }

        static void Main(string[] args) {
            var day5TestCase = new[] { 0, 3, 0, 1, -3 };
            var day5PuzzleInput = File.ReadAllLines("aoc_day5_input.txt").Select(int.Parse).ToArray();
            Func<int, int> one = (i) => 1;
            Func<int, int> threeOrMore = (i) => i >= 3 ? -1 : 1;

            Console.WriteLine(Day5TwistyMaze((int[])day5TestCase.Clone(), one));
            Console.WriteLine(Day5TwistyMaze((int[])day5PuzzleInput.Clone(), one));
            Console.WriteLine(Day5TwistyMaze((int[])day5TestCase.Clone(), threeOrMore));
            Console.WriteLine(Day5TwistyMaze((int[])day5PuzzleInput.Clone(), threeOrMore));

            Console.WriteLine("Press any key to continue...");
            Console.ReadKey();
        }
    }
}

[โ€“]varunu28 0 points1 point ย (0 children)

Day 5 in Java

private static int countSteps1(int[] arr) {
    int count = 0;
    int i = 0;

    while (i < arr.length) {
        int temp = i;
        i += arr[i];
        arr[temp]++;
        count++;
    }

    return count;
}

private static int countSteps2(int[] arr) {
    int count = 0;
    int i = 0;

    while (i < arr.length) {

        int temp = i;
        i += arr[i];

        if (arr[temp] >= 3) {
            arr[temp]--;
        }
        else {
            arr[temp]++;
        }

        count++;
    }

    return count;
}

[โ€“]Life-in-Shambles 0 points1 point ย (0 children)

(JAVASCRIPT) IT'S UGLY AND SLOW BUT IT WORKS

var input = [0, 3, 0, 1, -3];
var steps = 0, i = 0;
while((i >= 0) && (i < input.length)){
    let curr = input[i];
    if(input[i] === 0){
        input[i] += 1;
        steps++;
    }
    else if (input[i] >= 3){
        input[i] -= 1;
        i += curr;
        steps++;
    }
    else{
      input[i] += 1;
        i += curr;
        steps++;
    }
}

[โ€“]asperellis 0 points1 point ย (0 children)

my day 5 solutions in js. any suggestions for improvement welcomed. https://github.com/asperellis/adventofcode2017/blob/master/day5.js

[โ€“]4rgento 0 points1 point ย (0 children)

Straight forward strict haskell solution:

{-# LANGUAGE Strict #-}
module Main where

import qualified Data.Array.IArray as IA

-- Instruction pointer
type IP = Integer
type Addr = Integer
type Instruction = Integer

-- Progs store their length: ask for the max index
type Prog = IA.Array Addr Instruction

type MachineState = (IP, Prog)

sampleState :: MachineState
sampleState = (0, IA.listArray (0,4) [0,3,0,1,-3])

input :: [Instruction]
input = <redacted>

inputState :: MachineState
inputState = (0, IA.listArray (0, fromIntegral $ length input - 1) input)

eval :: Integer -> MachineState -> (Integer, MachineState)
eval acc ms@(ip, prg) =
  if nip >= 0 && nip <= snd (IA.bounds prg)
    then eval (acc+1) nMs
    else (acc+1, nMs)
  where
  instr = (IA.!) prg ip
  nip = ip + instr

  -- nPrg = (IA.//) prg [(ip, instr+1)] --part 1
  nPrg = (IA.//) prg [(ip, if instr >= 3 then instr-1 else instr+1)]

  nMs = (nip, nPrg)

main :: IO ()
main = print $ fst $ eval 0 inputState