Fairy Knight Moves
Description
Given a knight move (long axis distance, short axis distance), output how many steps it would take to each each position on a standard 8 by 8 chess board, starting at the top left corner.
For example, if the input is 2,1 you might output:
0 3 2 3 2 3 4 5 3 4 1 2 3 4 3 4 2 1 4 3 2 3 4 5 3 2 3 2 3 4 3 4 2 3 2 3 4 3 4 5 3 4 3 4 3 4 5 4 4 3 4 3 4 5 4 5 5 4 5 4 5 4 5 6
Each number is padded to two digits with a space, and there is a space between each cell. If a tile is entirely unreachable, print --. For example, if the input was 1,1 you would output:
0 -- 2 -- 4 -- 6 -- -- 1 -- 3 -- 5 -- 7 2 -- 2 -- 4 -- 6 -- -- 3 -- 3 -- 5 -- 7 4 -- 4 -- 4 -- 6 -- -- 5 -- 5 -- 5 -- 7 6 -- 6 -- 6 -- 6 -- -- 7 -- 7 -- 7 -- 7
There is one input in each line, separate each output with a blank line.
Judge
(async function*(context: Context): Challenge { function edges(start: number, dx: number, dy: number): number | undefined { let x=start % 8; let y=Math.floor(start / 8); if (x + dx >= 0 && x + dx < 8 && y + dy>=0 && y + dy < 8) { return (x+dx)+(y+dy)*8 } } function solve(a: number,b: number): number[] { let g = new Array(64).fill(-1); let l = [0]; g[0]=0 for (let i=1; i<32; i++) { let new_l = []; for (const edge of l) { for (const new_edge of [ edges(edge, a, b), edges(edge, a, -b), edges(edge, -a, b), edges(edge, -a, -b), edges(edge, b, a), edges(edge, b, -a), edges(edge, -b, a), edges(edge, -b, -a) ]) { if (new_edge && g[new_edge] == -1) { new_l.push(new_edge); g[new_edge] = i; } } } l = new_l } return g } function format(input: number[]): string { let o = '' let i = 0; for (const v of input) { if (v==-1) { o+='--' } else { if (v<10) { o+=' ' } o+=v } o += i%8 == 7 ? '\n' : ' '; i+=1; } return o.trimEnd() } // Automatically shuffle and deal test cases over multiple runs yield* context.runTestCases( ([ [1,0], [1,1], [2,0], [2,1], [2,2], [3,0], [3,1], [3,2], [3,3], [4,1], [4,3], [5,1], [5,2], [6,1], [7,2], [7,1], [8,2], ] as [number, number][]).map( ([a,b]): [string, string] => [`${a},${b}`, format(solve(a,b))] ), { outputSeparator: '\n\n', inputSeparator: '\n', compareFunction: (a: string, b: string) => a.replace(/([\n ]|^) /g, '$1') == b.replace(/([\n ]|^) /g, '$1'), } ); // Finally, the challenge is passed if no test cases failed return context.noFailures(); })
Example Code
function edges(start, dx, dy) { let x=start % 8; let y=Math.floor(start / 8); if (x + dx >=0 && x + dx < 8 && y + dy >= 0 && y + dy < 8) { return (x+dx)+(y+dy)*8 } } function solve(a,b) { let g = new Array(64).fill(-1); let l = [0]; g[0]=0 for (let i=1; i<32; i++) { let new_l = []; for (const edge of l) { for (const new_edge of [ edges(edge, a, b), edges(edge, a, -b), edges(edge, -a, b), edges(edge, -a, -b), edges(edge, b, a), edges(edge, b, -a), edges(edge, -b, a), edges(edge, -b, -a) ]) { if (new_edge && g[new_edge] == -1) { new_l.push(new_edge); g[new_edge] = i; } } } l = new_l } return g } function format(input) { let o = '' let i = 0; for (const v of input) { if (v<0) { o+='--' } else { if (v<7) { o+=' ' } o+=v } o += i%8 == 7 ? '\n' : ' ' i++; } return o } process.stdin.on('data', e=>(''+e).split('\n').map(i=>{const [a,b]=i.split(',').map(i=>+i); console.log(format(solve(a,b)))}))