• Ever wanted an RSS feed of all your favorite gaming news sites? Go check out our new Gaming Headlines feed! Read more about it here.

Deleted member 10234

User requested account closure
Banned
Oct 27, 2017
2,922
I have just begun working on this and finished day 2. Is there any more elegant solution to the second part of day 2 other than just brute force loop through two lists? I kept wanting to do something smarter like adjusting both noun and verb individually up and down one depending on the result till it hit the solution... but that feels like a lot of effort šŸ™ˆ
Because the verb and noun indicate the address of the data that will be used, there won't be any relation between two consecutive values. I think for this one bruteforcing is the (only?) way to go.
 

NetMapel

Member
Oct 25, 2017
3,379
For day 3 part 1, I have a question to ask for clarification. I have written lines of codes that will check for intersections between wires. Now I am starting at a central port of (0, 0) and then extending the wires from there. I haven noticed for the first practice data set of:

R75,D30,R83,U83,L12,D49,R71,U7,L72
U62,R66,U55,R34,D71,R55,D58,R83

Given a (0, 0) starting point, there appears to be an intersection at (158, -12) which created a distance of 146. That's shorter than the accepted distance of 159. Are we to assume that the wires cannot go in the left or below the starting point? Given the example graphs they provided, it's not clear whether they are allowing the wire to go left/down the starting point. I do not believe I made a mistake coming up with the intersecting points given all the other test datas did not give me this problem. Is that also something you guys faced when doing day 3 part 1?
 

Randdalf

Member
Oct 28, 2017
4,167
For day 3 part 1, I have a question to ask for clarification. I have written lines of codes that will check for intersections between wires. Now I am starting at a central port of (0, 0) and then extending the wires from there. I haven noticed for the first practice data set of:



Given a (0, 0) starting point, there appears to be an intersection at (158, -12) which created a distance of 146. That's shorter than the accepted distance of 159. Are we to assume that the wires cannot go in the left or below the starting point? I do not believe I made a mistake coming up with the intersecting points given all the other test datas did not give me this problem. Is that also something you guys faced when doing day 3 part 1?

Your code for calculating Manhattan distance is wrong. That point is 170 from the central port.
 

iapetus

Member
Oct 26, 2017
3,078
I knew I should have written an interface for input/output to the IntCode interpreter to happen programmatically. Ah well, at least I left sensible hooks for one...
 

Randdalf

Member
Oct 28, 2017
4,167
Isn't your part two crazily overengineered?

Just make a list of planets from YOU and SAN up to the center point. Work from YOU towards the center - stop at the first value that's in the SAN list and add the indices of that item in the two lists together (and subtract two).

I rewrote my day 6 part 2 and it's way simpler now: https://github.com/Randdalf/aoc19/blob/master/d06.py

I ended up with something similar to what you described.

I tried two ways of finding the path: inverting my orbits dictionary then working backwards, and recursive DFS. The latter seems just as fast and is less code, so it won out for me.
 

NetMapel

Member
Oct 25, 2017
3,379
Your code for calculating Manhattan distance is wrong. That point is 170 from the central port.
My abomination took a bit of time to calculate the Manhattan distance from the real data set but it worked :O Now I just need to optimize it... but scanning part B's problem set makes me think my current set up is best suited to tackle that lol
 
OP
OP
ElFly

ElFly

Member
Oct 27, 2017
2,733
did day 7 part a, may do part b later cause it sounds complex

even part a was complex to figure out. had skipped a rule and gotten v wrong answers

edit: did part b. It was hard

in the end I was sharing state between the _amplifiers_ cause I had not properly copied the array of the state, just a reference somehow

after that I had to put a try / except in the code cause some of the inputs caused out of bounds index reads. Then finally got it right

woop woop!
 
Last edited:

Qronicle

Member
Oct 27, 2017
718
Belgium
Fuck me, I'm stuck on part 2 :-/

So I'm having a big while loop until one of the thrusters ends his intcode application. I have different intcode instances for each of the thrusters, and whenever a thruster asks for input that isn't available, that thruster pauses execution, and I pass the last given output as input to the next one. Whenever I'm in the second feedback loop, I just continue from the address that asked for input with the last output. So either my logic is wrong, or I have made a mistake somewhere.

Does anybody have some output to compare for the first example? (Input: 3,26,1001,26,-4,26,3,27,1002,27,2,27,1,27,26,27,4,27,1001,28,-1,28,1005,28,6,99,0,0,5)

Engine 0 - phase 9
> Input: 9, 0
> Demands more input
Engine 1 - phase 8
> Input: 8, 5
> Demands more input
Engine 2 - phase 7
> Input: 7, 14
> Demands more input
Engine 3 - phase 6
> Input: 6, 31
> Demands more input
Engine 4 - phase 5
> Input: 5, 64
> Demands more input
> Output: 129
Engine 0 - phase 9
> Input: 129
> Demands more input
Engine 1 - phase 8
> Input: 263
> Demands more input
Engine 2 - phase 7
> Input: 530
> Demands more input
Engine 3 - phase 6
> Input: 1063
> Demands more input
Engine 4 - phase 5
> Input: 2128
> Demands more input
> Output: 4257
Engine 0 - phase 9
> Input: 4257
> Demands more input
Engine 1 - phase 8
> Input: 8519
> Demands more input
Engine 2 - phase 7
> Input: 17042
> Demands more input
Engine 3 - phase 6
> Input: 34087
> Demands more input
Engine 4 - phase 5
> Input: 68176
> Demands more input
> Output: 136353
Engine 0 - phase 9
> Input: 136353
> Demands more input
Engine 1 - phase 8
> Input: 272711
> Demands more input
Engine 2 - phase 7
> Input: 545426
> Demands more input
Engine 3 - phase 6
> Input: 1090855
> Demands more input
Engine 4 - phase 5
> Input: 2181712
> Demands more input
> Output: 4363425
Engine 0 - phase 9
> Input: 4363425
> End
 

gryvan

Brooklyn Rage
Member
Oct 25, 2017
487
I definitely would like more practice in my problem solving skills as well as my coding skills so I'll see how this goes!
 
Last edited:

iapetus

Member
Oct 26, 2017
3,078
Well, I'm tired so my code for part 2 is an embarrassing multithreaded mess. Five amplifiers running in parallel with input/output queues between them. Nobody can be allowed to see the source and live, but at least it worked.
 

Qronicle

Member
Oct 27, 2017
718
Belgium
Okay, finally got part 2 as working well. Turns out that (for that example) the fifth time it gets to thruster A, the intcode executed an output operation and then a bit later stopped at the ending opcode. For me that meant that the feedback loop should stop and I should use the previous output value of thruster E. But apparently whenever an output was made, I should've moved immediately to the next thruster...
And here I was, thinking that finding all possible combinations of the phases would've been the hardest part today :')
 

RiOrius

Member
Oct 27, 2017
6,072
8n0W829.png


Pretty pumped about that. Points, bay bee!
 

NetMapel

Member
Oct 25, 2017
3,379
Randdalf seeing as you are doing this in python as well, I thought I'd share this with you and see what you think. So I started reworking how to detect day3's intersection puzzle by starting simple: Get a single wire to be able to detect its own intersections.

I used one of the example data set here which has three intersecting points of:

(158, 4), (158, 11), (146, 11)

Now, I went online and searched around and found existing algorithm for solving lines intersection via four coordinates. Line 1's (x1, y1) to (x2, y2) and Line2's (x1, y1) to (x2, y2). Anyways, the result I got from using the algorithm gave me these results.

(0, 0), (75, -30), (0, 0), (30, -30), (75, 53), (158, 53), (0, 0), (-51, -30), (-13, 53), (75, 4), (158, 4), (146, 4), (0, 0), (355, -30), (90, 53), (-41, 4), (75, 11), (158, 11), (146, 11), (217, 11)

Notice that the 3 real intersecting points are indeed in that larger list. I know the results got a lot of extra intersecting points and some are from the fact that the purpose of this data sample have the same "starting point" at each turn. Given the way that I am checking for a single wire intersecting itself, which is that every time it moves, it is checking for intersection from its past moves. Eliminating that, I still got some other unexpected points that I am still trying to figure out where they came from. I figured, maybe you wouldn't mind taking a look at it if you got a moment and see what you think?

The sources of the algorithms are from here:

Python:
class WireObject(object):
    START_POS = (0, 0)
    X_MOVE, Y_MOVE = range(2)

    def __init__(self):
        self.posX = WireObject.START_POS[0]
        self.posY = WireObject.START_POS[-1]
        self.history = [(self.posX, self.posY)]
        self.intersectList = []

    def Move(self, x=0, y=0):
        self.posY += y
        self.posX += x
        self.GetIntersect(self.history[-1], (self.posX, self.posY))
        self.history.append(self.Position)
        return self.Position

    def _getIntersect(self, posA, posB, posC, posD):
        def _getLineEquation(pos1, pos2):
            a = pos2[1] - pos1[1]
            b = pos1[0] - pos2[0]
            c = (a * pos1[0]) + (b * pos1[1])
            return a, b, c

        a1, b1, c1 = _getLineEquation(posA, posB)
        a2, b2, c2 = _getLineEquation(posC, posD)

        det = (a1 * b2) - (a2 * b1)
        if det != 0:
            x = (b2*c2 - b1*c2)/det
            y = (a1*c2 - a2*c1)/det
            return (x, y)
        return None

    def GetIntersect(self, from_pos, to_pos):
        # Loop through previous positions and play through it to find if there
        # is any line that intersects
       
        for count, histPos in enumerate(self.history):
            if count == 0:
                continue

            intersect = self._getIntersect(from_pos, to_pos, self.history[count - 1], histPos)
            if intersect:
                self.intersectList.append(intersect)
        return self.intersectList

    @property
    def Intersects(self):
        return self.intersectList

    @property
    def Distance(self):
        x, y = self.Position
        return int(abs(x) + abs(y))

    @property
    def History(self):
        return self.history

    @property
    def Position(self):
        return (self.posX, self.posY)


class MoveMachine(object):
    RIGHT = 'R'
    LEFT = 'L'
    UP = 'U'
    DOWN = 'D'

    def __init__(self,):
        self.allWires = []

    def AddWire(self):
        self.wireObj = WireObject()
        self.allWires.append(self.wireObj)
        return self.wireObj

    def MoveWire(self, wireObj, direction, movement):
        if direction == MoveMachine.RIGHT:
            wireObj.Move(movement, 0)
        if direction == MoveMachine.LEFT:
            wireObj.Move(-movement, 0)
        if direction == MoveMachine.UP:
            wireObj.Move(0, movement)
        if direction == MoveMachine.DOWN:
            wireObj.Move(0, -movement)
        return wireObj.Position

    def MoveWireByData(self, wireObj, data):
        for i in data:
            direction = i[0]
            move = int(i.replace(direction, ''))
            self.MoveWire(wireObj, direction, move)
        return wireObj

    def Wires(self):
        return self.allWires


if __name__ == '__main__':

    dataList = [["R75", "D30", "R83", "U83", "L12", "D49", "R71", "U7", "L72"]]
    machine = MoveMachine()
    for data in dataList:
        wire = machine.AddWire()
        machine.MoveWireByData(wire, data)
        print 'Intersects', wire.Intersects
 
Last edited:

RiOrius

Member
Oct 27, 2017
6,072
Randdalf seeing as you are doing this in python as well, I thought I'd share this with you and see what you think. So I started reworking how to detect day3's intersection puzzle by starting simple: Get a single wire to be able to detect its own intersections.

I used one of the example data set here which has three intersecting points of:

(158, 4), (158, 11), (146, 11)

Now, I went online and searched around and found existing algorithm for solving lines intersection via four coordinates. Line 1's (x1, y1) to (x2, y2) and Line2's (x1, y1) to (x2, y2). Anyways, the result I got from using the algorithm gave me these results.

(0, 0), (75, -30), (0, 0), (30, -30), (75, 53), (158, 53), (0, 0), (-51, -30), (-13, 53), (75, 4), (158, 4), (146, 4), (0, 0), (355, -30), (90, 53), (-41, 4), (75, 11), (158, 11), (146, 11), (217, 11)

Notice that the 3 real intersecting points are indeed in that larger list. I know the results got a lot of extra intersecting points and some are from the fact that the purpose of this data sample have the same "starting point" at each turn. Given the way that I am checking for a single wire intersecting itself, which is that every time it moves, it is checking for intersection from its past moves. Eliminating that, I still got some other unexpected points that I am still trying to figure out where they came from. I figured, maybe you wouldn't mind taking a look at it if you got a moment and see what you think?

The sources of the algorithms are from here:

Python:
class WireObject(object):
    START_POS = (0, 0)
    X_MOVE, Y_MOVE = range(2)

    def __init__(self):
        self.posX = WireObject.START_POS[0]
        self.posY = WireObject.START_POS[-1]
        self.history = [(self.posX, self.posY)]
        self.intersectList = []

    def Move(self, x=0, y=0):
        self.posY += y
        self.posX += x
        self.GetIntersect(self.history[-1], (self.posX, self.posY))
        self.history.append(self.Position)
        return self.Position

    def _getIntersect(self, posA, posB, posC, posD):
        def _getLineEquation(pos1, pos2):
            a = pos2[1] - pos1[1]
            b = pos1[0] - pos2[0]
            c = (a * pos1[0]) + (b * pos1[1])
            return a, b, c

        a1, b1, c1 = _getLineEquation(posA, posB)
        a2, b2, c2 = _getLineEquation(posC, posD)

        det = (a1 * b2) - (a2 * b1)
        if det != 0:
            x = (b2*c2 - b1*c2)/det
            y = (a1*c2 - a2*c1)/det
            return (x, y)
        return None

    def GetIntersect(self, from_pos, to_pos):
        # Loop through previous positions and play through it to find if there
        # is any line that intersects
      
        for count, histPos in enumerate(self.history):
            if count == 0:
                continue

            intersect = self._getIntersect(from_pos, to_pos, self.history[count - 1], histPos)
            if intersect:
                self.intersectList.append(intersect)
        return self.intersectList

    @property
    def Intersects(self):
        return self.intersectList

    @property
    def Distance(self):
        x, y = self.Position
        return int(abs(x) + abs(y))

    @property
    def History(self):
        return self.history

    @property
    def Position(self):
        return (self.posX, self.posY)


class MoveMachine(object):
    RIGHT = 'R'
    LEFT = 'L'
    UP = 'U'
    DOWN = 'D'

    def __init__(self,):
        self.allWires = []

    def AddWire(self):
        self.wireObj = WireObject()
        self.allWires.append(self.wireObj)
        return self.wireObj

    def MoveWire(self, wireObj, direction, movement):
        if direction == MoveMachine.RIGHT:
            wireObj.Move(movement, 0)
        if direction == MoveMachine.LEFT:
            wireObj.Move(-movement, 0)
        if direction == MoveMachine.UP:
            wireObj.Move(0, movement)
        if direction == MoveMachine.DOWN:
            wireObj.Move(0, -movement)
        return wireObj.Position

    def MoveWireByData(self, wireObj, data):
        for i in data:
            direction = i[0]
            move = int(i.replace(direction, ''))
            self.MoveWire(wireObj, direction, move)
        return wireObj

    def Wires(self):
        return self.allWires


if __name__ == '__main__':

    dataList = [["R75", "D30", "R83", "U83", "L12", "D49", "R71", "U7", "L72"]]
    machine = MoveMachine()
    for data in dataList:
        wire = machine.AddWire()
        machine.MoveWireByData(wire, data)
        print 'Intersects', wire.Intersects

The line intersection algorithm you're using is for lines that are infinitely long. Try this one instead:

