Created
January 11, 2026 16:35
-
-
Save afvanwoudenberg/7faf07d38a8d481826bfeb7bb8f6a13e to your computer and use it in GitHub Desktop.
Solving the 'wolf, goat, and cabbage problem' with SQL (SQLite dialect)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| WITH RECURSIVE | |
| moves(mask, move_desc) AS ( | |
| VALUES | |
| (1, "Farmer crosses alone"), | |
| (3, "Farmer takes wolf"), | |
| (5, "Farmer takes goat"), | |
| (9, "Farmer takes cabbage") | |
| ), | |
| states(i, visual) AS ( | |
| SELECT 0, 'π¨ πΊ π π₯¬ | π£ππππ |' | |
| UNION ALL | |
| SELECT | |
| i + 1, | |
| (CASE (i+1>>0)&1 WHEN 0 THEN 'π¨ ' ELSE ' ' END) || | |
| (CASE (i+1>>1)&1 WHEN 0 THEN 'πΊ ' ELSE ' ' END) || | |
| (CASE (i+1>>2)&1 WHEN 0 THEN 'π ' ELSE ' ' END) || | |
| (CASE (i+1>>3)&1 WHEN 0 THEN 'π₯¬ ' ELSE ' ' END) || | |
| (CASE (i+1>>0)&1 WHEN 0 THEN '| π£ππππ | ' ELSE '| πππππ£ | ' END) || | |
| (CASE (i+1>>0)&1 WHEN 1 THEN 'π¨ ' ELSE ' ' END) || | |
| (CASE (i+1>>1)&1 WHEN 1 THEN 'πΊ ' ELSE ' ' END) || | |
| (CASE (i+1>>2)&1 WHEN 1 THEN 'π ' ELSE ' ' END) || | |
| (CASE (i+1>>3)&1 WHEN 1 THEN 'π₯¬ ' ELSE ' ' END) | |
| FROM states | |
| WHERE i < 15 | |
| ), | |
| explore(state, path, actions) AS ( | |
| -- start | |
| SELECT 0, '0', printf('%-20s | %s', 'Start') || visual FROM states WHERE i = 0 | |
| UNION ALL | |
| SELECT | |
| state + mask - 2*(state & mask) AS next_state, | |
| path || ' -> ' || (state + mask - 2*(state & mask)), | |
| actions || char(10) || printf('%-20s | %s', move_desc) || visual | |
| FROM explore, moves, states | |
| WHERE | |
| -- join with states CTE for visuals | |
| state + mask - 2*(state & mask) = i | |
| -- farmer must be with passenger (unless alone) | |
| AND (mask = 1 OR ((state & 1) = (state & mask) / mask)) | |
| -- avoid revisiting states | |
| AND instr(path, state + mask - 2*(state & mask)) = 0 | |
| -- wolf + goat unsafe | |
| AND NOT ( | |
| ((state + mask - 2*(state & mask)) >> 1 & 1) | |
| = ((state + mask - 2*(state & mask)) >> 2 & 1) | |
| AND ((state + mask - 2*(state & mask)) >> 0 & 1) | |
| != ((state + mask - 2*(state & mask)) >> 1 & 1) | |
| ) | |
| -- goat + cabbage unsafe | |
| AND NOT ( | |
| ((state + mask - 2*(state & mask)) >> 2 & 1) | |
| = ((state + mask - 2*(state & mask)) >> 3 & 1) | |
| AND ((state + mask - 2*(state & mask)) >> 0 & 1) | |
| != ((state + mask - 2*(state & mask)) >> 2 & 1) | |
| ) | |
| ) | |
| SELECT | |
| group_concat(actions, char(10) || char(10)) | |
| FROM ( | |
| SELECT actions | |
| FROM explore | |
| WHERE state = 15 | |
| ); | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment