Wordiff: Difference between revisions
Content added Content deleted
m (fix some typos) |
|||
Line 31: | Line 31: | ||
:* That last player must have entered a wordiff or loses. |
:* That last player must have entered a wordiff or loses. |
||
:* If the game is timed-out, the loser is the person who took the longest `average` time to answer in their rounds. |
:* If the game is timed-out, the loser is the person who took the longest `average` time to answer in their rounds. |
||
=={{header|Nim}}== |
|||
{{trans|Python}} |
|||
<lang Nim>import httpclient, sequtils, sets, strutils, sugar |
|||
from unicode import capitalize |
|||
const |
|||
DictFname = "unixdict.txt" |
|||
DictUrl1 = "http://wiki.puzzlers.org/pub/wordlists/unixdict.txt" # ~25K words |
|||
DictUrl2 = "https://raw.githubusercontent.com/dwyl/english-words/master/words.txt" # ~470K words |
|||
type Dictionary = HashSet[string] |
|||
proc loadDictionary(fname = DictFname): Dictionary = |
|||
## Return appropriate words from a dictionary file. |
|||
for word in fname.lines(): |
|||
if word.len >= 3 and word.allCharsInSet(Letters): result.incl word.toLowerAscii |
|||
proc loadWebDictionary(url: string): Dictionary = |
|||
## Return appropriate words from a dictionary web page. |
|||
let client = newHttpClient() |
|||
for word in client.getContent(url).splitLines(): |
|||
if word.len >= 3 and word.allCharsInSet(Letters): result.incl word.toLowerAscii |
|||
proc getPlayers(): seq[string] = |
|||
## Return inputted ordered list of contestant names. |
|||
try: |
|||
stdout.write "Space separated list of contestants: " |
|||
stdout.flushFile() |
|||
result = stdin.readLine().splitWhitespace().map(capitalize) |
|||
if result.len == 0: |
|||
quit "Empty list of names. Quitting.", QuitFailure |
|||
except EOFError: |
|||
echo() |
|||
quit "Encountered end of file. Quitting.", QuitFailure |
|||
proc isWordiffRemoval(word, prev: string; comment = true): bool = |
|||
## Is "word" derived from "prev" by removing one letter? |
|||
for i in 0..prev.high: |
|||
if word == prev[0..<i] & prev[i+1..^1]: return true |
|||
if comment: echo "Word is not derived from previous by removal of one letter." |
|||
result = false |
|||
proc isWordiffInsertion(word, prev: string; comment = true): bool = |
|||
## Is "word" derived from "prev" by adding one letter? |
|||
for i in 0..word.high: |
|||
if prev == word[0..<i] & word[i+1..^1]: return true |
|||
if comment: echo "Word is not derived from previous by insertion of one letter." |
|||
return false |
|||
proc isWordiffChange(word, prev: string; comment = true): bool = |
|||
## Is "word" derived from "prev" by changing exactly one letter? |
|||
var diffcount = 0 |
|||
for i in 0..word.high: |
|||
diffcount += ord(word[i] != prev[i]) |
|||
if diffcount != 1: |
|||
if comment: |
|||
echo "More or less than exactly one character changed." |
|||
return false |
|||
result = true |
|||
proc isWordiff(word: string; wordiffs: seq[string]; dict: Dictionary; comment = true): bool = |
|||
## Is "word" a valid wordiff from "wordiffs[^1]"? |
|||
if word notin dict: |
|||
if comment: |
|||
echo "That word is not in my dictionary." |
|||
return false |
|||
if word in wordiffs: |
|||
if comment: |
|||
echo "That word was already used." |
|||
return false |
|||
result = if word.len < wordiffs[^1].len: word.isWordiffRemoval(wordiffs[^1], comment) |
|||
elif word.len > wordiffs[^1].len: word.isWordiffInsertion(wordiffs[^1], comment) |
|||
else: word.isWordiffChange(wordiffs[^1], comment) |
|||
proc couldHaveGot(wordiffs: seq[string]; dict: Dictionary): seq[string] = |
|||
for word in dict - wordiffs.toHashSet: |
|||
if word.isWordiff(wordiffs, dict, comment = false): |
|||
result.add word |
|||
when isMainModule: |
|||
import random |
|||
randomize() |
|||
let dict = loadDictionary(DictFname) |
|||
let dict34 = collect(newSeq): |
|||
for word in dict: |
|||
if word.len in [3, 4]: word |
|||
let start = sample(dict34) |
|||
var wordiffs = @[start] |
|||
let players = getPlayers() |
|||
var iplayer = 0 |
|||
var word: string |
|||
while true: |
|||
let name = players[iplayer] |
|||
while true: |
|||
stdout.write "$1, input a wordiff from “$2”: ".format(name, wordiffs[^1]) |
|||
stdout.flushFile() |
|||
try: |
|||
word = stdin.readLine().strip() |
|||
if word.len > 0: break |
|||
except EOFError: |
|||
quit "Encountered end of file. Quitting.", QuitFailure |
|||
if word.isWordiff(wordiffs, dict): |
|||
wordiffs.add word |
|||
else: |
|||
echo "You have lost, $#.".format(name) |
|||
let possibleWords = couldHaveGot(wordiffs, dict) |
|||
if possibleWords.len > 0: |
|||
echo "You could have used: ", possibleWords[0..min(possibleWords.high, 20)].join(" ") |
|||
break |
|||
iplayer = (iplayer + 1) mod players.len</lang> |
|||
{{out}} |
|||
<pre>Space separated list of contestants: Paddy Maggie |
|||
Paddy, input a wordiff from “beta”: bet |
|||
Maggie, input a wordiff from “bet”: bee |
|||
Paddy, input a wordiff from “bee”: tee |
|||
Maggie, input a wordiff from “tee”: teen |
|||
Paddy, input a wordiff from “teen”: teeny |
|||
That word is not in my dictionary. |
|||
You have lost, Paddy. |
|||
You could have used: then steen tern keen teem teet been seen ten</pre> |
|||
=={{header|Python}}== |
=={{header|Python}}== |