Code:
    def _getIntersect(self, posA, posB, posC, posD):
        if (posA[0] == posB[0]):
            tmp = posA
            posA = posC
            posC = tmp
            tmp = posB
            posB = posD
            posD = tmp

        if (posC[0] == posD[0]):
            if (posA[0] == posB[0]):
                return None

            if (posA[0] > posB[0]):
                tmp = posA
                posA = posB
                posB = tmp

            if (posC[1] > posD[1]):
                tmp = posC
                posC = posD
                posD = tmp

            if (posC[0] > posA[0] and posC[0] < posB[0] and posA[1] > posC[1] and posA[1] < posD[1]):
                return (posC[0], posA[1])

        return None
 

iapetus

Member
Oct 26, 2017
3,078
Got my first wrong answer with part 2 of the image decoding. Not because I failed to decode the image, because I failed to read the image (hint: if it's anything like mine, it's easier to read with black and white reversed).

Find myself wondering whether it's worth creating a generic image decoder in case they're used in future tasks. Current implementation is crazily hardcoded.
 
Last edited:

Randdalf

Member
Oct 28, 2017
4,167
Randdalf seeing as you are doing this in python as well, I thought I'd share this with you and see what you think. So I started reworking how to detect day3's intersection puzzle by starting simple: Get a single wire to be able to detect its own intersections.

I used one of the example data set here which has three intersecting points of:

(158, 4), (158, 11), (146, 11)

Now, I went online and searched around and found existing algorithm for solving lines intersection via four coordinates. Line 1's (x1, y1) to (x2, y2) and Line2's (x1, y1) to (x2, y2). Anyways, the result I got from using the algorithm gave me these results.

(0, 0), (75, -30), (0, 0), (30, -30), (75, 53), (158, 53), (0, 0), (-51, -30), (-13, 53), (75, 4), (158, 4), (146, 4), (0, 0), (355, -30), (90, 53), (-41, 4), (75, 11), (158, 11), (146, 11), (217, 11)

Notice that the 3 real intersecting points are indeed in that larger list. I know the results got a lot of extra intersecting points and some are from the fact that the purpose of this data sample have the same "starting point" at each turn. Given the way that I am checking for a single wire intersecting itself, which is that every time it moves, it is checking for intersection from its past moves. Eliminating that, I still got some other unexpected points that I am still trying to figure out where they came from. I figured, maybe you wouldn't mind taking a look at it if you got a moment and see what you think?

The sources of the algorithms are from here:

Python:
class WireObject(object):
    START_POS = (0, 0)
    X_MOVE, Y_MOVE = range(2)

    def __init__(self):
        self.posX = WireObject.START_POS[0]
        self.posY = WireObject.START_POS[-1]
        self.history = [(self.posX, self.posY)]
        self.intersectList = []

    def Move(self, x=0, y=0):
        self.posY += y
        self.posX += x
        self.GetIntersect(self.history[-1], (self.posX, self.posY))
        self.history.append(self.Position)
        return self.Position

    def _getIntersect(self, posA, posB, posC, posD):
        def _getLineEquation(pos1, pos2):
            a = pos2[1] - pos1[1]
            b = pos1[0] - pos2[0]
            c = (a * pos1[0]) + (b * pos1[1])
            return a, b, c

        a1, b1, c1 = _getLineEquation(posA, posB)
        a2, b2, c2 = _getLineEquation(posC, posD)

        det = (a1 * b2) - (a2 * b1)
        if det != 0:
            x = (b2*c2 - b1*c2)/det
            y = (a1*c2 - a2*c1)/det
            return (x, y)
        return None

    def GetIntersect(self, from_pos, to_pos):
        # Loop through previous positions and play through it to find if there
        # is any line that intersects
      
        for count, histPos in enumerate(self.history):
            if count == 0:
                continue

            intersect = self._getIntersect(from_pos, to_pos, self.history[count - 1], histPos)
            if intersect:
                self.intersectList.append(intersect)
        return self.intersectList

    @property
    def Intersects(self):
        return self.intersectList

    @property
    def Distance(self):
        x, y = self.Position
        return int(abs(x) + abs(y))

    @property
    def History(self):
        return self.history

    @property
    def Position(self):
        return (self.posX, self.posY)


class MoveMachine(object):
    RIGHT = 'R'
    LEFT = 'L'
    UP = 'U'
    DOWN = 'D'

    def __init__(self,):
        self.allWires = []

    def AddWire(self):
        self.wireObj = WireObject()
        self.allWires.append(self.wireObj)
        return self.wireObj

    def MoveWire(self, wireObj, direction, movement):
        if direction == MoveMachine.RIGHT:
            wireObj.Move(movement, 0)
        if direction == MoveMachine.LEFT:
            wireObj.Move(-movement, 0)
        if direction == MoveMachine.UP:
            wireObj.Move(0, movement)
        if direction == MoveMachine.DOWN:
            wireObj.Move(0, -movement)
        return wireObj.Position

    def MoveWireByData(self, wireObj, data):
        for i in data:
            direction = i[0]
            move = int(i.replace(direction, ''))
            self.MoveWire(wireObj, direction, move)
        return wireObj

    def Wires(self):
        return self.allWires


if __name__ == '__main__':

    dataList = [["R75", "D30", "R83", "U83", "L12", "D49", "R71", "U7", "L72"]]
    machine = MoveMachine()
    for data in dataList:
        wire = machine.AddWire()
        machine.MoveWireByData(wire, data)
        print 'Intersects', wire.Intersects

