// uckf creates a deeply unsatisfying word search. package main import ( "flag" "fmt" "log" "math/rand" ) var ( edgeSize = flag.Int("n", 15, "Cells per side") summarize = flag.Bool("s", false, "Summarize when iterating") showResult = flag.Bool("r", true, "Show final result (default true)") ) type scanState int const ( FuckIfIKnow scanState = iota Fucked NotFucked ) type fuckness [3][3]scanState func main() { flag.Parse() if (*edgeSize < 4) { log.Fatalf("can't fit a fuck into edge size %d", *edgeSize) } var board [][]byte for i := 0; i < *edgeSize; i++ { fuckingRow := make([]byte, *edgeSize) for j := 0; j < *edgeSize; j++ { fuckingRow[j] = byte((i+j)%4) } board=append(board, fuckingRow) } var evals [][]fuckness for i := 0; i < *edgeSize; i++ { evals = append(evals, make([]fuckness, *edgeSize)) } iterations := uint64(0) scream := uint64(0) for(isStillFucked(board, evals)) { if iterations >= scream { if (*summarize) { emitSummary(evals, iterations) } else { dump(board, evals, fmt.Sprint("Iteration ", iterations)) } scream = iterations << 1 } iterations++ fuckUp(board, evals) } if (*showResult) { dump(board, evals, fmt.Sprintf("Not a single fuck (%d iterations)", iterations)) } else { emitSummary(evals, iterations) } } func emitSummary(evals [][]fuckness, iterations uint64) { nFucked := uint64(0) for _, row := range evals { for _, e := range row { if isFucked(e) { nFucked++ } } } fmt.Printf("Iteration %d: %d fucked (%.2f%%)\n", iterations, nFucked, 100 * float64(nFucked)/(float64(*edgeSize * *edgeSize))) } func onBoard(i, j int) bool { return i >= 0 && j >= 0 && i < *edgeSize && j < *edgeSize } func charAt(board [][]byte, i, j int) byte { if !onBoard(i, j) { return 5 } return board[i][j] } func isStillFucked(board [][]byte, evals[][]fuckness) bool { isFucked := false for i, row := range board { for j, c := range row { for dr := -1; dr <= 1; dr++ { for dc := -1; dc <= 1; dc++ { if dr == 0 && dc == 0 { continue } if evals[i][j][dr+1][dc+1] == Fucked { isFucked = true continue } if evals[i][j][dr+1][dc+1] != FuckIfIKnow { continue } // find theoretical start of fuck fRow, fCol := i + int(c)*-dr, j + int(c)*-dc // evaluate fuckness locallyFucked := true for w := 0; w < 4; w++ { if charAt(board, fRow+w*dr, fCol+w*dc) != byte(w) { locallyFucked = false break } } if locallyFucked { // mark every letter involved as fucked isFucked = true for w := 0; w < 4; w++ { evals[fRow+w*dr][fCol+w*dc][dr+1][dc+1] = Fucked } } else { evals[i][j][dr+1][dc+1] = NotFucked } } } } } return isFucked } func isFucked(f fuckness) bool { for i := 0; i <3; i++ { for j := 0; j < 3; j++ { if i == 1 && j == 1 { continue } if f[i][j] == Fucked { return true } } } return false } func mightBeFucked(f fuckness) bool { for i := 0; i <3; i++ { for j := 0; j < 3; j++ { if i == 1 && j == 1 { continue } if f[i][j] != NotFucked { return true } } } return false } func fuckUp(board [][]byte, evals [][]fuckness) { var todo [][2]int for i, row := range evals { for j, e := range row { if isFucked(e) { todo = append(todo, [2]int{i, j}) } else if mightBeFucked(e) { dump(board, evals, "Oh fuck") log.Fatalf("unevaluated fuckness at %d, %d: %v", i, j, e) } } } rand.Shuffle(len(todo), func(i, j int) { todo[j], todo[i] = todo[i], todo[j] }) // note: "head" moves frequently within this loop for head := 0; head < len(todo); head++ { item := todo[head] i, j := item[0], item[1] if(!isFucked(evals[i][j])) { continue } i2, j2 := -1, -1 for head++; head < len(todo); head++ { item2 := todo[head] itmp, jtmp := item2[0], item2[1] if(isFucked(evals[itmp][jtmp])) { i2, j2 = itmp, jtmp break } } if i2 == -1 { // fuck it, swap randomly i2 = rand.Intn(*edgeSize) j2 = rand.Intn(*edgeSize) } if board[i][j] != board[i2][j2] { unevaluate(evals, i, j) unevaluate(evals, i2, j2) board[i][j], board[i2][j2] = board[i2][j2], board[i][j] } } } func unevaluate(evals [][]fuckness, i, j int) { for dr := -1; dr <= 1; dr++ { for dc := -1; dc <= 1; dc++ { for x := -3; x < 4; x++ { r := i + dr * x c := j + dc * x if onBoard(r, c) { evals[r][c][dr+1][dc+1] = FuckIfIKnow } } } } } func dump(board [][]byte, evals [][]fuckness, title string) { fmt.Println() for i := 0; i < *edgeSize; i++ { fmt.Print("--") } fmt.Println() fmt.Println(title) fmt.Println() for i, row := range board { for j, r := range row { if isFucked(evals[i][j]) { fmt.Printf("%c ", "FUCK"[r]) } else { fmt.Printf("%c ", "fuck"[r]) } } fmt.Println() } }