Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- What evidence would you like to see? Given the test has concluded with a perfect result I doubt it'll be especially useful in the future. They don't have a native share, so here's my prompt and the python code it output. (Seriously, why would someone lie about this stuff? I've been posting about the same test for multiple models. I got nothing to prove here, I test them all equally and switch between them based on what's working best. I do most stuff in Claude Code).
- (I'm bad with reddit posting so you're getting a mess of text below)
- Prompt:
- I would like you to write some python code for me. The project is a scrabble board validator.
- A scrabble board, in text, looks like:
- ...............
- ...............
- ...............
- ...............
- ...............
- ...............
- .ZYMURGY.......
- .......E.......
- .......L.......
- .......L.......
- .......O.......
- .......WIND....
- .........A.....
- .........N.....
- ...............
- The .'s represent empty squares.
- The rules for verifying if a scrabble board is valid include:
- * The center tile (7,7) must contain a letter.
- * All non-empty spaces must form a single connected group that includes the center tile.
- * This means you can't have a disconnected word somewhere else on the board, everything has to connect to the center!
- * There must be at least two different letters on the board.
- * All words formed must be at least 2 letters long.
- * Words can only be vertical or horizontal, no diagonals.
- For the purpose of validating the scrabble board, you can ignore if the words themselves are valid (beyond having 2 letters).
- I'd like you to write several different bits of python.
- 1. The validator
- The validator is a library that contains all the logic to validate the board. It should be capable of taking a board (I recommend a list of 15 strings, each 15 characters long, but feel free to use another data structure) and validating it against the rules above.
- There should be an interface that allows me to check if a board is valid (returning True it so, or False if not) as well as an interface to fetch all words discovered on a valid board.
- 2. Tests
- The validator needs to be tested, and I would like to do this in pytest. Specifically, I would like you to write property tests with hypothesis. These should be actual useful tests, one for each of the properties where possible.
- An example of a property test I'd like to see is randomly generated boards that then verify that every valid board has at least 1 word in the words list.
- Rather than generate boards blindly with random characters, it would be nice if the property generator could create a number of words (from 1-whatever) and then place them on the board at random before testing.
- 3. A CLI utility to test files
- Lastly, I would like a CLI utility that can take a boards.txt file (with multiple boards separated by a blank line) and then validate them.
- Please invest extra effort on the property tests. There should be a mixture of static unit tests for obvious failure cases, and then some property tests that can generate valid (and invalid) boards to test many variations. Previous AI attempts to solve this have generated broken tests, even unit tests that have words that are clearly not in the board generated right above.
- Also please think hard about all the logical cases to test. I want exhaustive property tests, so make sure words have at least 2 different characters, there's a number of words on a board, and so on. We should be able to generate simple boards as well as quite complex boards, with multiple words.
- As you write the code, I'd like for you to execute the tests and fix any issues you discover until all tests are passing.
- Output (minus the words around it, just the code here):
- # scrabble_validator.py
- from collections import deque
- class ScrabbleValidator:
- def __init__(self, board):
- self.board = board
- self.rows = len(board)
- self.cols = len(board[0]) if self.rows > 0 else 0
- self.directions = [(0, 1), (1, 0), (0, -1), (-1, 0)]
- def is_valid(self):
- # Rule 1: Center tile must be non-empty
- if self.rows < 8 or self.cols < 8 or self.board[7][7] == '.':
- return False
- # Rule 2: At least two distinct letters
- letters = set()
- for row in self.board:
- for char in row:
- if char != '.':
- letters.add(char)
- if len(letters) < 2:
- return False
- # Rule 3: All non-empty tiles form a single connected group including center
- if not self._is_connected():
- return False
- # Rule 4: All words are at least 2 letters (handled during extraction)
- return True
- def _is_connected(self):
- visited = [[False for _ in range(self.cols)] for _ in range(self.rows)]
- queue = deque()
- total_non_empty = 0
- # Start BFS from center (7,7)
- if self.board[7][7] != '.':
- queue.append((7, 7))
- visited[7][7] = True
- total_non_empty += 1
- else:
- return False
- count = 0
- while queue:
- x, y = queue.popleft()
- count += 1
- for dx, dy in self.directions:
- nx, ny = x + dx, y + dy
- if 0 <= nx < self.rows and 0 <= ny < self.cols:
- if not visited[nx][ny] and self.board[nx][ny] != '.':
- visited[nx][ny] = True
- queue.append((nx, ny))
- total_non_empty += 1
- # Count all non-empty tiles
- actual_non_empty = sum(1 for i in range(self.rows) for j in range(self.cols)
- if self.board[i][j] != '.')
- return count == actual_non_empty
- def get_words(self):
- words = []
- # Horizontal words
- for i in range(self.rows):
- j = 0
- while j < self.cols:
- if self.board[i][j] != '.':
- start = j
- while j < self.cols and self.board[i][j] != '.':
- j += 1
- segment = ''.join(self.board[i][start:j])
- if len(segment) >= 2:
- words.append(segment)
- else:
- j += 1
- # Vertical words
- for j in range(self.cols):
- i = 0
- while i < self.rows:
- if self.board[i][j] != '.':
- start = i
- while i < self.rows and self.board[i][j] != '.':
- i += 1
- segment = ''.join(self.board[k][j] for k in range(start, i))
- if len(segment) >= 2:
- words.append(segment)
- else:
- i += 1
- return words
- if __name__ == "__main__":
- import sys
- if len(sys.argv) != 2:
- print("Usage: python scrabble_validator.py <input_file>")
- sys.exit(1)
- filename = sys.argv[1]
- try:
- with open(filename, 'r') as f:
- content = f.read().strip()
- boards = []
- current_board = []
- for line in content.splitlines():
- if line.strip() == '':
- if current_board:
- boards.append(current_board)
- current_board = []
- else:
- current_board.append(line.strip())
- if current_board:
- boards.append(current_board)
- for idx, board in enumerate(boards):
- if len(board) != 15 or any(len(row) != 15 for row in board):
- print(f"Board {idx+1}: Invalid dimensions (must be 15x15)")
- continue
- validator = ScrabbleValidator(board)
- if validator.is_valid():
- words = validator.get_words()
- print(f"Board {idx+1}: valid. Words: {', '.join(words)}")
- else:
- print(f"Board {idx+1}: invalid")
- except Exception as e:
- print(f"Error: {e}")
- sys.exit(1)
- Test:
- ```
- # test_scrabble_validator.py
- import pytest
- from scrabble_validator import ScrabbleValidator
- from hypothesis import given, assume, strategies as st
- import random
- # Unit tests for obvious cases
- def test_empty_board():
- board = ['.' * 15 for _ in range(15)]
- validator = ScrabbleValidator(board)
- assert not validator.is_valid()
- def test_missing_center():
- board = ['.' * 15 for _ in range(15)]
- validator = ScrabbleValidator(board)
- assert not validator.is_valid()
- def test_single_letter():
- board = ['.' * 15 for _ in range(15)]
- board[7] = '.' * 7 + 'A' + '.' * 7
- validator = ScrabbleValidator(board)
- assert not validator.is_valid()
- def test_disconnected_board():
- board = ['.' * 15 for _ in range(15)]
- # Center word
- board[7] = '.' * 7 + 'AB' + '.' * 6
- # Disconnected word
- board[0] = 'XY' + '.' * 13
- validator = ScrabbleValidator(board)
- assert not validator.is_valid()
- def test_valid_board():
- board = ['.' * 15 for _ in range(15)]
- board[7] = '.' * 7 + 'HELLO' + '.' * 3
- validator = ScrabbleValidator(board)
- assert validator.is_valid()
- words = validator.get_words()
- assert 'HELLO' in words
- def test_word_extraction():
- board = ['.' * 15 for _ in range(15)]
- board[6] = '.' * 7 + 'WORLD' + '.' * 3
- board[7] = '.' * 7 + 'E' + '.' * 7
- board[8] = '.' * 7 + 'A' + '.' * 7
- board[9] = '.' * 7 + 'R' + '.' * 7
- validator = ScrabbleValidator(board)
- words = validator.get_words()
- assert 'WORLD' in words
- assert 'WEAR' in words # Vertical word
- # Hypothesis strategies
- @st.composite
- def valid_board_strategy(draw):
- board = [['.'] * 15 for _ in range(15)]
- # Place center tile
- center_char = draw(st.sampled_from('ABCDEFGHIJKLMNOPQRSTUVWXYZ'))
- board[7][7] = center_char
- # Generate connected tiles
- positions = set([(7, 7)])
- num_tiles = draw(st.integers(min_value=1, max_value=50))
- directions = [(0, 1), (1, 0), (0, -1), (-1, 0)]
- for _ in range(num_tiles):
- candidates = set()
- for (x, y) in positions:
- for dx, dy in directions:
- nx, ny = x + dx, y + dy
- if 0 <= nx < 15 and 0 <= ny < 15 and (nx, ny) not in positions:
- candidates.add((nx, ny))
- if not candidates:
- break
- new_pos = draw(st.sampled_from(list(candidates)))
- positions.add(new_pos)
- # Assign letters ensuring at least two distinct
- distinct_letter = draw(st.sampled_from([c for c in 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' if c != center_char]))
- change_pos = draw(st.sampled_from(list(positions - {(7, 7)})))
- for x, y in positions:
- if (x, y) == change_pos:
- board[x][y] = distinct_letter
- else:
- board[x][y] = center_char
- return [''.join(row) for row in board]
- @st.composite
- def invalid_center_strategy(draw):
- board = draw(valid_board_strategy())
- board_list = [list(row) for row in board]
- board_list[7][7] = '.'
- return [''.join(row) for row in board_list]
- @st.composite
- def single_letter_strategy(draw):
- board = draw(valid_board_strategy())
- letter = draw(st.sampled_from('ABCDEFGHIJKLMNOPQRSTUVWXYZ'))
- board_list = [list(row) for row in board]
- for i in range(15):
- for j in range(15):
- if board_list[i][j] != '.':
- board_list[i][j] = letter
- return [''.join(row) for row in board_list]
- @st.composite
- def disconnected_strategy(draw):
- board = draw(valid_board_strategy())
- board_list = [list(row) for row in board]
- # Find an empty position not adjacent to any non-empty tile
- candidates = []
- for i in range(15):
- for j in range(15):
- if board_list[i][j] == '.':
- adjacent = False
- for di, dj in [(0, 1), (1, 0), (0, -1), (-1, 0)]:
- ni, nj = i + di, j + dj
- if 0 <= ni < 15 and 0 <= nj < 15 and board_list[ni][nj] != '.':
- adjacent = True
- break
- if not adjacent:
- candidates.append((i, j))
- if candidates:
- i, j = draw(st.sampled_from(candidates))
- board_list[i][j] = draw(st.sampled_from('ABCDEFGHIJKLMNOPQRSTUVWXYZ'))
- return [''.join(row) for row in board_list]
- return board # Fallback to valid board if no candidate found
- # Property-based tests
- @given(valid_board_strategy())
- def test_valid_boards(board):
- validator = ScrabbleValidator(board)
- assert validator.is_valid()
- @given(valid_board_strategy())
- def test_words_non_empty(board):
- validator = ScrabbleValidator(board)
- words = validator.get_words()
- assert len(words) >= 1
- for word in words:
- assert len(word) >= 2
- @given(invalid_center_strategy())
- def test_invalid_center(board):
- validator = ScrabbleValidator(board)
- assert not validator.is_valid()
- @given(single_letter_strategy())
- def test_single_letter(board):
- validator = ScrabbleValidator(board)
- assert not validator.is_valid()
- @given(disconnected_strategy())
- def test_disconnected_board(board):
- validator = ScrabbleValidator(board)
- assert not validator.is_valid()
- # Run tests
- if __name__ == "__main__":
- pytest.main()
- ```
- We went on to discuss how to add more hypothesis runs, which it did first time too. Is that enough for you?
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement