Data commit

This commit is contained in:
Ingy döt Net 2023-07-01 11:58:00 -04:00
parent 7387c8f97b
commit cb5bb5e222
199093 changed files with 3378972 additions and 0 deletions

View file

@ -0,0 +1,3 @@
---
from: http://rosettacode.org/wiki/Wordiff
note: Games

39
Task/Wordiff/00-TASK.txt Normal file
View file

@ -0,0 +1,39 @@
Wordiff is an original game in which contestants take turns spelling new dictionary words of three or more characters that only differ from
the last by a change in one letter.
The change can be either:
# a deletion of one letter;
# addition of one letter;
# or change in one letter.
Note:
* All words must be in the dictionary.
* No word in a game can be repeated.
* The first word must be three or four letters long.
;Task:
Create a program to aid in the playing of the game by:
* Asking for contestants names.
* Choosing an initial random three or four letter word from the dictionary.
* Asking each contestant in their turn for a wordiff word.
* Checking the wordiff word is:
:* in the dictionary,
:* not a repetition of past words,
:* and differs from the last appropriately.
;Optional stretch goals:
* Add timing.
* Allow players to set a maximum playing time for the game.
* An internal timer accumulates how long each user takes to respond in their turns.
* Play is halted if the maximum playing time is exceeded on a players input.
:* 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.
{{Template:Strings}}
<br><br>

View file

@ -0,0 +1,89 @@
V dict_fname = unixdict.txt
F load_dictionary(String fname = dict_fname)
Return appropriate words from a dictionary file
R Set(File(fname).read().split("\n").filter(word -> re:[a-z]{3,}.match(word)))
F get_players()
V names = input(Space separated list of contestants: )
R names.trim( ).split( , group_delimiters' 1B).map(n -> n.capitalize())
F is_wordiff_removal(word, String prev; comment = 1B)
Is word derived from prev by removing one letter?
V ans = word C Set((0 .< prev.len).map(i -> @prev[0 .< i]@prev[i + 1 ..]))
I !ans
I comment
print(Word is not derived from previous by removal of one letter.)
R ans
F counter(s)
DefaultDict[Char, Int] d
L(c) s
d[c]++
R d
F is_wordiff_insertion(String word, prev; comment = 1B) -> Bool
Is word derived from prev by adding one letter?
V diff = counter(word)
L(c) prev
I --diff[c] <= 0
diff.pop(c)
V diffcount = sum(diff.values())
I diffcount != 1
I comment
print(More than one character insertion difference.)
R 0B
V insert = Array(diff.keys())[0]
V ans = word C Set((0 .. prev.len).map(i -> @prev[0 .< i]@insert@prev[i ..]))
I !ans
I comment
print(Word is not derived from previous by insertion of one letter.)
R ans
F is_wordiff_change(String word, String prev; comment = 1B) -> Bool
Is word derived from prev by changing exactly one letter?
V diffcount = sum(zip(word, prev).map((w, p) -> Int(w != p)))
I diffcount != 1
I comment
print(More or less than exactly one character changed.)
R 0B
R 1B
F is_wordiff(wordiffs, word, dic, comment = 1B)
Is word a valid wordiff from wordiffs[-1] ?
I word !C dic
I comment
print(That word is not in my dictionary)
R 0B
I word C wordiffs
I comment
print(That word was already used.)
R 0B
I word.len < wordiffs.last.len
R is_wordiff_removal(word, wordiffs.last, comment)
E I word.len > wordiffs.last.len
R is_wordiff_insertion(word, wordiffs.last, comment)
R is_wordiff_change(word, wordiffs.last, comment)
F could_have_got(wordiffs, dic)
R (dic - Set(wordiffs)).filter(word -> is_wordiff(@wordiffs, word, @dic, comment' 0B))
V dic = load_dictionary()
V dic_3_4 = dic.filter(word -> word.len C (3, 4))
V start = random:choice(dic_3_4)
V wordiffs = [start]
V players = get_players()
V cur_player = 0
L
V name = players[cur_player]
cur_player = (cur_player + 1) % players.len
V word = input(name: Input a wordiff from 'wordiffs.last': ).trim( )
I is_wordiff(wordiffs, word, dic)
wordiffs.append(word)
E
print(YOU HAVE LOST name!)
print(Could have used: (could_have_got(wordiffs, dic)[0.<10]).join(, ) ...)
L.break

View file

@ -0,0 +1,35 @@
wordset: map read.lines relative "unixdict.txt" => strip
validAnswer?: function [answer][
if not? contains? wordset answer [
prints "\tNot a valid dictionary word."
return false
]
if contains? pastWords answer [
prints "\tWord already used."
return false
]
if 1 <> levenshtein answer last pastWords [
prints "\tNot a correct wordiff."
return false
]
return true
]
playerA: input "player A: what is your name? "
playerB: input "player B: what is your name? "
pastWords: new @[sample select wordset 'word [ contains? [3 4] size word ]]
print ["\nThe initial word is:" last pastWords "\n"]
current: playerA
while ø [
neww: strip input ~"|current|, what is the next word? "
while [not? validAnswer? neww][
neww: strip input " Try again: "
]
'pastWords ++ neww
current: (current=playerA)? -> playerB -> playerA
print ""
]

View file

@ -0,0 +1,265 @@
output file "Wordiff" ' 27 november 2022 '
begin enum 1
_playerLabel : _playerInput : _wordLabel : _wordInPlay : _playsLabel
_scrlView : _textView
_resignBtn : _againBtn : _quitBtn
end enum
begin globals
CFMutableArrayRef gWords, gNames, gUsed
gWords = fn MutableArrayWithCapacity( 0 )
gNames = fn MutableArrayWithCapacity( 0 )
gUsed = fn MutableArrayWithCapacity( 0 )
CFMutableStringRef gTxt
gTxt = fn MutableStringWithCapacity( 0 )
end globals
void local fn BuildInterface
window 1, @"Wordiff", ( 0, 0, 400, 450 ), NSWindowStyleMaskTitled + NSWindowStyleMaskClosable
// Fields for labels and input
textlabel _playerLabel, @"The players:", ( 0, 370, 148, 24 )
textlabel _wordLabel, @"Word in play:", ( 68, 409, 100, 24 )
textlabel _playsLabel, , ( 113, 370, 150, 24 )
textfield _playerInput, Yes, , ( 160, 372, 150, 24 )
textfield _wordInPlay, No, @". . .", ( 160, 412, 148, 24 )
ControlSetAlignment( _playerLabel, NSTextAlignmentRight )
ControlSetAlignment( _playerInput, NSTextAlignmentCenter )
ControlSetAlignment( _wordInPlay, NSTextAlignmentCenter )
ControlSetFormat( _playerInput, @"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", YES, 8, _formatCapitalize )
TextFieldSetTextColor( _wordLabel, fn ColorLightGray )
TextFieldSetTextColor( _wordInPlay, fn ColorLightGray )
TextFieldSetSelectable( _wordInPlay, No )
// Fields for computer feedback
scrollview _scrlView, ( 20, 60, 356, 300 ), NSBezelBorder
textview _textView, , _scrlView, , 1
ScrollViewSetHasVerticalScroller( _scrlView, YES )
TextViewSetTextContainerInset( _textView, fn CGSizeMake( 3, 3 ) )
TextSetFontWithName( _textView, @"Menlo", 12 )
TextSetColor( _textView, fn colorLightGray )
TextSetString( _textView, @"First, enter the name of each player and press Return to confirm. ¬
When done, press Return to start the game." )
// Buttons and menus
button _resignBtn, No, , @"Resign", ( 251, 15, 130, 32 )
button _againBtn, No, , @"New game", ( 114, 15, 130, 32 )
button _quitBtn, Yes, , @"Quit", ( 15, 15, 92, 32 )
filemenu 1 : menu 1, , No ' Nothing to file
editmenu 2 : menu 2, , No ' Nothing to edit
WindowMakeFirstResponder( 1, _playerInput ) ' Activate player input field
end fn
void local fn LoadWords
CFURLRef url
CFStringRef words, string
CFArrayRef tmp
CFRange range
// Fill the gWords list with just the lowercase words in unixdict
url = fn URLWithString( @"http://wiki.puzzlers.org/pub/wordlists/unixdict.txt" )
words = fn StringWithContentsOfURL( url, NSUTF8StringEncoding, NULL )
tmp = fn StringComponentsSeparatedByCharactersInSet( ( words ), fn CharacterSetNewlineSet )
for string in tmp
range = fn StringRangeOfStringWithOptions( string, @"^[a-z]+$", NSRegularExpressionSearch )
if range.location != NSNotFound then MutableArrayAddObject( gWords, string )
next
end fn
void local fn Say(str1 as CFStringRef, str2 as CFStringRef )
// Add strings to the computer feedback
fn MutableStringAppendString( gTxt, str1 )
fn MutableStringAppendString( gTxt, str2 )
TextSetString( _textView, gTxt )
TextScrollRangeToVisible( _textView, fn CFRangeMake( len( fn TextString( _textView ) ), 0) )
end fn
local fn CompareEqual( wrd1 as CFStringRef, wrd2 as CFStringRef ) as short
NSInteger i, k
CFStringRef a, b
//Find the number of differences in two strings
k = 0
for i = 0 to len( wrd1 ) - 1
a = mid( wrd1, i, 1 ) : b = mid( wrd2, i, 1 )
if fn StringIsEqual( a, b ) == No then k++
next
end fn = k
local fn ChopAndStitch( sShort as CFStringRef, sLong as CFStringRef ) as CFStringRef
NSInteger i, k
CFStringRef a, b
// Find the extra letter in the long string and remove it
k = 0
for i = 0 to len( sLong ) - 1
a = mid( sShort, i, 1 ) : b = mid( sLong, i, 1 )
if fn StringIsEqual( a, b ) == No then k = i : break ' Found it
next
a = left( sLong, k ) : b = mid( sLong, k + 1 ) 'Removed it
end fn = fn StringByAppendingString( a, b )
local fn WordiffWords( wrd1 as CFStringRef, wrd2 as CFStringRef ) as short
Short err = 0
// If a letter was added or removed, the strings should be identical after
// we remove the extra letter from the longest string.
// If they are the same length, the strings may differ at just one place.
select case
case len( wrd2 ) > len( wrd1 )
wrd2 = fn ChopAndStitch( wrd1, wrd2 )
if fn CompareEqual( wrd1, wrd2 ) != 0 then err = 1 ' Words identical?
case len( wrd1 ) > len( wrd2 )
wrd1 = fn ChopAndStitch( wrd2, wrd1 )
if fn CompareEqual( wrd1, wrd2 ) != 0 then err = 2
case len( wrd2 ) = len( wrd1 )
if fn CompareEqual( wrd1, wrd2 ) != 1 then err = 3 ' Only one change?
end select
end fn = err
local fn CheckWord( wrd1 as CFStringRef, wrd2 as CFStringRef ) as short
Short err = 0
// Preliminary tests to generate error codes
select case
case fn StringIsEqual( wrd1, wrd2 ) : err = 1
case len( wrd2 ) < 3 : err = 2
case len( wrd2 ) - len( wrd1 ) > 1 : err = 3
case len( wrd1 ) - len( wrd2 ) > 1 : err = 4
case fn ArrayContainsObject( gUsed, wrd2 ) == Yes : err = 5
case fn ArrayContainsObject( gWords, wrd2 ) == No : err = 6
end select
// Report error. If no error, check against Wordiff rules
select err
case 1 : fn Say( @"Don't be silly.", @"\n" )
case 2 : fn Say( @"New word must be three or more letters.", @"\n" )
case 3 : fn Say( @"Add just one letter, please.", @"\n" )
case 4 : fn Say( @"Delete just one letter, please.", @"\n" )
case 5 : fn Say( fn StringCapitalizedString( wrd2 ), @" was already used.\n" )
case 6 : fn Say( fn StringCapitalizedString( wrd2 ), @" is not in the dictionary.\n")
case 0
err = fn WordiffWords ( wrd1, wrd2 )
select err
case 1 : fn Say( @"Either change or add a letter.", @"\n" )
case 2 : fn Say( @"Either change or delete a letter.", @"\n" )
case 3 : fn Say( @"Don't change more than one letter.", @"\n")
end select
end select
end fn = err
void local fn ShowAllPossible
CFMutableArrayRef poss
CFStringRef wrd1, wrd2
NSUInteger i
// Check all words in dictionary, ignore error messages
poss = fn MutableArrayWithCapacity( 0 )
wrd1 = fn ControlStringValue( _wordInPlay )
for i = 0 to fn ArrayCount( gWords ) - 1
wrd2 = fn ArrayObjectAtIndex( gWords, i )
if fn fabs( len( wrd1 ) - len( wrd2 ) ) < 2 ' Not too long or short?
if len( wrd2 ) > 2 ' Has more than 2 chars?
if fn ArrayContainsObject( gUsed, wrd2 ) == No ' Not used before?
if ( fn WordiffWords( wrd1, wrd2 ) == 0 ) ' According to rules?
MutableArrayAddObject( poss, wrd2 ) ' Legal, so add to the pot
end if
end if
end if
end if
next
// Display legal words
fn Say( @"\n", fn ControlStringValue( _playerLabel ) )
if fn ArrayCount( poss ) > 0 ' Any words left?
fn Say( @" resigns, but could have chosen:", @"\n" )
fn MutableStringAppendString( gTxt, fn ArrayComponentsJoinedByString( poss, @", or " ) )
TextSetString( _textView, gTxt )
else
fn Say(@" resigns, there were no words left to play. ", @"New game?\n" )
end if
textfield _playerInput, No ' Just to be safe
end fn
void local fn Play
CFStringRef old, new, name
NSUInteger n
// Gather the info
name = fn ControlStringValue( _playerLabel )
new = fn ControlStringValue( _playerInput )
old = fn ArrayLastObject( gUsed )
if len( new ) == 0 then exit fn ' Just to be safe
fn Say(new, @"\n" )
if fn CheckWord( old, new ) == 0
// Input OK, so get ready next player
n = ( ( fn ArrayIndexOfObject( gNames, name ) + 1 ) mod fn ArrayCount( gNames ) )
name = fn ArrayObjectAtIndex( gNames, n )
textlabel _playerLabel, name
textfield _wordInPlay, , new
MutableArrayAddObject( gUsed, new )
end if
fn Say( name, @" plays: " )
textfield _playerInput, , @""
end fn
void local fn StartNewGame
CFStringRef name, wrd
NSUInteger n
// Pick a first player
n = rnd( fn ArrayCount( gNames ) )
name = fn ArrayObjectAtIndex( gNames, n - 1 )
// Pick a first word
MutableArrayRemoveAllObjects( gUsed )
do
n = rnd( fn ArrayCount( gWords ) ) - 1
wrd = fn ArrayObjectAtIndex( gWords, n )
until ( len( wrd ) = 3 ) or ( len( wrd ) = 4 )
MutableArrayAddObject( gUsed, wrd )
// Update window
ControlSetFormat( _playerInput, @"abcdefghijklmnopqrstuvwxyz", YES, 0, _formatLowercase )
fn Say( @"\n", @"Word in play: " ) : fn Say( wrd, @"\n" )
fn Say( name, @" plays: " )
textfield _wordInPlay, Yes, wrd
textlabel _playerLabel, name, (0, 370, 110, 24 )
textlabel _playsLabel, @"plays:"
textfield _playerInput, Yes
button _againBtn, Yes
button _resignBtn, Yes
WindowMakeFirstResponder( 1, _playerInput )
end fn
void local fn AskNames
CFStringRef name
name = fn ControlStringValue( _playerInput )
if len( name ) > 0 ' Another player?
MutableArrayAddObject( gNames, name )
fn Say( @"Welcome, ", name )
fn Say( @"!", @"\n" )
textfield _playerInput, YES, @""
else
if fn ArrayFirstObject( gNames ) != Null ' Just to be safe
fn StartNewGame
end if
end if
end fn
void local fn DoDialog( evt as Long, tag as Long )
select evt
case _btnClick
select tag
case _againBtn
fn MutableStringSetString( gTxt, @"" )
fn StartNewGame
case _resignBtn
button _resignBtn, No
fn ShowAllPossible
case _quitBtn : end
end select
case _textFieldDidEndEditing
if fn ArrayCount( gUsed ) == 0
fn AskNames
else
fn Play
end if
case _windowShouldClose : end
end select
end fn
on dialog fn DoDialog
fn BuildInterface
fn LoadWords
handleevents

View file

@ -0,0 +1,36 @@
require'general/misc/prompt'
wordiff=: {{
words=: cutLF tolower fread'unixdict.txt'
c1=: prompt 'Name of contestant 1: '
c2=: prompt 'Name of contestant 2: '
hist=. ,word=. ({~ ?@#) (#~ 3 4 e.~ #@>) words
echo 'First word is ',toupper;word
echo 'each contestant must pick a new word'
echo 'the new word must either change 1 letter or remove or add 1 letter'
echo 'the new word cannot be an old word'
while. do.
next=. <tolower prompt 'Pick a new word ',c1,': '
if. next e. hist do.
echo next,&;' has already been picked'
break.
end.
if. -. next e. words do.
echo next,&;' is not in the dictionary'
break.
end.
if. next =&#&> word do.
if. 1~:+/d=.next~:&;word do.
echo next,&;' differs from ',word,&;' by ',(":d),' characters'
break.
end.
else.
if. -. */1=(-&#&>/,[:+/=/&>/)(\:#@>) next,word do.
echo next,&;' differs too much from ',;word
break.
end.
end.
hist=. hist,word=. next
'c2 c1'=. c1;c2
end.
echo c2,' wins'
}}

View file

@ -0,0 +1,15 @@
wordiff''
Name of contestant 1: Jack
Name of contestant 2: Jill
First word is FLAX
each contestant must pick a new word
the new word must either change 1 letter or remove or add 1 letter
the new word cannot be an old word
Pick a new word Jack: flak
Pick a new word Jill: flap
Pick a new word Jack: clap
Pick a new word Jill: slap
Pick a new word Jack: slam
Pick a new word Jill: slap
slap has already been picked
Jack wins

View file

@ -0,0 +1,51 @@
isoneless(nw, ow) = any(i -> nw == ow[begin:i-1] * ow[i+1:end], eachindex(ow))
isonemore(nw, ow) = isoneless(ow, nw)
isonechanged(x, y) = length(x) == length(y) && count(i -> x[i] != y[i], eachindex(y)) == 1
onefrom(nw, ow) = isoneless(nw, ow) || isonemore(nw, ow) || isonechanged(nw, ow)
function askprompt(prompt)
ans = ""
while isempty(ans)
print(prompt)
ans = strip(readline())
end
return ans
end
function wordiff(dictfile = "unixdict.txt")
wordlist = [w for w in split(read(dictfile, String), r"\s+") if !occursin(r"\W", w) && length(w) > 2]
starters = [w for w in wordlist if 3 <= length(w) <= 4]
timelimit = something(tryparse(Float64, askprompt("Time limit (min) or 0 for none: ")), 0.0)
players = split(askprompt("Enter players' names. Separate by commas: "), r"\s*,\s*")
times, word = Dict(player => Float32[] for player in players), rand(starters)
used, totalsecs, timestart = [word], timelimit * 60, time()
while length(players) > 1
player = popfirst!(players)
playertimestart = time()
newword = askprompt("$player, your move. The current word is $word. Your worddiff? ")
if timestart + totalsecs > time()
if onefrom(newword, word) && !(newword in used) && lowercase(newword) in wordlist
println("Correct.")
push!(players, player)
word = newword
push!(used, newword)
push!(times[player], time() - playertimestart)
else
println("Wordiff choice incorrect. Player $player exits game.")
end
else # out of time
println("Sorry, time was up. Timing ranks for remaining players:")
avtimes = Dict(p => isempty(times[p]) ? NaN : sum(times[p]) / length(times[p])
for p in players)
sort!(players, lt = (x, y) -> avtimes[x] < avtimes[y])
foreach(p -> println(" $p:", lpad(avtimes[p], 10), " seconds average"), players)
break
end
sleep(rand() * 3)
end
length(players) < 2 && println("Player $(first(players)) is the only one left, and wins the game.")
end
wordiff()

View file

@ -0,0 +1,119 @@
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

View file

@ -0,0 +1,53 @@
use strict;
use warnings;
use feature 'say';
use List::Util 'min';
my %cache;
sub leven {
my ($s, $t) = @_;
return length($t) if $s eq '';
return length($s) if $t eq '';
$cache{$s}{$t} //=
do {
my ($s1, $t1) = (substr($s, 1), substr($t, 1));
(substr($s, 0, 1) eq substr($t, 0, 1))
? leven($s1, $t1)
: 1 + min(
leven($s1, $t1),
leven($s, $t1),
leven($s1, $t ),
);
};
}
print "What is your name?"; my $name = <STDIN>;
$name = 'Number 6';
say "What is your quest? Never mind that, I will call you '$name'";
say 'Hey! I am not a number, I am a free man!';
my @starters = grep { length() < 6 } my @words = grep { /.{2,}/ } split "\n", `cat unixdict.txt`;
my(%used,@possibles,$guess);
my $rounds = 0;
my $word = say $starters[ rand $#starters ];
while () {
say "Word in play: $word";
$used{$word} = 1;
@possibles = ();
for my $w (@words) {
next if abs(length($word) - length($w)) > 1;
push @possibles, $w if leven($word, $w) == 1 and ! defined $used{$w};
}
print "Your word? "; $guess = <STDIN>; chomp $guess;
last unless grep { $guess eq $_ } @possibles;
$rounds++;
$word = $guess;
}
my $already = defined $used{$guess} ? " '$guess' was already played but" : '';
if (@possibles) { say "\nSorry $name,${already} one of <@possibles> would have continued the game." }
else { say "\nGood job $name,${already} there were no possible words to play." }
say "You made it through $rounds rounds.";

View file

@ -0,0 +1,307 @@
(phixonline)-->
<span style="color: #000080;font-style:italic;">-- demo\rosetta\Wordiff.exw</span>
<span style="color: #008080;">include</span> <span style="color: #000000;">pGUI</span><span style="color: #0000FF;">.</span><span style="color: #000000;">e</span>
<span style="color: #004080;">Ihandle</span> <span style="color: #000000;">dlg</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">playerset</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">playtime</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">current</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">remain</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">turn</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">input</span><span style="color: #0000FF;">,</span>
<span style="color: #000000;">help</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">quit</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">hframe</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">history</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">timer</span>
<span style="color: #004080;">atom</span> <span style="color: #000000;">t0</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">t1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">t</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span>
<span style="color: #008080;">constant</span> <span style="color: #000000;">title</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"Wordiff game"</span><span style="color: #0000FF;">,</span>
<span style="color: #000000;">help_text</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"""
Allows single or multi-player modes.
Enter eg "Pete" to play every round yourself,
"Computer" for the computer to play itself,
"Pete,Computer" (or vice versa) to play against the computer,
"Pete,Sue" for a standard two-payer game, or
"Pete,Computer,Sue,Computer" for auto-plays between each human.
Words must be 3 letters or more, and present in the dictionary,
and not already used. You must key return (not tab) to finish
entering your move. The winner is the fastest average time, if
the timer is running (/non-zero), otherwise play continues
until player elimination leaves one (or less) remaining.
NB: Pressing tab or clicking on help will restart or otherwise
mess up the gameplay.
"""</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">help_cb</span><span style="color: #0000FF;">(</span><span style="color: #004080;">Ihandln</span> <span style="color: #000080;font-style:italic;">/*ih*/</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">IupMessage</span><span style="color: #0000FF;">(</span><span style="color: #000000;">title</span><span style="color: #0000FF;">,</span><span style="color: #000000;">help_text</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">IupSetFocus</span><span style="color: #0000FF;">(</span><span style="color: #000000;">dlg</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">return</span> <span style="color: #004600;">IUP_DEFAULT</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">over2</span><span style="color: #0000FF;">(</span><span style="color: #004080;">string</span> <span style="color: #000000;">word</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">return</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">word</span><span style="color: #0000FF;">)></span><span style="color: #000000;">2</span> <span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">less5</span><span style="color: #0000FF;">(</span><span style="color: #004080;">string</span> <span style="color: #000000;">word</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">return</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">word</span><span style="color: #0000FF;">)<</span><span style="color: #000000;">5</span> <span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">words</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">filter</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">unix_dict</span><span style="color: #0000FF;">(),</span><span style="color: #000000;">over2</span><span style="color: #0000FF;">),</span>
<span style="color: #000000;">valid</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{},</span>
<span style="color: #000000;">used</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{}</span>
<span style="color: #004080;">string</span> <span style="color: #000000;">word</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">lw</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">players</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">eliminated</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">times</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">averages</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">player</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">levenshtein1</span><span style="color: #0000FF;">(</span><span style="color: #004080;">string</span> <span style="color: #000000;">w</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">bool</span> <span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #004600;">false</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">l</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">w</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #008080;">not</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #000000;">w</span><span style="color: #0000FF;">,</span><span style="color: #000000;">used</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">and</span> <span style="color: #7060A8;">abs</span><span style="color: #0000FF;">(</span><span style="color: #000000;">l</span><span style="color: #0000FF;">-</span><span style="color: #000000;">lw</span><span style="color: #0000FF;">)<=</span><span style="color: #000000;">1</span> <span style="color: #008080;">then</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">costs</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">tagset</span><span style="color: #0000FF;">(</span><span style="color: #000000;">l</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">lw</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">costs</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">i</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">newcost</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">pj</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">i</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">j</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">l</span> <span style="color: #008080;">do</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">cj</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">costs</span><span style="color: #0000FF;">[</span><span style="color: #000000;">j</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">],</span>
<span style="color: #000000;">ne</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">word</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]!=</span><span style="color: #000000;">w</span><span style="color: #0000FF;">[</span><span style="color: #000000;">j</span><span style="color: #0000FF;">],</span>
<span style="color: #000000;">nc</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">newcost</span><span style="color: #0000FF;">+</span><span style="color: #000000;">ne</span>
<span style="color: #000000;">pj</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">min</span><span style="color: #0000FF;">({</span><span style="color: #000000;">pj</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">cj</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">nc</span><span style="color: #0000FF;">})</span>
<span style="color: #000000;">costs</span><span style="color: #0000FF;">[</span><span style="color: #000000;">j</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">pj</span>
<span style="color: #000000;">newcost</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">cj</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">costs</span><span style="color: #0000FF;">[$-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]==</span><span style="color: #000000;">1</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">res</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">procedure</span> <span style="color: #000000;">game_over</span><span style="color: #0000FF;">()</span>
<span style="color: #7060A8;">IupSetAttribute</span><span style="color: #0000FF;">(</span><span style="color: #000000;">history</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"APPENDITEM"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"GAME OVER:"</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">valid</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span>
<span style="color: #004080;">string</span> <span style="color: #000000;">valids</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"You could have had "</span><span style="color: #0000FF;">&</span><span style="color: #7060A8;">join</span><span style="color: #0000FF;">(</span><span style="color: #000000;">valid</span><span style="color: #0000FF;">,</span><span style="color: #008000;">", "</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">IupSetAttribute</span><span style="color: #0000FF;">(</span><span style="color: #000000;">history</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"APPENDITEM"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">valids</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #004080;">string</span> <span style="color: #000000;">winner</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"nobody"</span>
<span style="color: #004080;">atom</span> <span style="color: #000000;">best</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">1</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">players</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
<span style="color: #004080;">string</span> <span style="color: #000000;">player</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">players</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">],</span> <span style="color: #000000;">msg</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">eliminated</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">msg</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">": eliminated"</span>
<span style="color: #008080;">else</span>
<span style="color: #004080;">atom</span> <span style="color: #000000;">average</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">averages</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">average</span><span style="color: #0000FF;">=-</span><span style="color: #000000;">1</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">msg</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">": no times"</span>
<span style="color: #008080;">else</span>
<span style="color: #000000;">msg</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">sprintf</span><span style="color: #0000FF;">(</span><span style="color: #008000;">": %.3f"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">average</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">best</span><span style="color: #0000FF;">=-</span><span style="color: #000000;">1</span> <span style="color: #008080;">or</span> <span style="color: #000000;">average</span><span style="color: #0000FF;"><</span><span style="color: #000000;">best</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">winner</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">player</span>
<span style="color: #000000;">best</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">average</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #7060A8;">IupSetAttribute</span><span style="color: #0000FF;">(</span><span style="color: #000000;">history</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"APPENDITEM"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">player</span><span style="color: #0000FF;">&</span><span style="color: #000000;">msg</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #7060A8;">IupSetAttribute</span><span style="color: #0000FF;">(</span><span style="color: #000000;">history</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"APPENDITEM"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"And the winner is: "</span><span style="color: #0000FF;">&</span><span style="color: #000000;">winner</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">IupSetInt</span><span style="color: #0000FF;">(</span><span style="color: #000000;">history</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"TOPITEM"</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">IupGetInt</span><span style="color: #0000FF;">(</span><span style="color: #000000;">history</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"COUNT"</span><span style="color: #0000FF;">))</span>
<span style="color: #7060A8;">IupSetInt</span><span style="color: #0000FF;">(</span><span style="color: #000000;">timer</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"RUN"</span><span style="color: #0000FF;">,</span><span style="color: #004600;">false</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
<span style="color: #008080;">procedure</span> <span style="color: #000000;">score</span><span style="color: #0000FF;">(</span><span style="color: #004080;">string</span> <span style="color: #000000;">move</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">times</span><span style="color: #0000FF;">[</span><span style="color: #000000;">player</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">append</span><span style="color: #0000FF;">(</span><span style="color: #000000;">times</span><span style="color: #0000FF;">[</span><span style="color: #000000;">player</span><span style="color: #0000FF;">],</span><span style="color: #7060A8;">time</span><span style="color: #0000FF;">()-</span><span style="color: #000000;">t1</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">averages</span><span style="color: #0000FF;">[</span><span style="color: #000000;">player</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">sum</span><span style="color: #0000FF;">(</span><span style="color: #000000;">times</span><span style="color: #0000FF;">[</span><span style="color: #000000;">player</span><span style="color: #0000FF;">])/</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">times</span><span style="color: #0000FF;">[</span><span style="color: #000000;">player</span><span style="color: #0000FF;">])</span>
<span style="color: #000000;">used</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">append</span><span style="color: #0000FF;">(</span><span style="color: #000000;">used</span><span style="color: #0000FF;">,</span><span style="color: #000000;">move</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">word</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">move</span>
<span style="color: #000000;">lw</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">word</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">valid</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">filter</span><span style="color: #0000FF;">(</span><span style="color: #000000;">words</span><span style="color: #0000FF;">,</span><span style="color: #000000;">levenshtein1</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">IupSetStrAttribute</span><span style="color: #0000FF;">(</span><span style="color: #000000;">current</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"TITLE"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"Current word: "</span><span style="color: #0000FF;">&</span><span style="color: #000000;">word</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
<span style="color: #008080;">procedure</span> <span style="color: #000000;">advance_player</span><span style="color: #0000FF;">()</span>
<span style="color: #008080;">while</span> <span style="color: #004600;">true</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">player</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">mod</span><span style="color: #0000FF;">(</span><span style="color: #000000;">player</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">players</span><span style="color: #0000FF;">))+</span><span style="color: #000000;">1</span>
<span style="color: #008080;">if</span> <span style="color: #008080;">not</span> <span style="color: #000000;">eliminated</span><span style="color: #0000FF;">[</span><span style="color: #000000;">player</span><span style="color: #0000FF;">]</span> <span style="color: #008080;">then</span> <span style="color: #008080;">exit</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
<span style="color: #7060A8;">IupSetStrAttribute</span><span style="color: #0000FF;">(</span><span style="color: #000000;">turn</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"TITLE"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">players</span><span style="color: #0000FF;">[</span><span style="color: #000000;">player</span><span style="color: #0000FF;">]&</span><span style="color: #008000;">"'s turn:"</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">IupRefreshChildren</span><span style="color: #0000FF;">(</span><span style="color: #000000;">turn</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">IupSetStrAttribute</span><span style="color: #0000FF;">(</span><span style="color: #000000;">input</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"VALUE"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">word</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">t1</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">time</span><span style="color: #0000FF;">()</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
<span style="color: #008080;">procedure</span> <span style="color: #000000;">autoplay</span><span style="color: #0000FF;">()</span>
<span style="color: #008080;">while</span> <span style="color: #004600;">true</span> <span style="color: #008080;">do</span>
<span style="color: #008080;">if</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">valid</span><span style="color: #0000FF;">)=</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span>
<span style="color: #7060A8;">IupSetAttribute</span><span style="color: #0000FF;">(</span><span style="color: #000000;">history</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"APPENDITEM"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"no more moves possible"</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">game_over</span><span style="color: #0000FF;">()</span>
<span style="color: #008080;">exit</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">if</span> <span style="color: #7060A8;">proper</span><span style="color: #0000FF;">(</span><span style="color: #000000;">players</span><span style="color: #0000FF;">[</span><span style="color: #000000;">player</span><span style="color: #0000FF;">])!=</span><span style="color: #008000;">"Computer"</span> <span style="color: #008080;">then</span> <span style="color: #008080;">exit</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #004080;">string</span> <span style="color: #000000;">move</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">valid</span><span style="color: #0000FF;">[</span><span style="color: #7060A8;">rand</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">valid</span><span style="color: #0000FF;">))]</span>
<span style="color: #7060A8;">IupSetStrAttribute</span><span style="color: #0000FF;">(</span><span style="color: #000000;">history</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"APPENDITEM"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%s's move: %s\n"</span><span style="color: #0000FF;">,</span>
<span style="color: #0000FF;">{</span><span style="color: #000000;">players</span><span style="color: #0000FF;">[</span><span style="color: #000000;">player</span><span style="color: #0000FF;">],</span><span style="color: #000000;">move</span><span style="color: #0000FF;">})</span>
<span style="color: #7060A8;">IupSetInt</span><span style="color: #0000FF;">(</span><span style="color: #000000;">history</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"TOPITEM"</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">IupGetInt</span><span style="color: #0000FF;">(</span><span style="color: #000000;">history</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"COUNT"</span><span style="color: #0000FF;">))</span>
<span style="color: #000000;">score</span><span style="color: #0000FF;">(</span><span style="color: #000000;">move</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">advance_player</span><span style="color: #0000FF;">()</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
<span style="color: #008080;">procedure</span> <span style="color: #000000;">new_game</span><span style="color: #0000FF;">(</span><span style="color: #004080;">bool</span> <span style="color: #000000;">bStart</span><span style="color: #0000FF;">=</span><span style="color: #004600;">true</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">bool</span> <span style="color: #000000;">bActive</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">players</span><span style="color: #0000FF;">)!=</span><span style="color: #000000;">0</span>
<span style="color: #7060A8;">IupSetInt</span><span style="color: #0000FF;">(</span><span style="color: #000000;">turn</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"ACTIVE"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">bActive</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">IupSetInt</span><span style="color: #0000FF;">(</span><span style="color: #000000;">input</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"ACTIVE"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">bActive</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">bActive</span> <span style="color: #008080;">and</span> <span style="color: #000000;">bStart</span> <span style="color: #008080;">then</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">w34</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">filter</span><span style="color: #0000FF;">(</span><span style="color: #000000;">words</span><span style="color: #0000FF;">,</span><span style="color: #000000;">less5</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">while</span> <span style="color: #004600;">true</span> <span style="color: #008080;">do</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">r</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">rand</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">w34</span><span style="color: #0000FF;">))</span>
<span style="color: #000000;">word</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">w34</span><span style="color: #0000FF;">[</span><span style="color: #000000;">r</span><span style="color: #0000FF;">]</span>
<span style="color: #000000;">lw</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">word</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">used</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">word</span><span style="color: #0000FF;">}</span>
<span style="color: #000000;">valid</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">filter</span><span style="color: #0000FF;">(</span><span style="color: #000000;">words</span><span style="color: #0000FF;">,</span><span style="color: #000000;">levenshtein1</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">valid</span><span style="color: #0000FF;">)!=</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span> <span style="color: #008080;">exit</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #000000;">w34</span><span style="color: #0000FF;">[</span><span style="color: #000000;">r</span><span style="color: #0000FF;">..</span><span style="color: #000000;">r</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{}</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
<span style="color: #7060A8;">IupSetStrAttribute</span><span style="color: #0000FF;">(</span><span style="color: #000000;">current</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"TITLE"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"Current word: "</span><span style="color: #0000FF;">&</span><span style="color: #000000;">word</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">IupSetStrAttribute</span><span style="color: #0000FF;">(</span><span style="color: #000000;">turn</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"TITLE"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">players</span><span style="color: #0000FF;">[</span><span style="color: #000000;">player</span><span style="color: #0000FF;">]&</span><span style="color: #008000;">"'s turn:"</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">IupRefreshChildren</span><span style="color: #0000FF;">(</span><span style="color: #000000;">turn</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">IupSetStrAttribute</span><span style="color: #0000FF;">(</span><span style="color: #000000;">input</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"VALUE"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">word</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">IupSetAttribute</span><span style="color: #0000FF;">(</span><span style="color: #000000;">history</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"REMOVEITEM"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"ALL"</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">IupSetAttribute</span><span style="color: #0000FF;">(</span><span style="color: #000000;">history</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"APPENDITEM"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"Initial word: "</span><span style="color: #0000FF;">&</span><span style="color: #000000;">word</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">IupSetInt</span><span style="color: #0000FF;">(</span><span style="color: #000000;">history</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"TOPITEM"</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">IupGetInt</span><span style="color: #0000FF;">(</span><span style="color: #000000;">history</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"COUNT"</span><span style="color: #0000FF;">))</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">l</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">players</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">eliminated</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #004600;">false</span><span style="color: #0000FF;">,</span><span style="color: #000000;">l</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">times</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">({},</span><span style="color: #000000;">l</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">averages</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">l</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">t0</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">time</span><span style="color: #0000FF;">()</span>
<span style="color: #000000;">t1</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">time</span><span style="color: #0000FF;">()</span>
<span style="color: #7060A8;">IupSetInt</span><span style="color: #0000FF;">(</span><span style="color: #000000;">timer</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"RUN"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">t</span><span style="color: #0000FF;">!=</span><span style="color: #000000;">0</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">autoplay</span><span style="color: #0000FF;">()</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">players_cb</span><span style="color: #0000FF;">(</span><span style="color: #004080;">Ihandln</span> <span style="color: #000080;font-style:italic;">/*playerset*/</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">players</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">split</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">IupGetAttribute</span><span style="color: #0000FF;">(</span><span style="color: #000000;">playerset</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"VALUE"</span><span style="color: #0000FF;">),</span><span style="color: #008000;">","</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">player</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span>
<span style="color: #000000;">new_game</span><span style="color: #0000FF;">(</span><span style="color: #004600;">false</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">return</span> <span style="color: #004600;">IUP_DEFAULT</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">playtime_cb</span><span style="color: #0000FF;">(</span><span style="color: #004080;">Ihandle</span> <span style="color: #000080;font-style:italic;">/*playtime*/</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">t</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">IupGetInt</span><span style="color: #0000FF;">(</span><span style="color: #000000;">playtime</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"VALUE"</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">t</span> <span style="color: #008080;">then</span>
<span style="color: #7060A8;">IupSetInt</span><span style="color: #0000FF;">(</span><span style="color: #000000;">remain</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"VISIBLE"</span><span style="color: #0000FF;">,</span><span style="color: #004600;">true</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">IupSetStrAttribute</span><span style="color: #0000FF;">(</span><span style="color: #000000;">remain</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"TITLE"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"Remaining: %.1fs"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">t</span><span style="color: #0000FF;">})</span>
<span style="color: #008080;">else</span>
<span style="color: #7060A8;">IupSetInt</span><span style="color: #0000FF;">(</span><span style="color: #000000;">remain</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"VISIBLE"</span><span style="color: #0000FF;">,</span><span style="color: #004600;">false</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #7060A8;">IupRefreshChildren</span><span style="color: #0000FF;">(</span><span style="color: #000000;">remain</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">return</span> <span style="color: #004600;">IUP_DEFAULT</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">focus_cb</span><span style="color: #0000FF;">(</span><span style="color: #004080;">Ihandle</span> <span style="color: #000080;font-style:italic;">/*input*/</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">new_game</span><span style="color: #0000FF;">(</span><span style="color: #004600;">true</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">return</span> <span style="color: #004600;">IUP_DEFAULT</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">procedure</span> <span style="color: #000000;">verify_move</span><span style="color: #0000FF;">()</span>
<span style="color: #004080;">string</span> <span style="color: #000000;">move</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">IupGetAttribute</span><span style="color: #0000FF;">(</span><span style="color: #000000;">input</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"VALUE"</span><span style="color: #0000FF;">),</span>
<span style="color: #000000;">okstr</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"ok"</span>
<span style="color: #004080;">bool</span> <span style="color: #000000;">ok</span> <span style="color: #0000FF;">=</span> <span style="color: #008080;">not</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #000000;">move</span><span style="color: #0000FF;">,</span><span style="color: #000000;">used</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #008080;">not</span> <span style="color: #000000;">ok</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">okstr</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"already used"</span>
<span style="color: #008080;">else</span>
<span style="color: #000000;">ok</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #000000;">move</span><span style="color: #0000FF;">,</span><span style="color: #000000;">words</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #008080;">not</span> <span style="color: #000000;">ok</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">okstr</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"not in dictionary"</span>
<span style="color: #008080;">else</span>
<span style="color: #000000;">ok</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #000000;">move</span><span style="color: #0000FF;">,</span><span style="color: #000000;">valid</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #008080;">not</span> <span style="color: #000000;">ok</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">okstr</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"more than one change"</span>
<span style="color: #008080;">else</span>
<span style="color: #000000;">used</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">append</span><span style="color: #0000FF;">(</span><span style="color: #000000;">used</span><span style="color: #0000FF;">,</span><span style="color: #000000;">move</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">if</span> <span style="color: #008080;">not</span> <span style="color: #000000;">ok</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">okstr</span> <span style="color: #0000FF;">&=</span> <span style="color: #008000;">", player eliminated"</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #7060A8;">IupSetStrAttribute</span><span style="color: #0000FF;">(</span><span style="color: #000000;">history</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"APPENDITEM"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%s's move: %s %s\n"</span><span style="color: #0000FF;">,</span>
<span style="color: #0000FF;">{</span><span style="color: #000000;">players</span><span style="color: #0000FF;">[</span><span style="color: #000000;">player</span><span style="color: #0000FF;">],</span><span style="color: #000000;">move</span><span style="color: #0000FF;">,</span><span style="color: #000000;">okstr</span><span style="color: #0000FF;">})</span>
<span style="color: #7060A8;">IupSetInt</span><span style="color: #0000FF;">(</span><span style="color: #000000;">history</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"TOPITEM"</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">IupGetInt</span><span style="color: #0000FF;">(</span><span style="color: #000000;">history</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"COUNT"</span><span style="color: #0000FF;">))</span>
<span style="color: #008080;">if</span> <span style="color: #008080;">not</span> <span style="color: #000000;">ok</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">eliminated</span><span style="color: #0000FF;">[</span><span style="color: #000000;">player</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #004600;">true</span>
<span style="color: #008080;">if</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">players</span><span style="color: #0000FF;">)-</span><span style="color: #7060A8;">sum</span><span style="color: #0000FF;">(</span><span style="color: #000000;">eliminated</span><span style="color: #0000FF;">)<=</span><span style="color: #000000;">1</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">game_over</span><span style="color: #0000FF;">()</span>
<span style="color: #008080;">return</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">else</span>
<span style="color: #000000;">score</span><span style="color: #0000FF;">(</span><span style="color: #000000;">move</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #000000;">advance_player</span><span style="color: #0000FF;">()</span>
<span style="color: #000000;">autoplay</span><span style="color: #0000FF;">()</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">timer_cb</span><span style="color: #0000FF;">(</span><span style="color: #004080;">Ihandle</span> <span style="color: #000080;font-style:italic;">/*timer*/</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">atom</span> <span style="color: #000000;">e</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">time</span><span style="color: #0000FF;">()-</span><span style="color: #000000;">t0</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">e</span><span style="color: #0000FF;">>=</span><span style="color: #000000;">t</span> <span style="color: #008080;">then</span>
<span style="color: #7060A8;">IupSetStrAttribute</span><span style="color: #0000FF;">(</span><span style="color: #000000;">remain</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"TITLE"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"Remaining: 0s"</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">IupSetInt</span><span style="color: #0000FF;">(</span><span style="color: #000000;">turn</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"ACTIVE"</span><span style="color: #0000FF;">,</span><span style="color: #004600;">false</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">IupSetInt</span><span style="color: #0000FF;">(</span><span style="color: #000000;">input</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"ACTIVE"</span><span style="color: #0000FF;">,</span><span style="color: #004600;">false</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">game_over</span><span style="color: #0000FF;">()</span>
<span style="color: #008080;">else</span>
<span style="color: #7060A8;">IupSetStrAttribute</span><span style="color: #0000FF;">(</span><span style="color: #000000;">remain</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"TITLE"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"Remaining: %.1fs"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">t</span><span style="color: #0000FF;">-</span><span style="color: #000000;">e</span><span style="color: #0000FF;">})</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">return</span> <span style="color: #004600;">IUP_DEFAULT</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">quit_cb</span><span style="color: #0000FF;">(</span><span style="color: #004080;">Ihandle</span> <span style="color: #000080;font-style:italic;">/*ih*/</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">return</span> <span style="color: #004600;">IUP_CLOSE</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">key_cb</span><span style="color: #0000FF;">(</span><span style="color: #004080;">Ihandle</span> <span style="color: #000080;font-style:italic;">/*dlg*/</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">atom</span> <span style="color: #000000;">c</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">c</span><span style="color: #0000FF;">=</span><span style="color: #004600;">K_ESC</span> <span style="color: #008080;">then</span> <span style="color: #008080;">return</span> <span style="color: #004600;">IUP_CLOSE</span>
<span style="color: #008080;">elsif</span> <span style="color: #000000;">c</span><span style="color: #0000FF;">=</span><span style="color: #004600;">K_CR</span> <span style="color: #008080;">then</span>
<span style="color: #004080;">Ihandln</span> <span style="color: #000000;">focus</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">IupGetFocus</span><span style="color: #0000FF;">()</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">focus</span><span style="color: #0000FF;">=</span><span style="color: #000000;">playerset</span> <span style="color: #008080;">then</span>
<span style="color: #7060A8;">IupSetFocus</span><span style="color: #0000FF;">(</span><span style="color: #000000;">playtime</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">elsif</span> <span style="color: #000000;">focus</span><span style="color: #0000FF;">=</span><span style="color: #000000;">playtime</span> <span style="color: #008080;">then</span>
<span style="color: #7060A8;">IupSetFocus</span><span style="color: #0000FF;">(</span><span style="color: #000000;">input</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">new_game</span><span style="color: #0000FF;">()</span>
<span style="color: #008080;">elsif</span> <span style="color: #000000;">focus</span><span style="color: #0000FF;">=</span><span style="color: #000000;">input</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">verify_move</span><span style="color: #0000FF;">()</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">elsif</span> <span style="color: #000000;">c</span><span style="color: #0000FF;">=</span><span style="color: #004600;">K_F1</span> <span style="color: #008080;">then</span> <span style="color: #008080;">return</span> <span style="color: #000000;">help_cb</span><span style="color: #0000FF;">(</span><span style="color: #004600;">NULL</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">elsif</span> <span style="color: #000000;">c</span><span style="color: #0000FF;">=</span><span style="color: #004600;">K_cC</span> <span style="color: #008080;">then</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">n</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">IupGetInt</span><span style="color: #0000FF;">(</span><span style="color: #000000;">history</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"COUNT"</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">hist</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">n</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">n</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">hist</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">IupGetAttributeId</span><span style="color: #0000FF;">(</span><span style="color: #000000;">history</span><span style="color: #0000FF;">,</span><span style="color: #008000;">""</span><span style="color: #0000FF;">,</span><span style="color: #000000;">i</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #000000;">hist</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">join</span><span style="color: #0000FF;">(</span><span style="color: #000000;">hist</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"\n"</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">Ihandln</span> <span style="color: #000000;">clip</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">IupClipboard</span><span style="color: #0000FF;">()</span>
<span style="color: #7060A8;">IupSetAttribute</span><span style="color: #0000FF;">(</span><span style="color: #000000;">clip</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"TEXT"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">hist</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">clip</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">IupDestroy</span><span style="color: #0000FF;">(</span><span style="color: #000000;">clip</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">return</span> <span style="color: #004600;">IUP_CONTINUE</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #7060A8;">IupOpen</span><span style="color: #0000FF;">()</span>
<span style="color: #000000;">playerset</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">IupText</span><span style="color: #0000FF;">(</span><span style="color: #008000;">`EXPAND=HORIZONTAL`</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">playtime</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">IupText</span><span style="color: #0000FF;">(</span><span style="color: #008000;">`SPIN=Yes, SPINMIN=0, RASTERSIZE=48x`</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">IupSetCallback</span><span style="color: #0000FF;">({</span><span style="color: #000000;">playerset</span><span style="color: #0000FF;">,</span><span style="color: #000000;">playtime</span><span style="color: #0000FF;">},</span><span style="color: #008000;">"KILLFOCUS_CB"</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">Icallback</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"players_cb"</span><span style="color: #0000FF;">))</span>
<span style="color: #7060A8;">IupSetCallback</span><span style="color: #0000FF;">(</span><span style="color: #000000;">playtime</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"VALUECHANGED_CB"</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">Icallback</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"playtime_cb"</span><span style="color: #0000FF;">))</span>
<span style="color: #000000;">turn</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">IupLabel</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"turn"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"ACTIVE=NO"</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">input</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">IupText</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"EXPAND=HORIZONTAL, ACTIVE=NO"</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">IupSetCallback</span><span style="color: #0000FF;">(</span><span style="color: #000000;">input</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"GETFOCUS_CB"</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">Icallback</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"focus_cb"</span><span style="color: #0000FF;">))</span>
<span style="color: #000000;">current</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">IupLabel</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"Current word:"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"EXPAND=HORIZONTAL"</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">remain</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">IupLabel</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"Remaining time:0s"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"VISIBLE=NO"</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">history</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">IupList</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"VISIBLELINES=10, EXPAND=YES, CANFOCUS=NO"</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">hframe</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">IupFrame</span><span style="color: #0000FF;">(</span><span style="color: #000000;">history</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"TITLE=History, PADDING=5x4"</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">help</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">IupButton</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"Help (F1)"</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">Icallback</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"help_cb"</span><span style="color: #0000FF;">),</span><span style="color: #008000;">"PADDING=5x4"</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">quit</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">IupButton</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"Close"</span><span style="color: #0000FF;">,</span> <span style="color: #7060A8;">Icallback</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"quit_cb"</span><span style="color: #0000FF;">))</span>
<span style="color: #000000;">timer</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">IupTimer</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">Icallback</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"timer_cb"</span><span style="color: #0000FF;">),</span><span style="color: #000000;">100</span><span style="color: #0000FF;">,</span><span style="color: #004600;">false</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">buttons</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #7060A8;">IupFill</span><span style="color: #0000FF;">(),</span><span style="color: #000000;">help</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">IupFill</span><span style="color: #0000FF;">(),</span><span style="color: #000000;">quit</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">IupFill</span><span style="color: #0000FF;">()}</span>
<span style="color: #008080;">constant</span> <span style="color: #000000;">acp</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"ALIGNMENT=ACENTER, PADDING=5"</span>
<span style="color: #004080;">Ihandle</span> <span style="color: #000000;">settings</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">IupHbox</span><span style="color: #0000FF;">({</span><span style="color: #7060A8;">IupLabel</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"Contestant name(s)"</span><span style="color: #0000FF;">),</span>
<span style="color: #000000;">playerset</span><span style="color: #0000FF;">,</span>
<span style="color: #7060A8;">IupLabel</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"Timer (seconds)"</span><span style="color: #0000FF;">),</span>
<span style="color: #000000;">playtime</span><span style="color: #0000FF;">},</span><span style="color: #000000;">acp</span><span style="color: #0000FF;">),</span>
<span style="color: #000000;">currbox</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">IupHbox</span><span style="color: #0000FF;">({</span><span style="color: #000000;">current</span><span style="color: #0000FF;">,</span><span style="color: #000000;">remain</span><span style="color: #0000FF;">},</span><span style="color: #000000;">acp</span><span style="color: #0000FF;">),</span>
<span style="color: #000000;">numbox</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">IupHbox</span><span style="color: #0000FF;">({</span><span style="color: #000000;">turn</span><span style="color: #0000FF;">,</span><span style="color: #000000;">input</span><span style="color: #0000FF;">},</span><span style="color: #000000;">acp</span><span style="color: #0000FF;">),</span>
<span style="color: #000000;">btnbox</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">IupHbox</span><span style="color: #0000FF;">(</span><span style="color: #000000;">buttons</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"PADDING=40, NORMALIZESIZE=BOTH"</span><span style="color: #0000FF;">),</span>
<span style="color: #000000;">vbox</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">IupVbox</span><span style="color: #0000FF;">({</span><span style="color: #000000;">settings</span><span style="color: #0000FF;">,</span>
<span style="color: #000000;">currbox</span><span style="color: #0000FF;">,</span>
<span style="color: #000000;">numbox</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">hframe</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">btnbox</span><span style="color: #0000FF;">},</span> <span style="color: #008000;">"GAP=5,MARGIN=5x5"</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">dlg</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">IupDialog</span><span style="color: #0000FF;">(</span><span style="color: #000000;">vbox</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">`TITLE="%s", SIZE=500x220`</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">title</span><span style="color: #0000FF;">})</span>
<span style="color: #7060A8;">IupSetCallback</span><span style="color: #0000FF;">(</span><span style="color: #000000;">dlg</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"K_ANY"</span><span style="color: #0000FF;">,</span> <span style="color: #7060A8;">Icallback</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"key_cb"</span><span style="color: #0000FF;">))</span>
<span style="color: #7060A8;">IupShow</span><span style="color: #0000FF;">(</span><span style="color: #000000;">dlg</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #7060A8;">platform</span><span style="color: #0000FF;">()!=</span><span style="color: #004600;">JS</span> <span style="color: #008080;">then</span>
<span style="color: #7060A8;">IupMainLoop</span><span style="color: #0000FF;">()</span>
<span style="color: #7060A8;">IupClose</span><span style="color: #0000FF;">()</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<!--

View file

@ -0,0 +1,107 @@
# -*- coding: utf-8 -*-
from typing import List, Tuple, Dict, Set
from itertools import cycle, islice
from collections import Counter
import re
import random
import urllib
dict_fname = 'unixdict.txt'
dict_url1 = 'http://wiki.puzzlers.org/pub/wordlists/unixdict.txt' # ~25K words
dict_url2 = 'https://raw.githubusercontent.com/dwyl/english-words/master/words.txt' # ~470K words
word_regexp = re.compile(r'^[a-z]{3,}$') # reduce dict words to those of three or more a-z characters.
def load_dictionary(fname: str=dict_fname) -> Set[str]:
"Return appropriate words from a dictionary file"
with open(fname) as f:
return {lcase for lcase in (word.strip().lower() for word in f)
if word_regexp.match(lcase)}
def load_web_dictionary(url: str) -> Set[str]:
"Return appropriate words from a dictionary web page"
words = urllib.request.urlopen(url).read().decode().strip().lower().split()
return {word for word in words if word_regexp.match(word)}
def get_players() -> List[str]:
"Return inputted ordered list of contestant names."
names = input('Space separated list of contestants: ')
return [n.capitalize() for n in names.strip().split()]
def is_wordiff(wordiffs: List[str], word: str, dic: Set[str], comment=True) -> bool:
"Is word a valid wordiff from wordiffs[-1] ?"
if word not in dic:
if comment:
print('That word is not in my dictionary')
return False
if word in wordiffs:
if comment:
print('That word was already used.')
return False
if len(word) < len(wordiffs[-1]):
return is_wordiff_removal(word, wordiffs[-1], comment)
elif len(word) > len(wordiffs[-1]):
return is_wordiff_insertion(word, wordiffs[-1], comment)
return is_wordiff_change(word, wordiffs[-1], comment)
def is_wordiff_removal(word: str, prev: str, comment=True) -> bool:
"Is word derived from prev by removing one letter?"
...
ans = word in {prev[:i] + prev[i+1:] for i in range(len(prev))}
if not ans:
if comment:
print('Word is not derived from previous by removal of one letter.')
return ans
def is_wordiff_insertion(word: str, prev: str, comment=True) -> bool:
"Is word derived from prev by adding one letter?"
diff = Counter(word) - Counter(prev)
diffcount = sum(diff.values())
if diffcount != 1:
if comment:
print('More than one character insertion difference.')
return False
insert = list(diff.keys())[0]
ans = word in {prev[:i] + insert + prev[i:] for i in range(len(prev) + 1)}
if not ans:
if comment:
print('Word is not derived from previous by insertion of one letter.')
return ans
def is_wordiff_change(word: str, prev: str, comment=True) -> bool:
"Is word derived from prev by changing exactly one letter?"
...
diffcount = sum(w != p for w, p in zip(word, prev))
if diffcount != 1:
if comment:
print('More or less than exactly one character changed.')
return False
return True
def could_have_got(wordiffs: List[str], dic: Set[str]):
return (word for word in (dic - set(wordiffs))
if is_wordiff(wordiffs, word, dic, comment=False))
if __name__ == '__main__':
dic = load_web_dictionary(dict_url2)
dic_3_4 = [word for word in dic if len(word) in {3, 4}]
start = random.choice(dic_3_4)
wordiffs = [start]
players = get_players()
for name in cycle(players):
word = input(f"{name}: Input a wordiff from {wordiffs[-1]!r}: ").strip()
if is_wordiff(wordiffs, word, dic):
wordiffs.append(word)
else:
print(f'YOU HAVE LOST {name}!')
print("Could have used:",
', '.join(islice(could_have_got(wordiffs, dic), 10)), '...')
break

View file

@ -0,0 +1,96 @@
/*REXX program acts as a host and allows two or more people to play the WORDIFF game.*/
signal on halt /*allow the user(s) to halt the game. */
parse arg iFID seed . /*obtain optional arguments from the CL*/
if iFID=='' | iFID=="," then iFID='unixdict.txt' /*Not specified? Then use the default.*/
if datatype(seed, 'W') then call random ,,seed /*If " " " " seed. */
call read
call IDs
first= random(1, min(100000, starters) ) /*get a random start word for the game.*/
list= $$$.first
say; say eye "OK, let's play the WORDIFF game."; say; say
do round=1
do player=1 for players
call show; ou= o; upper ou
call CBLF word(names, player)
end /*players*/
end /*round*/
halt: say; say; say eye 'The WORDIFF game has been halted.'
done: exit 0 /*stick a fork in it, we're all done. */
quit: say; say; say eye 'The WORDDIF game is quitting.'; signal done
/*──────────────────────────────────────────────────────────────────────────────────────*/
isMix: return datatype(arg(1), 'M') /*return unity if arg has mixed letters*/
ser: say; say eye '***error*** ' arg(1).; say; return /*issue error message. */
last: parse arg y; return word(y, words(y) ) /*get last word in list.*/
over: call ser 'word ' _ x _ arg(1); say eye 'game over,' you; signal done /*game over*/
show: o= last(list); say; call what; say; L= length(o); return
verE: m= 0; do v=1 for L; m= m + (substr(ou,v,1)==substr(xu,v,1)); end; return m==L-1
verL: do v=1 for L; if space(overlay(' ', ou, v), 0)==xu then return 1; end; return 0
verG: do v=1 for w; if space(overlay(' ', xu, v), 0)==ou then return 1; end; return 0
what: say eye 'The current word in play is: ' _ o _; return
/*──────────────────────────────────────────────────────────────────────────────────────*/
CBLF: parse arg you /*ask carbon-based life form for a word*/
do getword=0 by 0 until x\==''
say eye "What's your word to be played, " you'?'
parse pull x; x= space(x); #= words(x); if #==0 then iterate; w= length(x)
if #>1 then do; call ser 'too many words given: ' x
x=; iterate getword
end
if \isMix(x) then do; call ser 'the name' _ x _ " isn't alphabetic"
x=; iterate getword
end
end /*getword*/
if wordpos(x, list)>0 then call over " has already been used"
xu= x; upper xu /*obtain an uppercase version of word. */
if \@.xu then call over " doesn't exist in the dictionary: " iFID
if length(x) <3 then call over " must be at least three letters long."
if w <L then if \verL() then call over " isn't a legal letter deletion."
if w==L then if \verE() then call over " isn't a legal letter substitution."
if w >L then if \verG() then call over " isn't a legal letter addition."
list= list x /*add word to the list of words used. */
return
/*──────────────────────────────────────────────────────────────────────────────────────*/
IDs: ?= "Enter the names of the people that'll be playing the WORDIFF game (or Quit):"
names= /*start with a clean slate (of names). */
do getIDs=0 by 0 until words(names)>1
say; say eye ?
parse pull ids; ids= space( translate(ids, , ',') ) /*elide any commas. */
if ids=='' then iterate; q= ids; upper q /*use uppercase QUIT*/
if abbrev('QUIT', q, 1) then signal quit
do j=1 for words(ids); x= word(ids, j)
if \isMix(x) then do; call ser 'the name' _ x _ " isn't alphabetic"
names=; iterate getIDs
end
if wordpos(x, names)>0 then do; call ser 'the name' _ x _ " is already taken"
names=; iterate getIDs
end
names= space(names x)
end /*j*/
end /*getIDs*/
say
players= words(names)
do until ans\==''
say eye 'The ' players " player's names are: " names
say eye 'Is this correct?'; pull ans; ans= space(ans)
end /*until*/
yeahs= 'yah yeah yes ja oui si da'; upper yeahs
do ya=1 for words(yeahs)
if abbrev( word(yeahs, ya), ans, 2) | ans=='Y' then return
end /*ya*/
call IDS; return
/*──────────────────────────────────────────────────────────────────────────────────────*/
read: _= ''; eye= copies('', 8) /*define a couple of eye catchers. */
say; say eye eye eye 'Welcome to the WORDIFF word game.' eye eye eye; say
@.= 0; starters= 0
do r=1 while lines(iFID)\==0 /*read each word in the file (word=X).*/
x= strip(linein(iFID)) /*pick off a word from the input line. */
if \isMix(x) then iterate /*Not a suitable word for WORDIFF? Skip*/
y= x; upper x /*pick off a word from the input line. */
@.x= 1; L= length(x) /*set a semaphore for uppercased word. */
if L<3 | L>4 then iterate /*only use short words for the start. */
starters= starters + 1 /*bump the count of starter words. */
$$$.starters= y /*save short words for the starter word*/
end /*#*/
if r>100 & starters> 10 then return /*is the dictionary satisfactory ? */
call ser 'Dictionary file ' _ iFID _ "wasn't found or isn't satisfactory."; exit 13

View file

@ -0,0 +1,55 @@
my @words = 'unixdict.txt'.IO.slurp.lc.words.grep(*.chars > 2);
my @small = @words.grep(*.chars < 6);
use Text::Levenshtein;
my ($rounds, $word, $guess, @used, @possibles) = 0;
loop {
my $lev;
$word = @small.pick;
hyper for @words -> $this {
next if ($word.chars - $this.chars).abs > 1;
last if ($lev = distance($word, $this)[0]) == 1;
}
last if $lev;
}
my $name = ',';
#[[### Entirely unnecessary and unuseful "chatty repartee" but is required by the task
run 'clear';
$name = prompt "Hello player one, what is your name? ";
say "Cool. I'm going to call you Gomer.";
$name = ' Gomer,';
sleep 1;
say "\nPlayer two, what is your name?\nOh wait, this isn't a \"specified number of players\" game...";
sleep 1;
say "Nevermind.\n";
################################################################################]]
loop {
say "Word in play: $word";
push @used, $word;
@possibles = @words.hyper.map: -> $this {
next if ($word.chars - $this.chars).abs > 1;
$this if distance($word, $this)[0] == 1 and $this @used;
}
$guess = prompt "your word? ";
last unless $guess @possibles;
++$rounds;
say qww<Ok! Woot! 'Way to go!' Nice! 👍 😀>.pick ~ "\n";
$word = $guess;
}
my $already = ($guess @used) ?? " $guess was already played but" !! '';
if @possibles {
say "\nOops. Sorry{$name}{$already} one of [{@possibles}] would have continued the game."
} else {
say "\nGood job{$name}{$already} there were no possible words to play."
}
say "You made it through $rounds rounds.";

View file

@ -0,0 +1,97 @@
import os
import rand
import time
import arrays
fn is_wordiff(guesses []string, word string, dict []string) bool {
if word !in dict {
println('That word is not in the dictionary')
return false
}
if word in guesses {
println('That word has already been used')
return false
}
if word.len < guesses[guesses.len-1].len {
return is_wordiff_removal(word, guesses[guesses.len-1])
} else if word.len > guesses[guesses.len-1].len {
return is_wordiff_insertion(word, guesses[guesses.len-1])
}
return is_wordiff_change(word,guesses[guesses.len-1])
}
fn is_wordiff_removal(new_word string, last_word string) bool {
for i in 0..last_word.len {
if new_word == last_word[..i] + last_word[i+1..] {
return true
}
}
println('Word is not derived from previous by removal of one letter')
return false
}
fn is_wordiff_insertion(new_word string, last_word string) bool {
if new_word.len > last_word.len+1 {
println('More than one character insertion difference')
return false
}
mut a := new_word.split('')
b := last_word.split('')
for c in b {
idx := a.index(c)
if idx >=0 {
a.delete(idx)
}
}
if a.len >1 {
println('Word is not derived from previous by insertion of one letter')
return false
}
return true
}
fn is_wordiff_change(new_word string, last_word string) bool {
mut diff:=0
for i,c in new_word {
if c != last_word[i] {
diff++
}
}
if diff != 1 {
println('More or less than exactly one character changed')
return false
}
return true
}
fn main() {
words := os.read_lines('unixdict.txt')?
time_limit := os.input('Time limit (sec) or 0 for none: ').int()
players := os.input('Please enter player names, separated by commas: ').split(',')
dic_3_4 := words.filter(it.len in [3,4])
mut wordiffs := rand.choose<string>(dic_3_4,1)?
mut timing := [][]f64{len: players.len}
start := time.now()
mut turn_count := 0
for {
turn_start := time.now()
word := os.input('${players[turn_count%players.len]}: Input a wordiff from ${wordiffs[wordiffs.len-1]}: ')
if time_limit != 0.0 && time.since(start).seconds()>time_limit{
println('TIMES UP ${players[turn_count%players.len]}')
break
} else {
if is_wordiff(wordiffs, word, words) {
wordiffs<<word
}else{
timing[turn_count%players.len] << time.since(turn_start).seconds()
println('YOU HAVE LOST ${players[turn_count%players.len]}')
break
}
}
timing[turn_count%players.len] << time.since(turn_start).seconds()
turn_count++
}
println('Timing ranks:')
for i,p in timing {
sum := arrays.sum<f64>(p) or {0}
println(' ${players[i]}: ${sum/p.len:10.3 f} seconds average')
}
}

View file

@ -0,0 +1,85 @@
import "random" for Random
import "/ioutil" for File, Input
import "/str" for Str
import "/sort" for Find
var rand = Random.new()
var words = File.read("unixdict.txt").trim().split("\n")
var player1 = Input.text("Player 1, please enter your name : ", 1)
var player2 = Input.text("Player 2, please enter your name : ", 1)
if (player2 == player1) player2 = player2 + "2"
var words3or4 = words.where { |w| w.count == 3 || w.count == 4 }.toList
var n = words3or4.count
var firstWord = words3or4[rand.int(n)]
var prevLen = firstWord.count
var prevWord = firstWord
var used = []
var player = player1
System.print("\nThe first word is %(firstWord)\n")
while (true) {
var word = Str.lower(Input.text("%(player), enter your word : ", 1))
var len = word.count
var ok = false
if (len < 3) {
System.print("Words must be at least 3 letters long.")
} else if (Find.first(words, word) == -1) {
System.print("Not in dictionary.")
} else if (used.contains(word)) {
System.print("Word has been used before.")
} else if (word == prevWord) {
System.print("You must change the previous word.")
} else if (len == prevLen) {
var changes = 0
for (i in 0...len) {
if (word[i] != prevWord[i]) {
changes = changes + 1
}
}
if (changes > 1) {
System.print("Only one letter can be changed.")
} else ok = true
} else if (len == prevLen + 1) {
var addition = false
var temp = word
for (i in 0...prevLen) {
if (word[i] != prevWord[i]) {
addition = true
temp = Str.delete(temp, i)
if (temp == prevWord) {
ok = true
}
break
}
}
if (!addition) ok = true
if (!ok) System.print("Invalid addition.")
} else if (len == prevLen - 1) {
var deletion = false
var temp = prevWord
for (i in 0...len) {
if (word[i] != prevWord[i]) {
deletion = true
temp = Str.delete(temp, i)
if (temp == word) {
ok = true
}
break
}
}
if (!deletion) ok = true
if (!ok) System.print("Invalid deletion.")
} else {
System.print("Invalid change.")
}
if (ok) {
prevLen = word.count
prevWord = word
used.add(word)
player = (player == player1) ? player2 : player1
} else {
System.print("So, sorry %(player), you've lost!")
return
}
}