Programma's en documentatie bij Woordle-2
Gebruikte procedures en variabelen
Hieronder volgt nogmaals een overzicht van de gebruikte procedures en variabelen in de programmatuur
Procedures
LineReduce(line)
Verwijdert Nieuwe Regel op het einde van een woord.
LeesWoorden(letters)
De woorden het het bestand worden ingelezen.
Overeenkomsten(KeuzeWoord, TeRadenWoord)
Er wordt per letter gecontroleerd of de letter voorkomt in het onbekende woord TeRadenWoord, zo ja, op de juiste plaats, of op een andere plaats. Per letter wordt een getal geretourneerd:
- 0 indien de letter niet voorkomt in TeRadenWoord
- 1 indien de letter voorkomt in TeRadenWoord, maar niet op de juiste plaats
- 2 indien de letter voorkomt in TeRadenWoord, ook op de juiste plaats
Bij elkaar gaat het om een lijst van 5, 6 of 7 getallen.
ReduceerWoorden(RWL, signatuur, KeuzeWoord)
Elke keer als je op Ok drukt wordt gekeken naar het aantal mogelijke oplossingen (RWL). Deze procedure controleert voor welke woorden RaadWoord in RWL exact dezelfde signatuur wordt gedenereerd als TeRadenWoord. Er wordt een nieuwe lijst RWL2 opgesteld bestaande uit deze woorden.
CompressSignatuur(signatuur, letters)
We zetten de signatuur om in een getal tussen 0 en 3letters d.m.v. het omschrijven in het drietallig stelsel.
DeCompressSignatuur(N, letters)
Doet het omgekeerde van CompressSignatuur en zet een getal om in een signatuur.
In regel 73 begint het hoofdprogramma. Dit wordt uitgevoerd voor alle gevallen waarin we zijn geinteresseerd (5, 6 en 7 letters)
Variabelen
- 73: TopNR: Voor de verschillende aantal letters kan er een verschillend aantal voor de TopN worden ingevoerd.
- 74/75: letters: De variabele die in de loop wordt gebruikt.
- 76: topn:Het aantal woorden met een best Onderscheidend Vermogen dat wordt geprint.
- 78: t0: Wordt gebruikt om na te gaan hoeveel tijd deze stap kost. In regel 120 volgt t1.
- 79: b3expL: Wordt gebruikt om 3letters te bepalen.
- 82: SigNs: Getallenlijst van lengte 3letters, wordt gebruikt om alle woorden op basis van signatuur in verschillende deelverzamelingen op te delen. Uiteindelijk kan het Onderscheidend Vermogen worden bepaald als het maximum van de getallen in de getallenlijst. (Zie regel 101.)
- 85: TOPN: Dit wordt een lijst van topn woorden met de beste Onderscheidende Vermogens. Ieder element in TOP10 bestaat uit de combinatie van ov (het Onderscheidend Vermogen) en het woord zelf.
- 86: W: De woordenlijst van letters letters.
- 87: lw: Het aantal woorden in deze woordenlijst.
- 89: ovN: Wordt gebruikt om TOP10 van woorden met de beste Onderscheidende Vermogens niet te groot te laten worden.
- 90: p10: Omdat het uitvoeren van dit programma nogal wat tijd in beslag neemt wordt steeds na een tiende deel van de rekentijd een regel afgedrukt. Dit gebeurt in regel 93. Deze regel is momenteel uitgecommentarieerd.
- 91: cntcont: Er wordt gewerkt met deze variabele. Pas als het aantal woorden gelijk is aan deze variabele mag er een nieuwe regel worden afgedrukt.
- 92: cnt: teller, in dit geval van GekozenWoord (zie regel 90).
- 93: GekozenWoord: deze variabele wordt in de loop gebruikt als eerste te kiezen woord.
- 100: TeRadenWoord: deze variabele wordt in een loop binnen de EersteWoord-loop gebruikt om alle woorden langs te lopen als te raden woord.
- 101: signatuur: Wordt gebruikt om de signatuur van een woord t.o.v. een te raden woord te bepalen.
- 102: NS: De signatuur wordt omgezet in dit getal, zodat het kan worden toegepast op de getallenlijst.
- 104: ov: De signatuur wordt omgezet in dit getal, zodat het kan worden toegepast op de getallenlijst.
- 117: ovN: De waarde van de N-de wooord met beste Onderscheidende Vermogens. In de volgende regel worden alle regels uit TOPN verwijderd met woorden met een slechtere Onderscheidend Vermogen.
- 120: t1: De tijd wordt opnieuw gemeten. Het verschil met to geeft aan hoelang er is gerekend.
- 123: TopNWoorden: Hierin worden de woorden uit TOPN gekopieerd. Vervolgens kunnen de woorden naast elkaar worden geplaatst.
# Woordle 10 # Het programma om het beste eerste woord te bepalen import math import time import string import numpy import tkinter as tk import random import sys from tkinter import filedialog from tkinter import messagebox def LineReduce(line): return line[0:len(line)-1].upper() def LeesWoorden(letters): W = [] DIR = "./" FILE = "woorden" TXT = ".txt" dfin = DIR+FILE+str(letters)+TXT fin = open(dfin, "r") line = LineReduce(fin.readline()) ll = len(line) while ll == letters: W.append(line) line = LineReduce(fin.readline()) ll = len(line) fin.close() return W def Overeenkomsten(KeuzeWoord, TeRadenWoord): global letters orig = "#" subs = "@" signatuur = [0,0,0,0,0,0,0] AWOORD = [orig, orig, orig, orig, orig, orig, orig] ARADEN = [subs, subs, subs, subs, subs, subs, subs] for i in range(letters): AWOORD[i] = KeuzeWoord[i] ARADEN[i] = TeRadenWoord[i] if AWOORD[i] == ARADEN[i]: AWOORD[i] = orig ARADEN[i] = subs signatuur[i] = 2 for i in range(letters): if AWOORD[i] in ARADEN: j = ARADEN.index(AWOORD[i]) AWOORD[i] = orig ARADEN[j] = subs signatuur[i] = 1 return signatuur def ReduceerWoorden(RWL, signatuur, KeuzeWoord): RWL2 = [] for w in RWL: signatuur2 = Overeenkomsten(KeuzeWoord, w) if signatuur2 == signatuur: RWL2.append(w) return RWL2 def CompressSignatuur(signatuur, letters): ResS = 0 for i in range(letters): ResS = 3*ResS + signatuur[i] return ResS TopNR = [10, 5, 5] #for letters in [5]: # Dit bleek uiteindelijk de meest lastige te zijn for letters in [5,6,7]: topn = TopNR[letters-5] print("Letters =", letters) t0 = time.process_time() b3expL = 1 for i in range(letters): b3expL *= 3 SigNs = [] for i in range(b3expL): SigNs.append(0) TOPN = [] W = LeesWoorden(letters) lw = len(W) print("Aantal woorden =", lw) ovN = lw p10 = lw / 10 cntcont = p10 cnt = 0 for GekozenWoord in W: cnt += 1 if cnt > cntcont: #print(round(cnt*100/lw), "% gedaan") cntcont += p10 for i in range(b3expL): SigNs[i] = 0 for TeRadenWoord in W: signatuur = Overeenkomsten(GekozenWoord, TeRadenWoord) SigN = CompressSignatuur(signatuur,letters) SigNs[SigN] += 1 ov = max(SigNs) # Aanpassen van TOPN (t/m regel 115) if len(TOPN) < topn: TOPN.append((ov, GekozenWoord)) TOPN.sort() ovN = TOPN[-1][0] else: if ov <= ovN: TOPN.append((ov, GekozenWoord)) TOPN.sort() if ov < ovN: TOPN.pop() # Verwijderen van aantal regels in TOPN ovN = TOPN[topn-1][0] while TOPN[-1][0] > ovN: TOPN.pop() t1 = time.process_time() print("Tijd die nodig was voor de berekening:", round(t1-t0)) print("Lijst met best Onderscheidende Vermogens:") TopNWoorden = [] for top in TOPN: print(top) TopNWoorden.append(top[1]) print(TopNWoorden) print() print("Ready")
En hoe verder?
De grootste berekeningen hebben we achter de rug. Vanaf nu gaan we alleen nog maar met de woorden uit TopN verder! We herhalen steeds het volgende proces. Opnieuw moet ook het tweede woord een zo'n groot mogelijk onderscheidend vermogen hebben. In feite kun je niet spreken over één tweede woord, maar een hele lijst tweede woorden, horende bij elk van de $238$ verschillende mogelijkheden. En dan volgt het derde woord. Evenmin "het derde woord", maar een serie van $238 \times 238$ woorden. Om dit alles iteratief te kunnen uitvoeren construeren we een hele grote lijst met alle benodigde informatie. We noemen de lijst DubbeleWoordenLijst. Die naam behoeft een toelichting: Elk element in de lijst is opnieuw een lijst. Deze lijst bevat twee woordenlijsten, namelijk de lijst van gekozen woorden en de lijst van mogelijke oplossingen (van te raden woorden), gerelateerd aan de gekozen woorden (en de gerelateerde signaturen. Elke keer wordt er een element geselecteerd uit DubbeleWoordenLijst. Dan wordt hiermee een actie uitgevoerd, namelijk net zoals we met het eerste woord deden zoeken we naar een woord met best Onderscheidend Vermogen (wOV). Hiervoor gaan we de complete woordenlijst langs. Is een dergelijk woord gevonden, dan wordt dit woord geplaatst achter de lijst van gekozen woorden. De tweede lijst wordt m.b.v. wOV onderverdeeld in $238$ verscillende deellijsten. Alle (niet-lege) deellijsten worden toegevoegd aan DubbeleWoordenLijst, terwijl het oorspronkelijke element wordt verwijderd.
DubbeleWoordenLijst
Elk element van DubbeleWoordenLijst bevat vijf delen:
- Het eerste deel is een getal dat aangeeft hoeveel woorden deze optie omvat,
- het tweede deel is ook een getal dat het aantal beurten aangeeft dat je nog over hebt,
- het derde deel omvat de gebruikte woorden,
- het vierde deel omvat de signatuur (SignatuurCompress hierop toegepast) van de deelverzamelingen , en
- het laatste deel omvat alle woorden die nog zo te raden zijn.
In het bovenstaande programma hebben we al wOV1 bepaald. We berekenen signatuur = Overeenkomsten(wOV1, w), waarbij we met w door de gehele woordenlijst W gaan. Op grond van de $238$ verschillende signaturen ontstaan even zoveel verschillende deelverzamelingen (wDeelV) van W. Deze verzamelingen plaatsen we in DubbeleWoordenLijst. Een element ziet er als volgt uit:
$\{len(wDeelV), 5, [wOV1], [SigN1], wDeelV\}$
(hierin is SigN1 (gecomprimeerde) signatuur en wDeelV de woorden die voldoen aan de signatuur).Vervolgens gaan we met behulp van het kleinste onderscheidend vermogen een volgend woord kiezen en steeds het eerste element vervangen door een hele serie nieuwe elementen. Na elke stap sorteren we de lijst. Zo werken we van groot naar klein. De kleinste elementen (d.w.z. de elementen waarvoor nog één of twee mogelijke te raden woorden zijn, die kunnen worden overgeslagen, omdat voor deze elementen nog resp. één of twee beurten te noteren zijn.
Na verloop van tijd ziet een element van DubbeleWoordenLijst er als volgt uit:
$\{len(wDeelV), 6-k, [wOV1, wOV2, ..., wOVk], [SigN1, SigN2, ..., SigNk], wDeelV\}$
Als we daarmee klaar zijn dan bestaat DubbeleWoordenLijst uit len(W) elementen, en elk element bevat een wDeelV van één element, en eerder in het element van DubbeleWoordenLijst staat welke woorden er gekozen moeten worden om wDeelV te raden. Nu kunnen we de gehele DubbeleWoordenLijst langs gaan en bepalen we voor elk woord op welke manier de opeenvolgende woorden gekozen moeten worden. Dit kunnen we naar een bestand wegschrijven.
Versnelling
In eerste instantie willen we weten of we in $6$ beurten het woord kunnen raden, zo niet, dan zijn er $7$ en mogelijk $8$ beurten nodig. Dat betekent dat als er na één beurt vijf woorden in een wDeelV staan, dan is dat prima, hoewel we er nog effort in zouden kunnen steken om sneller alle woorden te raden. Evenzo na twee beurten resteren vier woorden, na drie beurten drie woorden, etc. Trouwens als er twee woorden nog over zijn in wDeelV, dan is het meest optimale dat je kunt doen is één van de twee woorden kiezen, en als je pech hebt de ander. Bij drie woorden kan je op zoek gaan naar een woord met onderscheidend vermogen $1$, (hetgeen meestal wel te vinden is. De versnelling levert een tijdswinst op van rond de 15%.
Toelichting op de onderstaande twee programma's
De procedures komen overeen met eerder beschreven programmatuur.
Variabelen
Wat betreft de benaming. Ik heb er veel moeite in gestoken om de benaming die betrekking hebben op een bepaald deel van het proces dezelfde of vergelijkbare benamingen mee te geven. De belangrijkste benamingen zijn
- DWL: is de afkorting van DubbeleWoordenLijst. Met deze extensie wordt aangegeven dat iets is gekopieerd uit de DubbeleWoordenLijst. Komt voor in wOVs_DWL (r. 157) en SigNs_DWL (r. 160).
- wOV: woord met (best of bijna beste) Onderscheidend Vermogen, woordenlijst, indien er een "s" achter staat. Varianten zijn wOV1_5 (r. 7), wOV1_6 (r. 8), wOV1_7 (r. 9), WOV1 (r. 10), WOV1_5 (r. 11), wOV1 (r. 93), (r. 7), (r. 7), (r. 7), (r. 7), (r. 7),
- 7: wOV1_5: Het TOP10-woord (met best Onderscheidend Vermogen) van 5 letters,
- 8: wOV1_6: Het TOP10-woord (met best Onderscheidend Vermogen)van 6 letters,
- 9: wOV1_7: Het TOP10-woord (met best Onderscheidend Vermogen)van 7 letters,
- 10: WOV1: Woordenlijst met best Onderscheidend Vermogen, bestaande uit woorden van lengte 5, 6 en 7.
- 11: WOV1_5: De Top10 van woorden van lengte 5 met beste Onderscheidend Vermogen, Het programma kan op een andere manier worden gebruikt.
- 89: DIR: De locatie waar de woordenlijsten staan,
- 90: VERBOSE: Als VERBOSE = 1, dan krijg je gaanderweg nog informatie. Dan zie je het programma bezig zijn.
- 91: BEREKENINGEN: Als BEREKENINGEN = 1, dan wordt er intensiever gerekend. Zie opmerking onder Versnelling
- 90: letters: Hier begint de loop met variabele letters.
- 91: t0: Wordt gebruikt om na te gaan hoeveel tijd deze stap kost. In regel 225 volgt t1.
- 93: wOV1: Het woord met best Onderscheidend Vermogen.
- 95: W: De woordenlijst van letters letters.
- 96: lw: Het aantal woorden in deze woordenlijst.
- 105: WRes: Lijst van resultaten voor alle woorden uit de woordenlijst. Bij elk woord worden twee lijsten geplaatst: wOVs en wDeelV (de gekozen woorden en de mogelijke te raden woorden),
- 108: b3expL: Wordt gebruikt om 3letters te bepalen.
- 111: wDeelVs: Bestaat uit een lijst van b3expL lijsten, waarin de te raden woorden onderverdeeld.
- 112: ExtwDeelVs: Dit is een uitgebreide (Extended) versie, waarbij meer informatie wordt opgeslagen. Dit gaat als volgt:
- Aantal te raden woorden (= len(wDeelV))
- De gerelateerde signatuur (SigN)
- De te raden woorden (wDeelV)
- 116: TeRadenWoord: deze variabele wordt in een loop binnen de wOV1-loop gebruikt om alle woorden langs te lopen als te raden woord.
- 117: signatuur: Wordt gebruikt om de signatuur van een woord t.o.v. een te raden woord te bepalen.
- 118: SigN: De signatuur wordt omgezet in dit getal, zodat het kan worden toegepast op de getallenlijst.
- 126: rest: Deze rest slaat op het aantal woorden waarvan nog bepaald moet worden in hoeveel beurten je het betreffende woord kunt raden. Steeds als er een klein aantal woorden overblijft (dat binnen de 6 beurten geraden kan worden), dan wordt van rest dat aantal woorden afgetrokken.
- 138: SigNs: Getallenlijst van lengte 3letters, wordt gebruikt om alle woorden op basis van signatuur in verschillende deelverzamelingen op te delen. Uiteindelijk kan het Onderscheidend Vermogen worden bepaald als het maximum van de getallen in de getallenlijst.
- 143: lwDeelV: aantal elementen van wDeelV, dit is de lijst met mogelijk te raden woorden, met bepaalde signatuur.
- 144: NieuwAantalBeurten: Aantal beurten dat nog een woord kan worden geraden. Dit is 6 - len(wOVs)
- 145: wOVs: De reeks woorden met best Onderscheidend Vermogen, of te wel de lijst gekozen woorden.
- 148: SigNs: De reeks opeenvolgende signaturen, gerelateerd aan wOVs.
- 151: wDeelV: dit is de lijst met mogelijk te raden woorden, met bepaalde signatuur. Niet te verwarren met wDeelVs. Dit is weer een lijst van (meerdere) wDeelV.
- 162: EB: Berekening van extra beurten.
# Woordl 13 # We kiezen hier de complete serie woorden. # We gaan wel uit van een eerste gekozen woord. # Centraal in het programma staat DubbeleWoordenLijst. Zie hierboven. # Programma nr 15 is vergelijkbaar # Hier controleren we uitsluitend of elk woord binnen de 6 beurten geraden kan worden. # TOPN-woorden uit eerdere programma: wOV1_5 = 'RATEL' wOV1_6 = 'SENIOR' # Vindt ik mooier dan SOIREE. Je bent vrij om het aan te passen. wOV1_7 = 'STRELEN' wOV1s = [wOV1_5, wOV1_6, wOV1_7] wOV1s_5 = ['LITER', 'ALTER', 'LATER', 'RATEL', 'TROEL', 'LATEI', 'OLIET', 'SALET', 'RANSE', 'REALO'] import math import time import string import numpy import tkinter as tk import random import sys from tkinter import filedialog from tkinter import messagebox def LineReduce(line): return line[0:len(line)-1].upper() def LeesWoorden(letters): W = [] DIR = "./" FILE = "woorden" TXT = ".txt" dfin = DIR+FILE+str(letters)+TXT fin = open(dfin, "r") line = LineReduce(fin.readline()) ll = len(line) while ll == letters: W.append(line) line = LineReduce(fin.readline()) ll = len(line) fin.close() return W def Overeenkomsten(KeuzeWoord, TeRadenWoord): global letters orig = "#" subs = "@" signatuur = [0,0,0,0,0,0,0] AWOORD = [orig, orig, orig, orig, orig, orig, orig] ARADEN = [subs, subs, subs, subs, subs, subs, subs] for i in range(letters): AWOORD[i] = KeuzeWoord[i] ARADEN[i] = TeRadenWoord[i] if AWOORD[i] == ARADEN[i]: AWOORD[i] = orig ARADEN[i] = subs signatuur[i] = 2 for i in range(letters): if AWOORD[i] in ARADEN: j = ARADEN.index(AWOORD[i]) AWOORD[i] = orig ARADEN[j] = subs signatuur[i] = 1 return signatuur def ReduceerWoorden(RWL, R, KeuzeWoord): RWL2 = [] for w in RWL: R2 = Overeenkomsten(KeuzeWoord, w) if R2 == R: RWL2.append(w) return RWL2 def CompressSignatuur(signatuur, letters): ResS = 0 for i in range(letters): ResS = 3*ResS + signatuur[i] return ResS def DeCompressSignatuur(ResS,letters): signatuur = [0,0,0,0,0,0,0] for i in range(letters): signatuur[letters-1-i] = ResS % 3 ResS = ResS // 3 return signatuur VERBOSE = 0 BEREKENINGEN = 0 # 0: al stoppen bij aantal beurten te gaan, 1: stoppen bij 2 (m.u.v. 1 beurt) letters = 5 W = LeesWoorden(letters) lw = len(W) print("Aantal woorden =", lw) for wOV1 in wOV1s_5: t0 = time.process_time() DubbeleWoordenLijst = [] print("Woord met optimaal Onderscheidend Vermogen:", wOV1) if VERBOSE == 1: popcnt = 0 print("*** VERBOSE staat aan") if BEREKENINGEN == 0: print("*** BEREKENINGEN staan op INTENSIEF") print("*** #while-loops * #woorden * #beurten te gaan * Gekozen Woorden * Rest ***") WRes = [] for i in range(lw): WRes.append([W[i], [], []]) b3expL = 1 for i in range(letters): b3expL *= 3 wDeelVs = [] ExtwDeelVs = [] for i in range(b3expL): wDeelVs.append([]) ExtwDeelVs.append([]) for TeRadenWoord in W: signatuur = Overeenkomsten(wOV1, TeRadenWoord) SigN = CompressSignatuur(signatuur,letters) wDeelVs[SigN].append(TeRadenWoord) # Kopieren van informatie van wDeelVs naar ExtwDeelVs for i in range(b3expL): ExtwDeelVs[i] = ((len(wDeelVs[i]), i, [])) for w in wDeelVs[i]: ExtwDeelVs[i][2].append(w) ExtwDeelVs.sort(reverse=True) rest = lw # Hieronder wordt DubbeleWoordenLijst klaargemaakt for i in range(b3expL): wDeelV = [] for w in ExtwDeelVs[i][2]: wDeelV.append(w) if BEREKENINGEN == 1: ondergrens = 2 else: ondergrens = 5 if ExtwDeelVs[i][0] > ondergrens: DubbeleWoordenLijst.append((ExtwDeelVs[i][0], 5, [wOV1], [ExtwDeelVs[i][1]], wDeelV)) elif ExtwDeelVs[i][0] > 0: rest -= ExtwDeelVs[i][0] for w in wDeelV: ix = W.index(w) WRes[ix][1].append(wOV1) for w2 in wDeelV: WRes[ix][2].append(w2) SigNs = [] # wordt gebruikt om de registratie van woorden in de deelverzamelingen bij te houden for i in range(b3expL): SigNs.append(0) # Hier begint een while-loop. Heel gevaarlijk, in principe niet eindig! while len(DubbeleWoordenLijst) > 0: lwDeelV_DWL = DubbeleWoordenLijst[0][0] NieuwAantalBeurten = DubbeleWoordenLijst[0][1] - 1 wOVs_DWL = [] for w in DubbeleWoordenLijst[0][2]: wOVs_DWL.append(w) SigNs_DWL = [] for w in DubbeleWoordenLijst[0][3]: SigNs_DWL.append(w) wDeelV_DWL = [] for w in DubbeleWoordenLijst[0][4]: wDeelV_DWL.append(w) # Alle informatie uit DubbeleWoordenLijst[0] is gekopieerd # Dit eerste element wordt verwijderd. DubbeleWoordenLijst.pop(0) if VERBOSE == 1: # Printopdracht wordt uitsluitend uitgevoerd als VERBOSE == 1 popcnt += 1 if popcnt % 20 == 0: if lwDeelV < 6: print("***", popcnt, "*", wDeelV_DWL, "*", NieuwAantalBeurten+1, "*", wOVs_DWL, "*", rest, "***") else: print("***", popcnt, "*", lwDeelV_DWL, "*", NieuwAantalBeurten+1, "*", wOVs_DWL, "*", rest, "***") if NieuwAantalBeurten == 0: EB = len(wOVs_DWL) + len(wDeelV_DWL) - 6 print("EXTRA BEURTEN:", EB, wOVs_DWL, wDeelV_DWL) else: # wk bepalen (alleen de beste, d.w.z. met kleinste onderscheidend vermogen) ov = lwDeelV_DWL wOVk_Definitief = "" for wOVk in W: # Het k-de woord in k-de beurt for i in range(b3expL): SigNs[i] = 0 for TeRadenWoord in wDeelV_DWL: signatuur = Overeenkomsten(wOVk, TeRadenWoord) SigN = CompressSignatuur(signatuur,letters) SigNs[SigN] += 1 mxov = max(SigNs) if mxov < ov: wOVk_Definitief = wOVk ov = mxov wOVs_DWL.append(wOVk_Definitief) wDeelVs = [] ExtwDeelVs = [] for i in range(b3expL): wDeelVs.append([]) ExtwDeelVs.append([]) for TeRadenWoord in wDeelV_DWL: signatuur = Overeenkomsten(wOVk_Definitief, TeRadenWoord) SigN = CompressSignatuur(signatuur,letters) wDeelVs[SigN].append(TeRadenWoord) for i in range(b3expL): ExtwDeelVs[i] = ((len(wDeelVs[i]), i, [])) for w in wDeelVs[i]: ExtwDeelVs[i][2].append(w) ExtwDeelVs.sort(reverse=True) for i in range(b3expL): if BEREKENINGEN == 1: if NieuwAantalBeurten == 1: ondergrens = 1 else: ondergrens = 2 else: ondergrens = NieuwAantalBeurten if ExtwDeelVs[i][0] > ondergrens: wDeelV = [] for w in ExtwDeelVs[i][2]: wDeelV.append(w) NieuwSigNs_DWL = [] for signatuur in SigNs_DWL: NieuwSigNs_DWL.append(signatuur) NieuwSigNs_DWL.append(ExtwDeelVs[i][1]) DubbeleWoordenLijst.append((ExtwDeelVs[i][0], NieuwAantalBeurten, wOVs_DWL, NieuwSigNs_DWL, wDeelV)) else: rest -= ExtwDeelVs[i][0] wDeelV = [] for w in ExtwDeelVs[i][2]: wDeelV.append(w) for w in wDeelV: ix = W.index(w) for wOV in wOVs_DWL: WRes[ix][1].append(wOV) for w2 in wDeelV: WRes[ix][2].append(w2) DubbeleWoordenLijst.sort(reverse=True) t1 = time.process_time() print("Tijd die nodig was voor de berekening:", round(t1-t0)) print("Rest:", rest) print("Ready")
Opmerking over bovenstaande programma
Dat was pech! Bij "LITER" zijn er twee woorden die NIET in 6 beurten kunnen worden geraden. Daarom toch nog maar andere woorden geprobeerd. Gelukkig: bij 'RATEL' kunnen alle woorden in 6 beurten worden geraden!
- EXTRA BEURTEN: 1 ['LITER', 'KANON', 'DUMPS', 'WAZIG', 'AFBAD'] ['HAZEN', 'VAZEN']
- EXTRA BEURTEN: 1 ['ALTER', 'OENIG', 'BARAK', 'CHIMP', 'AFDUW'] ['NEREN', 'VEREN']
- EXTRA BEURTEN: 1 ['LATER', 'OENIG', 'BARAK', 'CHIMP', 'AFDUW'] ['NEREN', 'VEREN']
- RATEL: Rest: 0
- EXTRA BEURTEN: 1 ['TROEL', 'DANSI', 'BERGE', 'CHIMP', 'BEVAK'] ['NEREN', 'WEREN']
- EXTRA BEURTEN: 1 ['LATEI', 'DRUMS', 'GEKAP', 'BEHUW', 'AFZAG'] ['KAKEN', 'NAKEN']
- en 1 ['LATEI', 'DRONK', 'OPNAM', 'BESJE', 'BEHUW'] ['NONEN', 'ZONEN']
- EXTRA BEURTEN: 1 ['OLIET', 'DRANK', 'PANGS', 'ZWAMP', 'AFBAD'] ['HAZEN', 'VAZEN']
- EXTRA BEURTEN: 1 ['SALET', 'KRUIP', 'AFREN', 'BEDAM', 'BEHUW'] ['TORST', 'VORST']
- en 1 ['SALET', 'KENDO', 'ROZIG', 'BOMPA', 'BEHUW'] ['NEREN', 'VEREN']
- en 1 ['SALET', 'KENDO', 'GRIJP', 'FARMS', 'BAHAI'] ['NOREN', 'VOREN']
- EXTRA BEURTEN: 1 ['RANSE', 'OREER', 'BALKT', 'CHIMP', 'DOVIG'] ['NEREN', 'WEREN']
- EXTRA BEURTEN: 1 ['REALO', 'TONDE', 'KETST', 'AFHAP', 'BEJAG'] ['MOKTE', 'WOKTE']
Toelichting bij LITER. Stel dat je HAZEN of VAZEN moet raden. De eerste 5 gekozen woorden woorden zijn: LITER, KANON, DUMPS, WAZIG, AFBAD. Maar dan zijn er nog twee woorden mogelijk: HAZEN en VAZEN. Dat wil NIET zeggen dat het onmogelijk is om met LITER te beginnen, maar mogelijk moet je i.p.v. KANON een ander woord kiezen. Dat laat ik graag over aan de lezer! Voor de programmatuur die nog hierop volgt is zoiets als het vervangen van KANON door een ander woord killing, omdat daardoor de programmatuur veel ingewikkelder wordt.
Ik had al gedachten voor een dergelijk programma, maar echt eenvoudig was het niet geworden. Mogelijk dat je er nog eens zelf naar kunt kijken!
Maar gelukkig was RATEL als enige in de TOP10 waarbij alle woorden WEL binnen 6 beurten konden worden berekend. Er zijn trouwens ook woorden BUITEN de TOP10 waarmee gestart kan worden.
Introductie voor het volgende programma
Hieronder volgt het programma dat een complete woordenlijst genereert, met per woord de woorden die je moet gebruiken om het betreffende woord te vinden. De bestanden zijn woordenoplossingen met 5, 6 of 7.
De opbouw van de woordenlijst is als volgt:
- woord zelf
- de reeks van gekozen woorden die tot dat woord leiden (of in een aantal gevallen twee woorden)
- ten slotte staan er één of twee woorden.
Voorbeeld
- TAART: RATEL, HAAKS, BOMIG, DWEEP, [TAART VAART ]
Ook worden hier de statistieken gemaakt. Als er twee woorden nog resteren, dan wordt één in de eerstvolgende beurt gebruikt en het andere in de beurt daarna.
Aangezien het volgende programma slechts op een paar plaatsen anders is vergeleken met het bovenstaande programma is er verder geen technische uitleg bij.
# Woordl 16 # We kiezen hier de complete serie woorden. # We gaan wel uit van een eerste gekozen woord. # Centraal in het programma staat DubbeleWoordenLijst. Zie hierboven. # Programma nr 13 is vergelijkbaar # Hier genereren we uitvoer per woord welke woorden er moeten worden gekozen. # TOPN-woorden uit eerdere programma: wOV1_5 = 'RATEL' wOV1_6 = 'SENIOR' # Vindt ik mooier dan SOIREE. Je bent vrij om het aan te passen. wOV1_7 = 'STRELEN' wOV1s = [wOV1_5, wOV1_6, wOV1_7] wOV1s_5 = ['LITER', 'ALTER', 'LATER', 'RATEL', 'TROEL', 'LATEI', 'OLIET', 'SALET', 'RANSE', 'REALO'] import math import time import string import numpy import tkinter as tk import random import sys from tkinter import filedialog from tkinter import messagebox def LineReduce(line): return line[0:len(line)-1].upper() def LeesWoorden(letters): W = [] DIR = "./" FILE = "woorden" TXT = ".txt" dfin = DIR+FILE+str(letters)+TXT fin = open(dfin, "r") line = LineReduce(fin.readline()) ll = len(line) while ll == letters: W.append(line) line = LineReduce(fin.readline()) ll = len(line) fin.close() return W def Overeenkomsten(KeuzeWoord, TeRadenWoord): global letters orig = "#" subs = "@" signatuur = [0,0,0,0,0,0,0] AWOORD = [orig, orig, orig, orig, orig, orig, orig] ARADEN = [subs, subs, subs, subs, subs, subs, subs] for i in range(letters): AWOORD[i] = KeuzeWoord[i] ARADEN[i] = TeRadenWoord[i] if AWOORD[i] == ARADEN[i]: AWOORD[i] = orig ARADEN[i] = subs signatuur[i] = 2 for i in range(letters): if AWOORD[i] in ARADEN: j = ARADEN.index(AWOORD[i]) AWOORD[i] = orig ARADEN[j] = subs signatuur[i] = 1 return signatuur def ReduceerWoorden(RWL, R, KeuzeWoord): RWL2 = [] for w in RWL: R2 = Overeenkomsten(KeuzeWoord, w) if R2 == R: RWL2.append(w) return RWL2 def CompressSignatuur(signatuur, letters): ResS = 0 for i in range(letters): ResS = 3*ResS + signatuur[i] return ResS def DeCompressSignatuur(ResS,letters): signatuur = [0,0,0,0,0,0,0] for i in range(letters): signatuur[letters-1-i] = ResS % 3 ResS = ResS // 3 return signatuur VERBOSE = 0 BEREKENINGEN = 1 # 0: al stoppen bij aantal beurten te gaan, 1: stoppen bij 2 (m.u.v. 1 beurt) #for letters in [5]: for letters in [5,6,7]: t0 = time.process_time() W = LeesWoorden(letters) lw = len(W) print("Letters =", letters, "Aantal woorden =", lw) DubbeleWoordenLijst = [] wOV1 = wOV1s[letters-5] print("Woord met optimaal Onderscheidend Vermogen:", wOV1) if VERBOSE == 1: popcnt = 0 print("*** VERBOSE staat aan") if BEREKENINGEN == 1: print("*** BEREKENINGEN staan op INTENSIEF") print("*** #while-loops * #woorden * #beurten te gaan * Gekozen Woorden * Rest ***") WRes = [] for i in range(lw): WRes.append([W[i], [], []]) b3expL = 1 for i in range(letters): b3expL *= 3 wDeelVs = [] ExtwDeelVs = [] for i in range(b3expL): wDeelVs.append([]) ExtwDeelVs.append([]) for TeRadenWoord in W: signatuur = Overeenkomsten(wOV1, TeRadenWoord) SigN = CompressSignatuur(signatuur,letters) wDeelVs[SigN].append(TeRadenWoord) # Kopieren van informatie van wDeelVs naar ExtwDeelVs for i in range(b3expL): ExtwDeelVs[i] = [len(wDeelVs[i]), i, []] for w in wDeelVs[i]: ExtwDeelVs[i][2].append(w) ExtwDeelVs.sort(reverse=True) rest = lw # Hieronder wordt DubbeleWoordenLijst klaargemaakt for i in range(b3expL): wDeelV = [] for w in ExtwDeelVs[i][2]: wDeelV.append(w) if BEREKENINGEN == 1: ondergrens = 2 else: ondergrens = 5 if ExtwDeelVs[i][0] > ondergrens: DubbeleWoordenLijst.append((ExtwDeelVs[i][0], 5, [wOV1], [ExtwDeelVs[i][1]], wDeelV)) elif ExtwDeelVs[i][0] > 0: rest -= ExtwDeelVs[i][0] for w in wDeelV: ix = W.index(w) WRes[ix][1].append(wOV1) for w2 in wDeelV: WRes[ix][2].append(w2) #print(w, WRes[ix]) SigNs = [] # wordt gebruikt om de registratie van woorden in de deelverzamelingen bij te houden for i in range(b3expL): SigNs.append(0) # Hier begint een while-loop. Heel gevaarlijk, in principe niet eindig! while len(DubbeleWoordenLijst) > 0: lwDeelV_DWL = DubbeleWoordenLijst[0][0] NieuwAantalBeurten = DubbeleWoordenLijst[0][1] - 1 wOVs_DWL = [] for w in DubbeleWoordenLijst[0][2]: wOVs_DWL.append(w) SigNs_DWL = [] for w in DubbeleWoordenLijst[0][3]: SigNs_DWL.append(w) wDeelV_DWL = [] for w in DubbeleWoordenLijst[0][4]: wDeelV_DWL.append(w) # Alle informatie uit DubbeleWoordenLijst[0] is gekopieerd # Dit eerste element wordt verwijderd. DubbeleWoordenLijst.pop(0) if VERBOSE == 1: # Printopdracht wordt uitsluitend uitgevoerd als VERBOSE == 1 popcnt += 1 if popcnt % 20 == 0: if lwDeelV_DWL < 6: print("***", popcnt, "*", wDeelV_DWL, "*", NieuwAantalBeurten+1, "*", wOVs_DWL, "*", rest, "***") else: print("***", popcnt, "*", lwDeelV_DWL, "*", NieuwAantalBeurten+1, "*", wOVs_DWL, "*", rest, "***") if NieuwAantalBeurten == 0: EB = len(wOVs_DWL) + len(wDeelV_DWL) - 6 print("EXTRA BEURTEN:", EB, wOVs_DWL, wDeelV_DWL) else: # wk bepalen (alleen de beste, d.w.z. met kleinste onderscheidend vermogen) ov = lwDeelV_DWL wOVk_Definitief = "" for wOVk in W: for i in range(b3expL): SigNs[i] = 0 for TeRadenWoord in wDeelV_DWL: signatuur = Overeenkomsten(wOVk, TeRadenWoord) SigN = CompressSignatuur(signatuur,letters) SigNs[SigN] += 1 mxov = max(SigNs) if mxov < ov: wOVk_Definitief = wOVk ov = mxov wOVs_DWL.append(wOVk_Definitief) wDeelVs = [] ExtwDeelVs = [] for i in range(b3expL): wDeelVs.append([]) ExtwDeelVs.append([]) for TeRadenWoord in wDeelV_DWL: signatuur = Overeenkomsten(wOVk_Definitief, TeRadenWoord) SigN = CompressSignatuur(signatuur,letters) wDeelVs[SigN].append(TeRadenWoord) for i in range(b3expL): ExtwDeelVs[i] = ([len(wDeelVs[i]), i, []]) for w in wDeelVs[i]: ExtwDeelVs[i][2].append(w) ExtwDeelVs.sort(reverse=True) # Sorteren is niet nodig for i in range(b3expL): if BEREKENINGEN == 1: if NieuwAantalBeurten == 1: ondergrens = 1 else: ondergrens = 2 else: ondergrens = NieuwAantalBeurten if ExtwDeelVs[i][0] > ondergrens: wDeelV = [] for w in ExtwDeelVs[i][2]: wDeelV.append(w) NieuwSigNs_DWL = [] for signatuur in SigNs_DWL: NieuwSigNs_DWL.append(signatuur) NieuwSigNs_DWL.append(ExtwDeelVs[i][1]) DubbeleWoordenLijst.append((ExtwDeelVs[i][0], NieuwAantalBeurten, wOVs_DWL, NieuwSigNs_DWL, wDeelV)) else: rest -= ExtwDeelVs[i][0] wDeelV = [] for w in ExtwDeelVs[i][2]: wDeelV.append(w) for w in wDeelV: ix = W.index(w) for wOV in wOVs_DWL: WRes[ix][1].append(wOV) for w2 in wDeelV: WRes[ix][2].append(w2) #print(w, WRes[ix]) DubbeleWoordenLijst.sort(reverse=True) t1 = time.process_time() print("Tijd die nodig was voor de berekening:", round(t1-t0)) print("Rest:", rest) # Wegschrijven van WO naar een bestand DIR = "./" # Mijn bestanden: FILEOUT = "woordenoplossingen" TXT = ".txt" dfout = DIR+FILEOUT + str(letters) + TXT fout = open(dfout, "w") STAT = [0,0,0,0,0,0,0] for i in range(lw): wres = WRes[i] fout.write(wres[0]) fout.write(": ") for w in wres[1]: fout.write(w) fout.write(", ") beurten = len(wres[1]) if len(wres[2]) == 1: if not (wres[1][-1] == wres[2][0]): beurten += 1 else: ix = wres[2].index(wres[0]) beurten = beurten + 1 + ix STAT[beurten] += 1 fout.write("[") for w in wres[2]: fout.write(w) fout.write(" ") fout.write("]\n\r") fout.close() print("Statistieken:") for ii in range(6): i = ii + 1 print("beurten:", i, STAT[i], "woorden") print("Rest:", rest) print("Ready")
Een simpel Woordl-Hack-programma
We gaan nu gebruik maken van de kennis dat je altijd binnen 6 beurten een woord kunt raden. Eerst volgt een simpel programmaatje met als invoer een aantal woorden die je hebt ingevoerd in het programma, vergezeld steeds van de bijbehorende signaturen. De uitvoer bestaat uit een rij woorden die nog mogelijk zijn. Je zult merken dat het nog een hele klus is om de invoer aan te leveren.
Als je even nadenkt hoe je het programma zou schrijven, dan denk ik dat je er zonder problemen wel achter komt. We maken een woordenlijst, met alle woorden. opeenvolgend keren selecteren we de deelverzameling die ook voldoet aan de volgende signatuur.
# Woordl 19 # Mini hack # De invoer is wel een gedoe, maar je kunt heel snel het volgende woord berekenen # Invoer: [("LASTER", [0,0,0,1,0,0]), ("KONING", [0,1,1,0,0,0]), # ("VLUCHT", [0,0,0,0,1,1]), ("OMHOOG", [0,0,1,0,2,0])] # Uitvoer: Aantal woorden en een lijst # Invoer: [("STRELEN", [0,0,0,0,1,0,0]), ("SCHOUWT", [0,0,0,0,2,0,0]), ("KLUISJE", [1,1,1,1,0,0,0]), # ("AFKLUIF", [1,0,1,1,2,2,0]), ("ZAADCEL", [0,2,0,0,0,0,2])] # Uitvoer: Aantal woorden en een lijst # Invoer: [("STRELEN", [0,0,1,1,0,0,1]), ("ENGERDS", [1,1,1,0,1,1,0]), ("GEBOORD", [1,2,0,0,0,1,1]), # ("ZWENKTE", [0,0,1,1,0,0,0])] # Uitvoer: Aantal woorden en een lijst import math import time import string import numpy import tkinter as tk import random import sys from tkinter import filedialog from tkinter import messagebox def LineReduce(line): return line[0:len(line)-1].upper() def LeesWoorden(letters): W = [] DIR = "./" FILE = "woorden" TXT = ".txt" dfin = DIR+FILE+str(letters)+TXT fin = open(dfin, "r") line = LineReduce(fin.readline()) ll = len(line) while ll == letters: W.append(line) line = LineReduce(fin.readline()) ll = len(line) fin.close() return W def Overeenkomsten(KeuzeWoord, TeRadenWoord): global letters orig = "#" subs = "@" R = [0,0,0,0,0,0,0] AWOORD = [orig, orig, orig, orig, orig, orig, orig] ARADEN = [subs, subs, subs, subs, subs, subs, subs] for i in range(letters): AWOORD[i] = KeuzeWoord[i] ARADEN[i] = TeRadenWoord[i] if AWOORD[i] == ARADEN[i]: AWOORD[i] = orig ARADEN[i] = subs R[i] = 2 for i in range(letters): if AWOORD[i] in ARADEN: j = ARADEN.index(AWOORD[i]) AWOORD[i] = orig ARADEN[j] = subs R[i] = 1 return R def ReduceerWoorden(WK, R, KeuzeWoord): WK2 = [] for w in WK: R2 = Overeenkomsten(KeuzeWoord, w) if R2 == R: WK2.append(w) return WK2 def CompressR(R,letters): Res = 0 for i in range(letters): Res = 3*Res + R[i] return Res def DeCompressR(Res,letters): R = [0,0,0,0,0,0,0] for i in range(letters): R[letters-1-i] = Res % 3 Res = Res // 3 return R DIR = "./" Invoer6A = [("LASTER", [0,0,0,1,0,0]), ("KONING", [0,1,1,0,0,0]), ("VLUCHT", [0,0,0,0,1,1]), ("OMHOOG", [0,0,1,0,2,0])] Invoer6B = [("SENIOR", [0,0,0,0,1,0]), ("KLACHT", [0,1,1,0,0,0]), ("OMVOUW", [1,0,0,0,0,0]), ("AFLOOP", [1,0,1,1,0,0])] Invoer6C = [("SENIOR", [0,1,1,1,0,1]), ("KIEREN", [0,2,0,1,2,2]), ("RIJDEN", [2,2,0,0,2,2]), ("BELANG", [0,1,0,0,1,0])] Invoer7A = [("STRELEN", [0,0,0,1,1,0,0]), ("KLEDING", [0,1,1,0,0,0,1]), ("BEZWAAR", [0,1,0,0,1,0,0]), ("GEROEMD", [1,0,0,1,2,0,0])] Invoer7B = [("STRELEN", [0,0,0,0,1,0,0]), ("SCHOUWT", [0,0,0,0,2,0,0]), ("KLUISJE", [1,1,1,1,0,0,0]), ("AFKLUIF", [1,0,1,1,2,2,0]), ("ZAADCEL", [0,2,0,0,0,0,2])] Invoer7C = [("STRELEN", [0,0,1,1,0,0,1]), ("ENGERDS", [1,1,1,0,1,1,0]), ("GEBOORD", [1,2,0,0,0,1,1]), ("ZWENKTE", [0,0,1,1,0,0,0])] Invoer7D = [("STRELEN", [1,0,0,0,0,0,0]), ("FANCLUB", [0,0,0,0,0,0,0]), ("OPSCHIK", [1,1,1,0,0,0,1])] for Invoer in [Invoer6A, Invoer6B, Invoer6C, Invoer7A, Invoer7B, Invoer7C, Invoer7D]: letters = len(Invoer[0][0]) print(letters) W = LeesWoorden(letters) lw = len(W) WO = [] for i in range(lw): WO.append([W[i], [], []]) mx10 = lw print("Aantal woorden =", lw) li = len(Invoer) for i in range(li): GekozenWoord = Invoer[i][0] RK = Invoer[i][1] ResK = CompressR(RK,letters) WNew = [] for TeRadenWoord in W: R = Overeenkomsten(GekozenWoord, TeRadenWoord) Res = CompressR(R,letters) if Res == ResK: WNew.append(TeRadenWoord) W = WNew print(GekozenWoord, len(W)) print(W) print("Ready")
Een uitgebreid Woordl-Hack-programma
Stel nu voor dat je zelf de opeenvolgende woorden gaat kiezen. De gebruiker hoeft alleen maar per keer aan te geven per letter welke kleur de betreffende letter krijgt. Volgens de volgorde die ook in programma 15 zat worden steeds de volgende woorden bepaald, en voila, altijd binnen 6 beurten!
Veel is een kopie van programma 6. Nieuw ishet gebruik van de drie knoppen op regel 7. De gebruiker doorloopt het getoonde woord en kleurt per letter zwart, geel en groen. Dit in relatie met "DEL", alle kleuringen verwijderen, en "BACK", alleen de laatste kleuring verwijderen.
Als de kleuringen naar wens zijn van de gebruiker, dan drukt hij op "OK". Vervolgens wordt het volgende woord berekend. De berekening die wordt uitgevoerd is helemaal vergelijkbaar met de berekening in de programma's 13 en 15. Niets nieuws!
Wat gebeurt er precies? Eerst worden de letters A t/m Z bijgewerkt, analoog zoals dat in programma 6 gebeurde. Daarna wordt SigN bepaald, de gecomprimeerde signatuur. We starten aanvankelijk met de complete woordenlijst, die noemen we wDeelV. We bepalen op grond van SigN een deelverzameling, en plaatsen die deelverzameling weer in wDeelV. Vervolgens moeten we een nieuw woord gaan kiezen, een wOVk_Definitief. Met wOVk doorlopen we de complete woordenlijst, en controleren we of het Onderscheidend Vermogen zo klein mogelijk is. Het woord wOVk, met kleinste Onderscheidend Vermogen wordt gekozen, en getoond.
Je zult merken dat de berekening aanvankelijk wat trager loopt, omdat meer berekeningen moeten worden uitgevoerd.
# WoordL 21 # In het geval van WoordL.py in Linux omgeving: #!/usr/bin/python3 # WoordL Het hack-programma. # De computer genereert steeds een woord # Voer voor elk woord per letter een kleur in (grijs, geel of groen) import math import string import numpy import tkinter as tk import random import sys from tkinter import filedialog from tkinter import messagebox def LineReduce(line): return line[0:len(line)-1].upper() def LeesWoorden(letters): W = [] DIR = "./" FILE = "woorden" TXT = ".txt" dfin = DIR+FILE+str(letters)+TXT fin = open(dfin, "r") line = LineReduce(fin.readline()) ll = len(line) while ll == letters: W.append(line) line = LineReduce(fin.readline()) ll = len(line) fin.close() return W def Overeenkomsten(KeuzeWoord, TeRadenWoord): global letters orig = "#" subs = "@" R = [0,0,0,0,0,0,0] AWOORD = [orig, orig, orig, orig, orig, orig, orig] ARADEN = [subs, subs, subs, subs, subs, subs, subs] for i in range(letters): AWOORD[i] = KeuzeWoord[i] ARADEN[i] = TeRadenWoord[i] if AWOORD[i] == ARADEN[i]: AWOORD[i] = orig ARADEN[i] = subs R[i] = 2 for i in range(letters): if AWOORD[i] in ARADEN: j = ARADEN.index(AWOORD[i]) AWOORD[i] = orig ARADEN[j] = subs R[i] = 1 return R def ReduceerWoorden(WK, R, KeuzeWoord): WK2 = [] for w in WK: R2 = Overeenkomsten(KeuzeWoord, w) if R2 == R: WK2.append(w) return WK2 def CompressSignatuur(signatuur,letters): SigN = 0 for i in range(letters): SigN = 3*SigN + signatuur[i] return SigN def FacePrint(face, C): face.config(text=C, font=(FontName, FontSize, 'bold'), fg = zwart) return def BackPrint(face, color): color = KLEUREN[color] face.config(bg = color) return def Back(): # Een letter terug global regel, letter, letters, wOVk_Definitief if letter > 0: letter -= 1 BackPrint(buttons[regel][letter], 4) return def Del(): # Regel verwijderen global regel, letter, letters while letter > 0: Back() return def New(): # Regel verwijderen Replay(letters) return def Color(x): # Plaatsen van kleur: 0 grijs, 1 geel, 2 groen global regel, letter, letters, Signatuur if letter < letters: BackPrint(buttons[regel][letter], x) Signatuur[letter] = x letter += 1 return def Ok(): # Controleren van Signatuur global regel, letter, letters, wOVk_Definitief, wDeelV, W, b3expL, Signatuur if letter == letters: # Eerst de reductie van het aantal woorden o.g.v. Signatuur toepassen SigNs = [] for i in range(b3expL): SigNs.append(0) wDeelV_Nieuw = [] for TeRadenWoord in wDeelV: signatuur = Overeenkomsten(wOVk_Definitief, TeRadenWoord) if signatuur == Signatuur: wDeelV_Nieuw.append(TeRadenWoord) wDeelV = wDeelV_Nieuw ov = len(wDeelV) FacePrint(buttons[10][7], str(ov)) # Bijwerken van de kleuren van A t/m Z for i in range(letters): w = ord(wOVk_Definitief[i]) - ord("A") y = w // 7 + ABCstartregel x = w % 7 ABCvalue[y-ABCstartregel][x] = max(ABCvalue[y-ABCstartregel][x], Signatuur[i]) BackPrint(buttons[y][x], ABCvalue[y-ABCstartregel][x]) regel += 1 letter = 0 if ov == 0: print("Geen oplossing") if letters == 5: wOVk_Definitief = "XXXXX" elif letters == 6: wOVk_Definitief = "XXXXXX" else: wOVk_Definitief = "XXXXXXX" elif ov < 3: wOVk_Definitief = wDeelV[0] else: # Nu nog het volgende woord bepalen (wOVk_Definitief) if letters == 5: wOVk_Definitief = "XXXXX" elif letters == 6: wOVk_Definitief = "XXXXXX" else: wOVk_Definitief = "XXXXXXX" for wOVk in W: for i in range(b3expL): SigNs[i] = 0 for TeRadenWoord in wDeelV: signatuur = Overeenkomsten(wOVk, TeRadenWoord) SigN = CompressSignatuur(signatuur,letters) SigNs[SigN] += 1 mxov = max(SigNs) if mxov < ov: wOVk_Definitief = wOVk ov = mxov for x in range(letters): FacePrint(buttons[regel][x], wOVk_Definitief[x]) return def Stat(): # Statistieken van gespeelde partijen return def Replay(NumLetters): # Reset van het spel global letters, regel, letter, ABCvalue, W, wOVk_Definitief, wDeelV, b3expL letters = NumLetters wOVk_Definitief = STARTWOORD[letters-5] for y in range(6): # eerste zes regels for x in range(letters): BackPrint(buttons[y][x], 4) # 4 = wit FacePrint(buttons[y][x], " ") for x in range(7 - letters): BackPrint(buttons[y][letters+x], 3) # 3 = grijs FacePrint(buttons[y][letters+x], " ") for x in range(letters): FacePrint(buttons[0][x], STARTWOORD[letters-5][x]) W = LeesWoorden(letters) lw = len(W) wDeelV = [] Signatuur = [0,0,0,0,0,0,0] for w in W: wDeelV.append(w) FacePrint(buttons[10][7], str(lw)) b3expL = 1 for i in range(letters): b3expL *= 3 ABCvalue = [[-1, -1, -1, -1, -1, -1, -1], [-1, -1, -1, -1, -1, -1, -1], [-1, -1, -1, -1, -1, -1, -1], [-1, -1, -1, -1, -1, 0, 0]] for x in range(7): for y in range(4): BackPrint(buttons[y+ABCstartregel][x], 3) Titel = "Hacken van WoordL "+str(letters)+" letters" root.title(Titel) regel = 0 letter = 0 return def ShowButtons(): for y in range (V+5): button_row = [] for x in range (H+1): if (x < letters) & (y < V): if y == 0: button = tk.Button(root, text=STARTWOORD[letters-5][x], width=2, height=1, bg=wit, fg=zwart, borderwidth = 1, font=(FontName, FontSize, 'bold')) else: button = tk.Button(root, text="", width=2, height=1, bg=wit, fg=zwart, borderwidth = 1, font=(FontName, FontSize, 'bold')) elif (y < V) & (letters <= x) & (x < H): button = tk.Button(root, text="", width=4, height=1, bg=grijs, fg=zwart, borderwidth = 1, font=(FontName, FontSize, 'bold')) elif (y == 0) & (x == H): button = tk.Button(root, text=TEKSTEN[y], width=4, height=1, bg=grijs, fg=zwart, borderwidth = 1, font=(FontName, FontSize, 'bold'), command=lambda y=y, x=x: Back()) elif (y == 1) & (x == H): button = tk.Button(root, text=TEKSTEN[y], width=4, height=1, bg=grijs, fg=zwart, borderwidth = 1, font=(FontName, FontSize, 'bold'), command=lambda y=y, x=x: Del()) elif (y == 2) & (x == H): button = tk.Button(root, text=TEKSTEN[y], width=4, height=1, bg=grijs, fg=zwart, borderwidth = 1, font=(FontName, FontSize, 'bold'), command=lambda y=y, x=x: Ok()) elif (y == 3) & (x == H): button = tk.Button(root, text=TEKSTEN[y], width=4, height=1, bg=grijs, fg=zwart, borderwidth = 1, font=(FontName, FontSize, 'bold'), command=lambda y=y, x=x: New()) elif (y == 4) & (x == H): button = tk.Button(root, text=TEKSTEN[y], width=4, height=1, bg=grijs, fg=zwart, borderwidth = 1, font=(FontName, FontSize, 'bold'), command=lambda y=y, x=x: Replay(5)) elif (y == 5) & (x == H): button = tk.Button(root, text=TEKSTEN[y], width=4, height=1, bg=grijs, fg=zwart, borderwidth = 1, font=(FontName, FontSize, 'bold'), command=lambda y=y, x=x: Replay(6)) elif (y == 6) & (x == H): button = tk.Button(root, text=TEKSTEN[y], width=4, height=1, bg=grijs, fg=zwart, borderwidth = 1, font=(FontName, FontSize, 'bold')) elif (y == 7) & (x == H): button = tk.Button(root, text=TEKSTEN[y], width=4, height=1, bg=grijs, fg=zwart, borderwidth = 1, font=(FontName, FontSize, 'bold'), command=lambda y=y, x=x: Replay(7)) elif (y == 8) & (x == H): button = tk.Button(root, text=TEKSTEN[y], width=4, height=1, bg=grijs, fg=zwart, borderwidth = 1, font=(FontName, FontSize, 'bold'), command=lambda y=y, x=x: Stat()) elif (y == 9) & (x == H): button = tk.Button(root, text=TEKSTEN[y], width=4, height=1, bg=grijs, fg=zwart, borderwidth = 1, font=(FontName, FontSize, 'bold'), command=lambda root=root: root.destroy()) elif (y == 10) & (x == H): button = tk.Button(root, text=str(lw), width=4, height=1, bg=grijs, fg=zwart, borderwidth = 1, font=(FontName, FontSize, 'bold')) elif (y == 6) & (x < 3): button = tk.Button(root, text="", width=4, height=1, bg=KLEUREN[x], fg=zwart, borderwidth = 1, font=(FontName, FontSize, 'bold'), command=lambda x=x: Color(x)) elif (y == 6) & (x >= 3) & (x < H): button = tk.Button(root, text="", width=4, height=1, bg=grijs, fg=zwart, borderwidth = 1, font=(FontName, FontSize, 'bold')) elif (y > 6) & (x < H): button = tk.Button(root, text=ABC[y-ABCstartregel][x], width=4, height=1, bg=grijs, fg=zwart, borderwidth = 1, font=(FontName, FontSize, 'bold')) button.grid(row=y, column=x, sticky="nsew") button_row.append(button) buttons.append(button_row) root.grid_rowconfigure(V+4, weight=1) root.grid_columnconfigure(H+1, weight=1) return root = tk.Tk() root.title("Hacken van WoordL 5 letters") STARTWOORD = ['RATEL', 'SENIOR', 'STRELEN'] TEKSTEN = ["Back", "Del", "OK", "New", "5", "6", "", "7", "Stat", "Exit", " "] # Nog een button kan worden toegevoegd OPLOSSING = ["G", "E", "R", "A", "D", "E", "N"] ABC = [["A", "B", "C", "D", "E", "F", "G"], ["H", "I", "J", "K", "L", "M", "N"], ["O", "P", "Q", "R", "S", "T", "U"], ["V", "W", "X", "Y", "Z", "", ""]] # kleuren grijs = "light gray" #3 wit = "white" #4 zwart = "black" #5 rood = "magenta" #6 blauw = "steelblue1" #7 KLEUREN = ["dim gray", "khaki1", "seagreen1", grijs, wit, zwart, rood, blauw] FontName = 'Helvetica' FontSize = '28' H = 7 V = 6 ABCstartregel = 7 regel = 0 letters = 5 letter = 0 Signatuur = [0,0,0,0,0,0,0] b3expL = 1 for i in range(letters): b3expL *= 3 wOVk_Definitief = STARTWOORD[0] W = LeesWoorden(letters) lw = len(W) wDeelV = [] for w in W: wDeelV.append(w) ABCvalue = [[-1, -1, -1, -1, -1, -1, -1], [-1, -1, -1, -1, -1, -1, -1], [-1, -1, -1, -1, -1, -1, -1], [-1, -1, -1, -1, -1, 0, 0]] buttons = [] ShowButtons() root.mainloop()
# Woordl 22 #Terug naar boven import math import numpy import tkinter as tk import random import sys root = tk.Tk() button = tk.Button(root, text="Exit", width=4, height=1, bg="light gray", fg="black", borderwidth = 1, font=('Helvetica', '32', 'bold'), command=lambda root=root: root.destroy()) button.grid(row=0, column=0, sticky="nsew") root.grid_rowconfigure(1, weight=1) root.grid_columnconfigure(1, weight=1) root.mainloop()
XEREN, YEREN, XEERT, YEERT
Hieronder zijn aan de woordenlijst van Open Taal 4 woorden toegevoegd: XEREN, YEREN, XEERT, YEERT. Is het mogelijk om alle woorden in $6$ beurten te raden?
# Woordl 24 # We kiezen hier de complete serie woorden. # Er zijn 4 woorden toegevoegd: XEREN, YEREN, XEERT, YEERT # We gaan wel uit van een eerste gekozen woord. # Centraal in het programma staat DubbeleWoordenLijst. Zie hierboven. # Programma nr 15 is vergelijkbaar # Hier controleren we uitsluitend of elk woord binnen de 6 beurten geraden kan worden. # TOPN-woorden uit eerdere programma: wOV1_5 = 'RATEL' wOV1_6 = 'SENIOR' # Vindt ik mooier dan SOIREE. Je bent vrij om het aan te passen. wOV1_7 = 'STRELEN' wOV1s = [wOV1_5, wOV1_6, wOV1_7] wOV1s_5 = ['LITER', 'ALTER', 'LATER', 'RATEL', 'TROEL', 'LATEI', 'OLIET', 'SALET', 'RANSE', 'REALO'] XEREN = ["XEREN", "YEREN", "XEERT", "YEERT"] import math import time import string import numpy import tkinter as tk import random import sys from tkinter import filedialog from tkinter import messagebox def LineReduce(line): return line[0:len(line)-1].upper() def LeesWoorden(letters): W = [] DIR = "./" FILE = "woorden" TXT = ".txt" dfin = DIR+FILE+str(letters)+TXT fin = open(dfin, "r") line = LineReduce(fin.readline()) ll = len(line) while ll == letters: W.append(line) line = LineReduce(fin.readline()) ll = len(line) fin.close() return W def Overeenkomsten(KeuzeWoord, TeRadenWoord): global letters orig = "#" subs = "@" signatuur = [0,0,0,0,0,0,0] AWOORD = [orig, orig, orig, orig, orig, orig, orig] ARADEN = [subs, subs, subs, subs, subs, subs, subs] for i in range(letters): AWOORD[i] = KeuzeWoord[i] ARADEN[i] = TeRadenWoord[i] if AWOORD[i] == ARADEN[i]: AWOORD[i] = orig ARADEN[i] = subs signatuur[i] = 2 for i in range(letters): if AWOORD[i] in ARADEN: j = ARADEN.index(AWOORD[i]) AWOORD[i] = orig ARADEN[j] = subs signatuur[i] = 1 return signatuur def ReduceerWoorden(RWL, R, KeuzeWoord): RWL2 = [] for w in RWL: R2 = Overeenkomsten(KeuzeWoord, w) if R2 == R: RWL2.append(w) return RWL2 def CompressSignatuur(signatuur, letters): ResS = 0 for i in range(letters): ResS = 3*ResS + signatuur[i] return ResS def DeCompressSignatuur(ResS,letters): signatuur = [0,0,0,0,0,0,0] for i in range(letters): signatuur[letters-1-i] = ResS % 3 ResS = ResS // 3 return signatuur VERBOSE = 0 BEREKENINGEN = 0 # 0: al stoppen bij aantal beurten te gaan, 1: stoppen bij 2 (m.u.v. 1 beurt) letters = 5 W = LeesWoorden(letters) for w in XEREN: W.append(w) lw = len(W) print("Aantal woorden =", lw) for wOV1 in wOV1s_5: t0 = time.process_time() DubbeleWoordenLijst = [] print("Woord met optimaal Onderscheidend Vermogen:", wOV1) if VERBOSE == 1: popcnt = 0 print("*** VERBOSE staat aan") if BEREKENINGEN == 0: print("*** BEREKENINGEN staan op INTENSIEF") print("*** #while-loops * #woorden * #beurten te gaan * Gekozen Woorden * Rest ***") WRes = [] for i in range(lw): WRes.append([W[i], [], []]) b3expL = 1 for i in range(letters): b3expL *= 3 wDeelVs = [] ExtwDeelVs = [] for i in range(b3expL): wDeelVs.append([]) ExtwDeelVs.append([]) for TeRadenWoord in W: signatuur = Overeenkomsten(wOV1, TeRadenWoord) SigN = CompressSignatuur(signatuur,letters) wDeelVs[SigN].append(TeRadenWoord) # Kopieren van informatie van wDeelVs naar ExtwDeelVs for i in range(b3expL): ExtwDeelVs[i] = ((len(wDeelVs[i]), i, [])) for w in wDeelVs[i]: ExtwDeelVs[i][2].append(w) ExtwDeelVs.sort(reverse=True) rest = lw # Hieronder wordt DubbeleWoordenLijst klaargemaakt for i in range(b3expL): wDeelV = [] for w in ExtwDeelVs[i][2]: wDeelV.append(w) if BEREKENINGEN == 1: ondergrens = 2 else: ondergrens = 5 if ExtwDeelVs[i][0] > ondergrens: DubbeleWoordenLijst.append((ExtwDeelVs[i][0], 5, [wOV1], [ExtwDeelVs[i][1]], wDeelV)) elif ExtwDeelVs[i][0] > 0: rest -= ExtwDeelVs[i][0] for w in wDeelV: ix = W.index(w) WRes[ix][1].append(wOV1) for w2 in wDeelV: WRes[ix][2].append(w2) SigNs = [] # wordt gebruikt om de registratie van woorden in de deelverzamelingen bij te houden for i in range(b3expL): SigNs.append(0) # Hier begint een while-loop. Heel gevaarlijk, in principe niet eindig! while len(DubbeleWoordenLijst) > 0: lwDeelV_DWL = DubbeleWoordenLijst[0][0] NieuwAantalBeurten = DubbeleWoordenLijst[0][1] - 1 wOVs_DWL = [] for w in DubbeleWoordenLijst[0][2]: wOVs_DWL.append(w) SigNs_DWL = [] for w in DubbeleWoordenLijst[0][3]: SigNs_DWL.append(w) wDeelV_DWL = [] for w in DubbeleWoordenLijst[0][4]: wDeelV_DWL.append(w) # Alle informatie uit DubbeleWoordenLijst[0] is gekopieerd # Dit eerste element wordt verwijderd. DubbeleWoordenLijst.pop(0) if VERBOSE == 1: # Printopdracht wordt uitsluitend uitgevoerd als VERBOSE == 1 popcnt += 1 if popcnt % 20 == 0: if lwDeelV < 6: print("***", popcnt, "*", wDeelV_DWL, "*", NieuwAantalBeurten+1, "*", wOVs_DWL, "*", rest, "***") else: print("***", popcnt, "*", lwDeelV_DWL, "*", NieuwAantalBeurten+1, "*", wOVs_DWL, "*", rest, "***") if NieuwAantalBeurten == 0: EB = len(wOVs_DWL) + len(wDeelV_DWL) - 6 print("EXTRA BEURTEN:", EB, wOVs_DWL, wDeelV_DWL) else: # wk bepalen (alleen de beste, d.w.z. met kleinste onderscheidend vermogen) ov = lwDeelV_DWL wOVk_Definitief = "" for wOVk in W: # Het k-de woord in k-de beurt for i in range(b3expL): SigNs[i] = 0 for TeRadenWoord in wDeelV_DWL: signatuur = Overeenkomsten(wOVk, TeRadenWoord) SigN = CompressSignatuur(signatuur,letters) SigNs[SigN] += 1 mxov = max(SigNs) if mxov < ov: wOVk_Definitief = wOVk ov = mxov wOVs_DWL.append(wOVk_Definitief) wDeelVs = [] ExtwDeelVs = [] for i in range(b3expL): wDeelVs.append([]) ExtwDeelVs.append([]) for TeRadenWoord in wDeelV_DWL: signatuur = Overeenkomsten(wOVk_Definitief, TeRadenWoord) SigN = CompressSignatuur(signatuur,letters) wDeelVs[SigN].append(TeRadenWoord) for i in range(b3expL): ExtwDeelVs[i] = ((len(wDeelVs[i]), i, [])) for w in wDeelVs[i]: ExtwDeelVs[i][2].append(w) ExtwDeelVs.sort(reverse=True) for i in range(b3expL): if BEREKENINGEN == 1: if NieuwAantalBeurten == 1: ondergrens = 1 else: ondergrens = 2 else: ondergrens = NieuwAantalBeurten if ExtwDeelVs[i][0] > ondergrens: wDeelV = [] for w in ExtwDeelVs[i][2]: wDeelV.append(w) NieuwSigNs_DWL = [] for signatuur in SigNs_DWL: NieuwSigNs_DWL.append(signatuur) NieuwSigNs_DWL.append(ExtwDeelVs[i][1]) DubbeleWoordenLijst.append((ExtwDeelVs[i][0], NieuwAantalBeurten, wOVs_DWL, NieuwSigNs_DWL, wDeelV)) else: rest -= ExtwDeelVs[i][0] wDeelV = [] for w in ExtwDeelVs[i][2]: wDeelV.append(w) for w in wDeelV: ix = W.index(w) for wOV in wOVs_DWL: WRes[ix][1].append(wOV) for w2 in wDeelV: WRes[ix][2].append(w2) DubbeleWoordenLijst.sort(reverse=True) t1 = time.process_time() print("Tijd die nodig was voor de berekening:", round(t1-t0)) print("Rest:", rest) print("Ready")
Conclusie t.a.v. XEREN, YEREN, XEERT en YEERT
XEREN, YEREN, XEERT, YEERT kunnen zonder probleem worden toegevoegd. Gebruik dan als eerste woord RATEL. De vraag is wat is het kleinste aantal woorden dat je moet toevoegen, zodat er woorden ontstaan die pas in zeven beurten kunnen worden gevonden. Dit is geen eenvoudige vraag in de algemeenheid. Voor deze programmatuur is de vraag eenvoudiger.