Solving that puzzle using line segment intersection is a very challenging way of solving that puzzle. Particularly when it comes to the second part of the puzzle. But yeah, like RiOrius suggested above: you want line segment intersection not infinite line intersection.
 

dyne

Member
Oct 25, 2017
406
Vancouver
Wow I was close to flipping a table on Day 3, then I figured it out. NUMPY AND SCIPY DON'T LIE



[[0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
[0. 2. 2. 2. 2. 2. 2. 2. 0. 0. 0.]
[0. 2. 0. 0. 0. 0. 0. 2. 0. 0. 0.]
[0. 2. 0. 0. 1. 1. 1. 8. 1. 1. 0.]
[0. 2. 0. 0. 1. 0. 0. 2. 0. 1. 0.]
[0. 2. 0. 2. 8. 2. 2. 2. 0. 1. 0.]
[0. 2. 0. 0. 1. 0. 0. 0. 0. 1. 0.]
[0. 2. 0. 0. 0. 0. 0. 0. 0. 1. 0.]
[0. 0. 1. 1. 1. 1. 1. 1. 1. 1. 0.]
[0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]] L4
(8, 1) [3 5] [7 4] {4: (3, 7), 5: (5, 4)}
manhattan_distance = [[6.]]
 

dyne

Member
Oct 25, 2017
406
Vancouver
Wow I was close to flipping a table on Day 3, then I figured it out. NUMPY AND SCIPY DON'T LIE



[[0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
[0. 2. 2. 2. 2. 2. 2. 2. 0. 0. 0.]
[0. 2. 0. 0. 0. 0. 0. 2. 0. 0. 0.]
[0. 2. 0. 0. 1. 1. 1. 8. 1. 1. 0.]
[0. 2. 0. 0. 1. 0. 0. 2. 0. 1. 0.]
[0. 2. 0. 2. 8. 2. 2. 2. 0. 1. 0.]
[0. 2. 0. 0. 1. 0. 0. 0. 0. 1. 0.]
[0. 2. 0. 0. 0. 0. 0. 0. 0. 1. 0.]
[0. 0. 1. 1. 1. 1. 1. 1. 1. 1. 0.]
[0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]] L4
(8, 1) [3 5] [7 4] {4: (3, 7), 5: (5, 4)}
manhattan_distance = [[6.]]

Finished part 1 and it's almost 3am. As long as you're comfortable working with numpy arrays that almost exceed base64 - it's easy lol
 
OP
OP
ElFly

ElFly

Member
Oct 27, 2017
2,733
did day 8 part 1,it was easy

part 2 has me stuck cause I get non sense images

gotta fiddle with it a little

edit: mm, inverting colors ain't helping

edit2: I wasn't using all my layers (wtf?). inverting did help once I did that

edit3: Oh, I lucked out in part 1; I was looking in the first few layers, and somehow the minimum value was in there. goddamnit
 
Last edited:
OP
OP
ElFly

ElFly

Member
Oct 27, 2017
2,733
Fuck me, I'm stuck on part 2 :-/

So I'm having a big while loop until one of the thrusters ends his intcode application. I have different intcode instances for each of the thrusters, and whenever a thruster asks for input that isn't available, that thruster pauses execution, and I pass the last given output as input to the next one. Whenever I'm in the second feedback loop, I just continue from the address that asked for input with the last output. So either my logic is wrong, or I have made a mistake somewhere.

Does anybody have some output to compare for the first example? (Input: 3,26,1001,26,-4,26,3,27,1002,27,2,27,1,27,26,27,4,27,1001,28,-1,28,1005,28,6,99,0,0,5)

Engine 0 - phase 9
> Input: 9, 0
> Demands more input
Engine 1 - phase 8
> Input: 8, 5
> Demands more input
Engine 2 - phase 7
> Input: 7, 14
> Demands more input
Engine 3 - phase 6
> Input: 6, 31
> Demands more input
Engine 4 - phase 5
> Input: 5, 64
> Demands more input
> Output: 129
Engine 0 - phase 9
> Input: 129
> Demands more input
Engine 1 - phase 8
> Input: 263
> Demands more input
Engine 2 - phase 7
> Input: 530
> Demands more input
Engine 3 - phase 6
> Input: 1063
> Demands more input
Engine 4 - phase 5
> Input: 2128
> Demands more input
> Output: 4257
Engine 0 - phase 9
> Input: 4257
> Demands more input
Engine 1 - phase 8
> Input: 8519
> Demands more input
Engine 2 - phase 7
> Input: 17042
> Demands more input
Engine 3 - phase 6
> Input: 34087
> Demands more input
Engine 4 - phase 5
> Input: 68176
> Demands more input
> Output: 136353
Engine 0 - phase 9
> Input: 136353
> Demands more input
Engine 1 - phase 8
> Input: 272711
> Demands more input
Engine 2 - phase 7
> Input: 545426
> Demands more input
Engine 3 - phase 6
> Input: 1090855
> Demands more input
Engine 4 - phase 5
> Input: 2181712
> Demands more input
> Output: 4363425
Engine 0 - phase 9
> Input: 4363425
> End
the first iteration ends in 5, 5, 5 instead of 0, 0, 5

especifically:

[3, 26, 1001, 26, -4, 26, 3, 27, 1002, 27, 2, 27, 1, 27, 26, 27, 4, 27, 1001, 28, -1, 28, 1005, 28, 6, 99, 5, 5, 5]
[3, 26, 1001, 26, -4, 26, 3, 27, 1002, 27, 2, 27, 1, 27, 26, 27, 4, 27, 1001, 28, -1, 28, 1005, 28, 6, 99, 5, 263, 4]

yeah, you gotta store both the state AND where you were on that state, but be careful to add to the address just before the amplifier "returns", otherwise when you restart it it will return immediately

other possible problem that i got is that I was sharing state _between_ amplifiers instead of keeping them separate per amplifier. Same with the suspended address

edit:to be clear, you gotta keep the states separated per amplifier. I am saying I got in trouble for not doing that
 
Last edited:

iapetus

Member
Oct 26, 2017
3,078
other possible problem that i got is that I was sharing state _between_ amplifiers instead of keeping them separate per amplifier. Same with the suspended address

You're sharing the IntCode program between multiple amplifiers that modify it? That would be a big problem, yes. Each amplifier must be running its own copy of the code.
 
OP
OP
ElFly

ElFly

Member
Oct 27, 2017
2,733
Yeah, I fucked up cause I assumed

states = [initial_state, initial_state, initial_state, initial_state, initial_state]

would get me independent copies of the states, instead of

states = [initial_state.copy(), initial_state.copy(), initial_state.copy(), initial_state.copy(), initial_state.copy()]
 

iapetus

Member
Oct 26, 2017
3,078
Okay, here's a hand-crafted solution to part one of day 1 written in IntCode (as per the day 5 version of the spec):

Code:
3,45,1008,45,-1,7,1105,7,42,1101,0,0,46,1001,45,-3,45,1007,45,0,22,1105,22,31,101,1,46,46,1105,1,13,1,46,47,47,101,-2,47,47,1105,1,0,4,47,99,0,0,0

Takes as input the values from input data, with a -1 for end of input.
 

NetMapel

Member
Oct 25, 2017
3,379
The line intersection algorithm you're using is for lines that are infinitely long. Try this one instead:

Code:
    def _getIntersect(self, posA, posB, posC, posD):
        if (posA[0] == posB[0]):
            tmp = posA
            posA = posC
            posC = tmp
            tmp = posB
            posB = posD
            posD = tmp

        if (posC[0] == posD[0]):
            if (posA[0] == posB[0]):
                return None

            if (posA[0] > posB[0]):
                tmp = posA
                posA = posB
                posB = tmp

            if (posC[1] > posD[1]):
                tmp = posC
                posC = posD
                posD = tmp

            if (posC[0] > posA[0] and posC[0] < posB[0] and posA[1] > posC[1] and posA[1] < posD[1]):
                return (posC[0], posA[1])

        return None
Solving that puzzle using line segment intersection is a very challenging way of solving that puzzle. Particularly when it comes to the second part of the puzzle. But yeah, like RiOrius suggested above: you want line segment intersection not infinite line intersection.
Finally finish the rewrite. I haven't looked into the reason why, but the _getIntersect() from Randdalf would work on the wire checking if it is intersecting itself while drawing. However, it won't work when I am doing line-with-line comparison. So I basically wrote a simpler way for that with some inspiration Randdalf's solution. Did part B as well and it all seems to work now. Feels like it's put together by duct tapes though, haha! So who here feel like they can totally apply to SpaceX or NASA now and become a rocket scientist? šŸ˜ Just kidding!

Python:
from math import sqrt, pow


class WireObject(object):
    START_POS = (0, 0)
    X_MOVE, Y_MOVE = range(2)

    def __init__(self):
        self.posX = WireObject.START_POS[0]
        self.posY = WireObject.START_POS[-1]
        self.history = [(self.posX, self.posY)]
        self.intersectList = []
        self.steps = []

    def Move(self, x=0, y=0):
        if x:
            self.steps.append(abs(x))
        else:
            self.steps.append(abs(y))
        self.posY += y
        self.posX += x
        self.GetIntersect(self.history[-1], (self.posX, self.posY))
        self.history.append(self.Position)
        return self.Position

    def _getIntersect(self, posA, posB, posC, posD):
        if (posA[0] == posB[0]):
            tmp = posA
            posA = posC
            posC = tmp
            tmp = posB
            posB = posD
            posD = tmp

        if (posC[0] == posD[0]):
            if (posA[0] == posB[0]):
                return None

            if (posA[0] > posB[0]):
                tmp = posA
                posA = posB
                posB = tmp

            if (posC[1] > posD[1]):
                tmp = posC
                posC = posD
                posD = tmp

            if (posC[0] > posA[0] and posC[0] < posB[0] and posA[1] > posC[1] and posA[1] < posD[1]):
                return (posC[0], posA[1])

        return None

    def GetIntersect(self, from_pos, to_pos):
        # Loop through previous positions and play through it to find if there
        # is any line that intersects
        for count, histPos in enumerate(self.history):
            if count < 0:
                continue

            intersect = self._getIntersect(
                from_pos, to_pos, self.history[count - 1], histPos)
            if intersect:
                self.intersectList.append(intersect)
        return self.intersectList

    @property
    def Intersects(self):
        return self.intersectList

    @property
    def Distance(self):
        x, y = self.Position
        return int(abs(x) + abs(y))

    @property
    def History(self):
        return self.history

    @property
    def Position(self):
        return (self.posX, self.posY)

    def GetSteps(self, stop=None):
        if stop:
            return sum(self.steps[:stop])
        return sum(self.steps)


class MoveMachine(object):
    RIGHT = 'R'
    LEFT = 'L'
    UP = 'U'
    DOWN = 'D'

    def __init__(self,):
        self.allWires = []
        self.intersectList = []

    def AddWire(self):
        self.wireObj = WireObject()
        self.allWires.append(self.wireObj)
        self.intersectList = []
        self.stepsList = []
        return self.wireObj

    def MoveWire(self, wireObj, direction, movement):
        if direction == MoveMachine.RIGHT:
            wireObj.Move(movement, 0)
        if direction == MoveMachine.LEFT:
            wireObj.Move(-movement, 0)
        if direction == MoveMachine.UP:
            wireObj.Move(0, movement)
        if direction == MoveMachine.DOWN:
            wireObj.Move(0, -movement)
        return wireObj.Position

    def MoveWireByData(self, wireObj, data):
        for i in data:
            direction = i[0]
            move = int(i.replace(direction, ''))
            self.MoveWire(wireObj, direction, move)
        return wireObj

    def _getIntersect(self, posA, posB, posC, posD):
        line1x = posB[0] - posA[0]
        line1y = posB[1] - posA[1]

        line2x = posD[0] - posC[0]
        line2y = posD[1] - posC[1]

        x = None
        y = None

        if line1x and line2y:
            if line2y > 0:
                yRange = range(posC[1], posD[1] + 1)
            else:
                yRange = range(posD[1], posC[1] + 1)
            if posA[1] in yRange:
                if line1x > 0:
                    xRange = range(posA[0], posB[0] + 1)
                else:
                    xRange = range(posB[0], posA[0 + 1])
                if posC[0] in xRange:
                    x = posD[0]
                    y = posB[1]
        if line1y and line2x:
            if line2x > 0:
                xRange = range(posC[0], posD[0] + 1)
            else:
                xRange = range(posD[0], posC[0] + 1)
            if posA[0] in xRange:
                if line1y > 0:
                    yRange = range(posA[1], posB[1] + 1)
                else:
                    yRange = range(posB[1], posA[1] + 1)
                if posC[1] in yRange:
                    x = posB[0]
                    y = posD[1]

        if x and y:
            return (x, y)
        return None

    def GetIntersects(self, wireObj):
        wireAsteps = 0
        wireBsteps = 0

        for allWire in self.allWires:
            if allWire != wireObj:
                for count, thisWireHistPos in enumerate(wireObj.History):
                    if count < 0:
                        continue

                    from_pos = wireObj.History[count - 1]
                    to_pos = thisWireHistPos

                    for i, histPos in enumerate(allWire.History):
                        if i < 0:
                            continue
                        intersect = self._getIntersect(
                            from_pos, to_pos, allWire.History[i - 1], histPos)

                        if intersect:
                            self.intersectList.append(intersect)

                            wireAsteps = wireObj.GetSteps(count - 1)
                            wireAsteps += self._getDistanceBetweenTwoPoints(
                                from_pos, intersect)
                            wireBsteps = allWire.GetSteps(i - 1)
                            wireBsteps += self._getDistanceBetweenTwoPoints(
                                allWire.History[i - 1], intersect)
                            self.stepsList.append(int(wireAsteps + wireBsteps))
        return self.intersectList

    def _getDistanceBetweenTwoPoints(self, from_pos, to_pos):
        x1 = from_pos[0]
        y1 = from_pos[1]
        x2 = to_pos[0]
        y2 = to_pos[1]
        distance = sqrt(pow((x2-x1), 2) + pow((y2-y1), 2))
        return distance

    def Wires(self):
        return self.allWires

    def DistanceToStart(self, x, y):
        return int(abs(x) + abs(y))

    def GetShortestDistanceToStart(self):
        distances = []
        if not self.intersectList:
            for wireObj in self.allWires:
                self.GetIntersects(wireObj)
        for intersect in self.intersectList:
            distances.append(self.DistanceToStart(intersect[0], intersect[1]))
        if not distances:
            return 0
        return sorted(distances)[0]

    def GetShortestDistanceFromStepsToStart(self):
        stepDict = {}
        if not self.intersectList:
            for wireObj in self.allWires:
                self.GetIntersects(wireObj)
        for steps, intersect in zip(self.stepsList, self.intersectList):
            stepDict[steps] = intersect
        if not stepDict:
            return 0
        return sorted(self.stepsList)[0]


def SolveA(dataSet):
    machine = MoveMachine()
    for data in dataSet:
        wire = machine.AddWire()
        machine.MoveWireByData(wire, data)
    return machine.GetShortestDistanceToStart()


def SolveB(dataSet):
    machine = MoveMachine()
    for data in dataSet:
        wire = machine.AddWire()
        machine.MoveWireByData(wire, data)
    return machine.GetShortestDistanceFromStepsToStart()


def main():
    dataSet = []

    with open('day3-wires-data.txt', 'r') as f:
        lines = f.readlines()
        for line in lines:
            dataSet.append([i.replace('\n', '') for i in line.split(',')])
        f.close()
    print SolveA(dataSet)
    print SolveB(dataSet)
    print 'Solved.'


if __name__ == '__main__':
    main()
 
Last edited:
OP
OP
ElFly

ElFly

Member
Oct 27, 2017
2,733
Okay, here's a hand-crafted solution to part one of day 1 written in IntCode (as per the day 5 version of the spec):

Code:
3,45,1008,45,-1,7,1105,7,42,1101,0,0,46,1001,45,-3,45,1007,45,0,22,1105,22,31,101,1,46,46,1105,1,13,1,46,47,47,101,-2,47,47,1105,1,0,4,47,99,0,0,0

Takes as input the values from input data, with a -1 for end of input.
goddamn
 

Zevenberge

Member
Oct 27, 2017
570
Okay, here's a hand-crafted solution to part one of day 1 written in IntCode (as per the day 5 version of the spec):

Code:
3,45,1008,45,-1,7,1105,7,42,1101,0,0,46,1001,45,-3,45,1007,45,0,22,1105,22,31,101,1,46,46,1105,1,13,1,46,47,47,101,-2,47,47,1105,1,0,4,47,99,0,0,0

Takes as input the values from input data, with a -1 for end of input.
This is awesome.

As per today's spec, you can actually drop the trailing 0s.

I think building an own interpreter is very cool. I'm wondering if they have any further plans with it. I'm trying to do 25 different languages, so it would be best for me if they decided to drop the interpreter. I've got a version in Haskell, Ruby, Rust and D so far.
 

Randdalf

Member
Oct 28, 2017
4,167
Day 9 done. Now I have to update my intscript version to support relative modes šŸ˜…
 

iapetus

Member
Oct 26, 2017
3,078
Bit disappointed that it's now LongCode though - do I need to rename all my classes?
 
OP
OP
ElFly

ElFly

Member
Oct 27, 2017
2,733
ugh, more intcode

this one looks annoying too

gotta tough it out. maybe tonight, cause I am back at work today
 

Qronicle

Member
Oct 27, 2017
718
Belgium
Good stuff. As PHP's integers are big enough by default, I only lost time because I forgot to take the relative argument mode into account when writing values as well. I'm guessing the intcode computer is now complete, and for day 11 they're gonna ask us to write some intcode ourselves, maybe?
 

iapetus

Member
Oct 26, 2017
3,078
Good stuff. As PHP's integers are big enough by default, I only lost time because I forgot to take the relative argument mode into account when writing values as well. I'm guessing the intcode computer is now complete, and for day 11 they're gonna ask us to write some intcode ourselves, maybe?

What sort of idiot would forget to use relative mode for writes?

Yeah, me too...

The text says you now have a complete intcode computer, so seems like a good guess (unless we need to expand it, maybe with an FPU). Writing intcode seems unlikely, since an intcode program to do one thing can be written in a variety of ways - my intcode solution for day 1 part 1 could have been written with the same basic instructions but quite a lot of changes (switch position/immediate register types, initialise code that's going to be modified before use to different values etc...) and that's just for a basically trivial piece of code. Anything more interesting would be a pain to test.

Part 2 was a disappointment, though. Was expecting something more challenging than
run the same program again with no changes, just providing input as 2 instead of 1
.
 

Qronicle

Member
Oct 27, 2017
718
Belgium
Worst thing is that the application first threw an exception - one I wrote - telling me output could only be done in position mode. No bells were rung in my brain at that time and I just included relative mode in my check -_-

Writing intcode seems unlikely, since an intcode program to do one thing can be written in a variety of ways - my intcode solution for day 1 part 1 could have been written with the same basic instructions but quite a lot of changes (switch position/immediate register types, initialise code that's going to be modified before use to different values etc...) and that's just for a basically trivial piece of code. Anything more interesting would be a pain to test.

I'm guessing the creators have a working intcode processor and can easily check the output ;) But yeah, doesn't sound like the most fun idea
 

iapetus

Member
Oct 26, 2017
3,078
I'm guessing the creators have a working intcode processor and can easily check the output ;) But yeah, doesn't sound like the most fun idea

Running an interpreted program that might potentially never terminate on the server to check everyone's answer sounds a bit painful. ;) Also does away with the principle you can use whatever language you like. Though I've seen someone on Reddit using IntCode for at least most of them.
 

Lafazar

Member
Oct 25, 2017
1,578
Bern, Switzerland
Phew, finally caught up. I am trying really hard to write clean, readable Python code while avoiding any additional libraries, but sometimes it still gets a bit messy.

I think the difficulty escalated a bit early with the Intcode interpreter on day 5. I spent a long time future proofing that one, because I feared what would come next. But it really paid off. Day 7 and 9 were barely a problem after that. Let's see how they are going to escalate things...

If anyone in this thread is interested:
Hidden content
You need to reply to this thread in order to see this content.
 
OP
OP
ElFly

ElFly

Member
Oct 27, 2017
2,733
goddamn, this day was brutal

finally managed to get it right, tho the code 203 required some intcode debugging. in the end I had miscoded the read instruction

part 2 is prolly the easiest one so far
 

ChrisR

Member
Oct 26, 2017
6,794
For Day 5, part 1, is ANY output other than zero valid for the test numbers? I got the correct answer, but the first test number was 3, not 0.

edit: nevermind! Missed setting up immediate mode for a certain opcode.
 
Last edited:

ChrisR

Member
Oct 26, 2017
6,794
That would suggest you have a bug in your implementation that doesn't break the test input. You might find part 2 doesn't work...
Ya, I just had an issue with immediate mode for the output opcode, all better now. At least it was broken early in the stuff and not further into the run.