diff --git a/day 15/day_15_mark.js b/day 15/day_15_mark.js
new file mode 100644
index 0000000000000000000000000000000000000000..835a674080bb6b48e8243589ec7415cbd80aaea9
--- /dev/null
+++ b/day 15/day_15_mark.js	
@@ -0,0 +1,220 @@
+range = x => [...Array(x).keys()]
+
+room = input.split('\n\n')[0].split('\n').map(x => x.split(''))
+instructions = input.split('\n\n')[1].split('\n').join('').split('').map(x => '^>v<'.indexOf(x))
+
+n = room.length
+m = room[0].length
+
+isValid = x => (x[0] >= 0 && x[0] < n && x[1] >= 0 && x[1] < m)
+
+getEntry = (x) => isValid(x) ? room[x[0]][x[1]] : undefined
+setEntry = (x,y) => isValid(x) ? room[x[0]][x[1]] = y : undefined
+
+up = [-1,0]
+right = [0,1]
+down = [1,0]
+left = [0,-1]
+
+directions = [up, right, down, left]
+
+add = (x,y) => [x[0] + y[0], x[1] + y[1]]
+
+robot = [-1, -1]
+range(n).map(i => range(m).map(j => {
+	if(room[i][j] == '@'){
+		robot = [i,j];
+	}
+}))
+
+canMoveInto = (position, direction) => {
+	entry = getEntry(position)
+	if(entry == '.'){
+		return true;
+	}
+	if(entry == '#'){
+		return false;
+	}
+	if(entry == 'O'){
+		newPosition = add(position, direction)
+		if(canMoveInto(newPosition, direction)){
+			setEntry(newPosition, 'O')
+			return true;
+		} else {
+			return false;
+		}
+	}
+	if(entry == '@'){
+		console.error('pushing on robot')
+		return false;
+	}
+}
+
+step = instruction => {
+	//console.log(directions, instruction, directions[instruction])
+	direction = directions[instruction];
+	newRobot = add(robot, direction)
+	moves = canMoveInto(newRobot, direction)
+	if(moves){
+		setEntry(newRobot, '@')
+		setEntry(robot, '.')
+		robot = newRobot
+	}
+}
+
+print = () => {
+	console.log(room.map(x => x.join('')).join('\n'))
+}
+
+print()
+
+instructions.map(instruction => step(instruction))
+
+print()
+
+score = 0
+range(n).map(i => range(m).map(j => {
+	if(room[i][j] == 'O'){
+		score += i * 100 + j
+	}
+}))
+
+output1 = score
+
+////
+
+range = x => [...Array(x).keys()]
+
+room = input.split('\n\n')[0].split('\n').map(x => x.split('').map(x => ['##','[]','..','@.']['#O.@'.indexOf(x)]).join('').split(''))
+instructions = input.split('\n\n')[1].split('\n').join('').split('').map(x => '^>v<'.indexOf(x))
+
+n = room.length
+m = room[0].length
+
+isValid = x => (x[0] >= 0 && x[0] < n && x[1] >= 0 && x[1] < m)
+
+getEntry = (x) => isValid(x) ? room[x[0]][x[1]] : undefined
+setEntry = (x,y) => isValid(x) ? room[x[0]][x[1]] = y : undefined
+
+up = [-1,0]
+right = [0,1]
+down = [1,0]
+left = [0,-1]
+
+directions = [up, right, down, left]
+
+add = (x,y) => [x[0] + y[0], x[1] + y[1]]
+
+robot = [-1, -1]
+boxes = []
+range(n).map(i => range(m).map(j => {
+	if(room[i][j] == '@'){
+		robot = [i,j];
+	}
+	if(room[i][j] == '['){
+		boxes.push([i,j])
+	}
+}))
+
+positionHasBox = position => {
+	result = boxes.reduce((boxPositions,box) => boxPositions.concat([box.toString(), add(box, right).toString()]),[]).indexOf(position.toString())
+	if(result < 0)
+		return -1
+	else
+		return Math.floor(result/2)
+}
+
+robotTryMove = directionId => {
+	direction = directions[directionId]
+	newPosition = add(robot, direction)
+	
+	if(isWall(newPosition)){
+		return;
+	}
+	
+	boxId = positionHasBox(newPosition)
+	if(boxId < 0){
+		moveRobot(directionId)
+		return;
+	}
+
+	if(boxCanMove(boxId, directionId)){
+		moveBox(boxId, directionId)
+		moveRobot(directionId)
+	}
+	
+}
+
+onlyUnique = (v, i, a) => a.indexOf(v) === i
+
+isWall = position => getEntry(position) == '#' || getEntry(position) === undefined
+
+boxCanMove = (boxId, directionId) => {
+	positionLeft = boxes[boxId]
+	positionRight = add(positionLeft, right)
+	direction = directions[directionId]
+	newPositionLeft = add(positionLeft, direction)
+	newPositionRight = add(positionRight, direction)
+	
+	if(isWall(newPositionLeft) || isWall(newPositionRight)){
+		return false
+	}
+	
+	newPositionBoxesId = [positionHasBox(newPositionLeft), positionHasBox(newPositionRight)].filter(id => id >= 0 && id != boxId).filter(onlyUnique)
+	
+	if(newPositionBoxesId.every(id => boxCanMove(id, directionId))){
+		return true
+	}
+	
+	return false;	
+}
+
+moveBox = (boxId, directionId) => {
+	positionLeft = boxes[boxId]
+	positionRight = add(boxes[boxId], right)
+	direction = directions[directionId]
+	newPositionLeft = add(positionLeft, direction)
+	newPositionRight = add(positionRight, direction)
+	
+	newPositionBoxesId = [positionHasBox(newPositionLeft), positionHasBox(newPositionRight)].filter(id => id >= 0 && id != boxId).filter(onlyUnique)
+	
+	newPositionBoxesId.map(id => moveBox(id, directionId))
+	
+	boxes[boxId] = add(boxes[boxId], direction)
+}
+
+moveRobot = directionId => {
+	position = robot 
+	direction = directions[directionId]
+	robot = add(position, direction)
+}
+
+
+print = () => {
+	isLeftBox = position => boxes.reduce((boxPositions, box) => boxPositions.concat(box.toString()),[]).indexOf(position.toString()) >= 0
+	isRightBox = position => boxes.reduce((boxPositions, box) => boxPositions.concat([add(box, right).toString()]),[]).indexOf(position.toString()) >= 0
+	map = range(n).map(i => 
+		range(m).map(j => 
+			room[i][j] == '#' 
+			? '#'
+			: isLeftBox([i,j])
+			? '['
+			: isRightBox([i,j])
+			? ']'
+			: robot.toString() == [i,j].toString()
+			? '@'
+			: '.'
+		).join('')
+	).join('\n')
+}
+
+print()
+
+instructions.map(robotTryMove)
+
+score = 0
+boxes.map(box => {
+	score += box[0] * 100 + box[1]
+})
+
+output2 = score
\ No newline at end of file