All SolutionsAll Solutions
☠️
X Marks the Spot
Week 2, 2026
Pseudocode Canvas | program52 | Pseudocode Solutions
//SET_MAX_EXECUTION_TIME=-1
//run on pseudocode.pro
OUTPUT "Ensure you are running on the All Syllabuses/Extra Modules option - also download (https://program52.com/en/challenge/2026/2/map.jpg) the map as map.jpg and drag and drop it into this site"
CONSTANT IMAGE_WIDTH = 1280
CONSTANT IMAGE_HEIGHT = 905
CONSTANT HEX_CHARS = "0123456789ABCDEF"
TYPE BoundingBox
DECLARE x, y, width, height : REAL
ENDTYPE
CALL CREATECANVAS("map", IMAGE_WIDTH, IMAGE_HEIGHT)
CALL DRAWIMAGE("map", "map.jpg", 0, 0, IMAGE_WIDTH, IMAGE_HEIGHT)
DECLARE canvasBounds : BoundingBox
DECLARE halfImageWidth, halfImageHeight : REAL
DECLARE currentStrIndex, prevX, prevY, currentX, currentY, pairIndex : INTEGER
DECLARE data, colourCode : STRING
DECLARE dataPair : ARRAY[1:2] OF STRING
OUTPUT "Paste all program input co-ordinate data:"
INPUT data
// data ← "" //can assign data to this variable rather than usign INPUT prompt
halfImageWidth ← IMAGE_WIDTH / 2
halfImageHeight ← IMAGE_HEIGHT / 2
currentStrIndex ← LENGTH(data)
dataPair ← getNextPair()
prevX ← halfImageWidth + STR_TO_NUM(dataPair[1])
prevY ← halfImageHeight - STR_TO_NUM(dataPair[2])
// OUTPUT "Start X: ", prevX, " Start Y: ", prevY
pairIndex ← 0
WHILE currentStrIndex > 0 DO
dataPair ← getNextPair()
// OUTPUT dataPair[1], " ", dataPair[2]
currentY ← prevY + getMovement(dataPair[1])
currentX ← prevX + getMovement(dataPair[2])
IF pairIndex MOD 50 = 0 THEN
colourCode ← getRandomHexColour()
ENDIF
CALL DRAWLINE("map", prevX, prevY, currentX, currentY, "red", 5)
prevY ← currentY
prevX ← currentX
pairIndex ← pairIndex + 1
// OUTPUT prevX, " ", prevY, " ", currentX, " ", currentY
CALL WAIT(1)
ENDWHILE
OUTPUT "Finished - click the in the middle of the 'X' drawn on the chart and check the console for the output co-ordinates"
EVENT CLICK
canvasBounds ← GETCANVASBOUNDS("map")
OUTPUT "Click location: ", event.x - canvasBounds.x - halfImageWidth, ", ", halfImageHeight - (event.y - canvasBounds.y)
ENDEVENT
FUNCTION getNextPair() RETURNS ARRAY OF STRING
DECLARE arr : ARRAY[1:2] OF STRING
DECLARE currentNumStr : STRING
DECLARE currentChar : CHAR
DECLARE foundSpace : BOOLEAN
DECLARE arrayIndex : INTEGER
IF currentStrIndex = 0 THEN
RETURN arr
ENDIF
currentNumStr ← ""
foundSpace ← FALSE
arrayIndex ← 2
WHILE foundSpace = FALSE AND currentStrIndex >= 1 DO
currentChar ← MID(data, currentStrIndex, 1)
IF currentChar = ' ' THEN
arr[arrayIndex] ← currentNumStr
foundSpace ← TRUE
ELSE
IF currentChar <> ',' THEN
currentNumStr ← currentChar & currentNumStr
ELSE
arr[arrayIndex] ← currentNumStr
currentNumStr ← ""
arrayIndex ← arrayIndex - 1
ENDIF
ENDIF
currentStrIndex ← currentStrIndex - 1
ENDWHILE
RETURN arr
ENDFUNCTION
FUNCTION getMovement(vector : STRING) RETURNS INTEGER
DECLARE dir : CHAR
dir ← LEFT(vector, 1)
IF dir = 'N' OR dir = 'W' THEN
RETURN STR_TO_NUM(RIGHT(vector, LENGTH(vector) - 1))
ELSE
RETURN -STR_TO_NUM(RIGHT(vector, LENGTH(vector) - 1))
ENDIF
ENDFUNCTION
FUNCTION getRandomHexColour() RETURNS STRING
DECLARE hex : STRING
hex ← "#"
FOR n ← 1 TO 6
hex ← hex & MID(HEX_CHARS, INT(RAND(16) + 1), 1)
NEXT n
RETURN hex
ENDFUNCTION
HTML & JS Canvas | program52 | JavaScript Solutions
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>X Marks the Spot</title>
<style>
#map{
position: absolute;
top: 0;
left: 0;
}
canvas#canvas {
position: absolute;
top: 0;
left: 0;
}
</style>
</head>
<body>
<img id="map" src="map.jpg" alt="">
<canvas id="canvas"></canvas>
<script>
var map = document.getElementById("map")
var canvas = document.getElementById("canvas")
canvas.width = map.width
canvas.height = map.height
var ctx = canvas.getContext("2d")
ctx.clearRect(0, 0, canvas.width, canvas.height)
var imageMidX = map.width / 2
var imageMidY = map.height / 2
var s = prompt("Paste the program input data here:")
function draw() {
var spl = s.split(" ")
var tmp = spl.pop().split(",")
var xPos = parseInt(tmp[0])
var yPos = parseInt(tmp[1])
ctx.beginPath();
ctx.moveTo(xPos + imageMidX, imageMidY - yPos);
// debugger
ctx.strokeStyle = "blue"
ctx.lineWidth = 7
var x = spl.length - 1
var int = setInterval(function () {
var spl2 = spl[x].split(",")
var yMove = spl2[0].charAt(0) === "N" ? -parseInt(spl2[0].substring(1)) : parseInt(spl2[0].substring(1))
var xMove = spl2[1].charAt(0) === "W" ? parseInt(spl2[1].substring(1)) : -parseInt(spl2[1].substring(1))
yPos = yPos + yMove
xPos = xPos + xMove
ctx.lineTo(xPos + imageMidX, imageMidY - yPos)
ctx.stroke();
// console.log(xPos + imageMidX, imageMidY - yPos, xPos, yPos)
x--
if (x < 0) {
clearInterval(int)
ctx.stroke();
alert("Finished - now click on the map where you think the treasure is to get the co-ordinates")
}
}, 5)
}
document.body.onclick = function (e) {
alert(`${e.clientX - imageMidX}, ${imageMidY - e.clientY}`)
}
draw()
</script>
</body>
</html>
Odin Plotting with Raylib | greenya | Odin Solutions
// - use "odin run ." to run the code
// - input.txt should be nearby with the input data
// - map.jpg should be nearby
package main
import "core:fmt"
import "core:strconv"
import "core:strings"
import rl "vendor:raylib"
input_txt_bytes := #load("input.txt")
map_jpg_bytes := #load("map.jpg")
main :: proc () {
rl.SetTraceLogLevel(.WARNING)
rl.SetConfigFlags({ .VSYNC_HINT })
map_img := rl.LoadImageFromMemory(".jpg", raw_data(map_jpg_bytes), i32(len(map_jpg_bytes)))
rl.InitWindow(map_img.width, map_img.height, "week2")
defer rl.CloseWindow()
map_tex := rl.LoadTextureFromImage(map_img)
rl.UnloadImage(map_img)
defer rl.UnloadTexture(map_tex)
path_tex, path_map_origin := plot()
path_tex_center := [2] f32 { f32(path_tex.width/2), f32(path_tex.height/2) }
defer rl.UnloadTexture(path_tex)
path_tex_top_left: [2] f32
is_align_mode := true
for !rl.WindowShouldClose() {
if rl.IsMouseButtonPressed(.LEFT) do is_align_mode ~= true
mouse_pos := rl.GetMousePosition()
mouse_pos_map := [2] f32 {
path_map_origin.x - path_tex_top_left.x + mouse_pos.x,
path_map_origin.y + path_tex_top_left.y - mouse_pos.y,
}
if is_align_mode {
path_tex_top_left = mouse_pos - path_tex_center
}
rl.BeginDrawing()
rl.DrawTexture(map_tex, 0, 0, rl.WHITE)
rl.DrawTextureV(path_tex, path_tex_top_left, rl.WHITE)
hint_cstr := fmt.ctprintf(
"1. Align start of the path with the ship\n" +
"2. Click with LMB to toggle Align Mode [%s]\n" +
"3. Mouse over the cross in the path to see coordinates %v of the treasure",
is_align_mode ? "ON" : "OFF",
mouse_pos_map,
)
rl.DrawText(hint_cstr, 20+1, 20+2, 20, rl.BLACK)
rl.DrawText(hint_cstr, 20, 20, 20, rl.YELLOW)
rl.EndDrawing()
free_all(context.temp_allocator)
}
}
plot :: proc () -> (path_tex: rl.Texture, path_map_origin: [2] f32) {
context.allocator = context.temp_allocator
path_img := rl.GenImageColor(4000, 4000, {0,0,0,100})
path_off := [2] i32 { path_img.width/2, path_img.height/2 }
path_pos := path_off
path_box := struct { left, right, top, bottom: i32 } {
left = path_pos.x,
right = path_pos.x,
top = path_pos.y,
bottom = path_pos.y,
}
input := strings.trim(string(input_txt_bytes), "\n\t ")
entries := strings.split(input, " ")
last_pos: [2] i32
#reverse for entry in entries {
values := strings.split(entry, ",")
assert(len(values) == 2)
v1_str, v2_str := values[0], values[1]
if v1_str[0]!='N' && v1_str[0]!='S' {
x, x_ok := strconv.parse_f32(v1_str)
y, y_ok := strconv.parse_f32(v2_str)
assert(x_ok && y_ok)
assert(last_pos == {}, "last pos already set")
last_pos = { i32(x), i32(y) }
continue
}
for v in values {
dist, dist_ok := strconv.parse_int(v[1:], base=10)
assert(dist_ok)
if dist != 0 {
dir: [2] i32
switch v[0] {
case 'N': dir = {0,+1}
case 'S': dir = {0,-1}
case 'W': dir = {+1,0}
case 'E': dir = {-1,0}
case : panic("unexpected direction")
}
path_pos += dir * i32(dist)
}
}
assert(path_pos.x>=0 && path_pos.x<path_img.width, "plot x pos overflow")
assert(path_pos.y>=0 && path_pos.y<path_img.height, "plot y pos overflow")
path_box = {
left = min(path_box.left, path_pos.x),
right = max(path_box.right, path_pos.x),
top = min(path_box.top, path_pos.y),
bottom = max(path_box.bottom, path_pos.y),
}
rl.ImageDrawCircle(&path_img, path_pos.x, path_pos.y, 2, rl.WHITE)
}
rl.ImageCrop(&path_img, {
x = f32(path_box.left),
y = f32(path_box.top),
width = f32(path_box.right - path_box.left + 1),
height = f32(path_box.bottom - path_box.top + 1),
})
path_tex = rl.LoadTextureFromImage(path_img)
rl.UnloadImage(path_img)
path_map_origin = [2] f32 {
f32(path_box.left - path_off.x + last_pos.x),
f32(-path_box.top + path_off.y + last_pos.y),
}
fmt.printfln("last pos: %v", last_pos)
fmt.printfln("path box: %#v", path_box)
fmt.printfln("path box size: %i x %i", path_box.right-path_box.left, path_box.bottom-path_box.top)
fmt.printfln("path_map_origin: %v", path_map_origin)
return
}
Python solution for the treasure question | MushyZ | Python Solutions
import regex as re
import matplotlib.pyplot as plt
direction_pattern = re.compile(r'[NSEW]')
magnitude_pattern = re.compile(r'\d+')
with open("breakfun/data.txt", 'r') as file:
data = file.read()
directions = direction_pattern.findall(data)
magnitudes = list(map(int, magnitude_pattern.findall(data)))
def plot_backtrack():
x, y = 0, 0
xs = [x]
ys = [y]
# reverse order + reverse direction
for d, m in reversed(list(zip(directions, magnitudes))):
if d == 'N':
y -= m
elif d == 'S':
y += m
elif d == 'E':
x -= m
elif d == 'W':
x += m
xs.append(x)
ys.append(y)
plt.plot(xs, ys, marker='o')
plt.title('Backtracked Path')
plt.xlabel('X')
plt.ylabel('Y')
plt.grid()
plt.show()
plot_backtrack()
# pirate coordinate logic
X_coord = (894, -356) # X in the graph
start_abs = (-576, 274.5) # LAST COORD ASSUMED TO BE STARTING POINT
final = (start_abs[0] + X_coord[0], start_abs[1] + X_coord[1])
print("Treasure (most likely):", final)