import java.util.*; // // Primer stroja za igro Wordle. Stroj vzdržuje množico slovarskih besed, ki // so združljive z vsemi dosedanjimi omejitvami, in vsakokrat izbere ``prvo'' // besedo iz množice (tj. tisto, ki jo vrne iterator ob prvem klicu metode // next). // public class Tekm_12345678 implements Stroj { // izhodiščna množica besed // (nastavi se ob inicializaciji, potem pa se ne spreminja) private Set izhodiscneBesede; // množica besed, ki še ustreza omejitvam private Set besede; // nazadnje izbrana beseda private String zadnjaIzbira; // // Nastavi izhodiščno množico besed. // @Override public void inicializiraj(Set besede) { this.izhodiscneBesede = new TreeSet<>(besede); } // // Na podlagi podanega odziva na prejšnjo izbiro vrne naslednjo izbiro. // // odziv[i]: odziv ('+', 'o' ali '-') na i-to črko prejšnje izbire; // null, ko ogrodje zahteva prvo izbiro. // @Override public String poteza(List odziv) { if (odziv == null) { // Prva ``poteza'': ponastavi množico besed. this.besede = new TreeSet<>(this.izhodiscneBesede); } else { if (vseEnako(odziv, '+')) { // Konec, naša zadnja izbira je bila pravilna! return null; } if (this.besede.isEmpty()) { // Množica besed je prazna, kljub temu da besede še nismo // uganili. throw new RuntimeException("Nekaj močno smrdi!"); } // Iz množice odstranimo vse besede, ki niso združljive z odzivom // na zadnjo izbiro. Set odstrani = new TreeSet<>(); for (String beseda: this.besede) { if (!jeZdruzljiva(beseda, this.zadnjaIzbira, odziv)) { odstrani.add(beseda); } } this.besede.removeAll(odstrani); } // Vrnemo ``prvo'' besedo iz množice (tj. prvo, ki jo vrne iterator). return this.zadnjaIzbira = this.besede.iterator().next(); } // // Vrne true natanko v primeru, če so vsi elementi podanega seznama enaki // podanemu elementu. // private static boolean vseEnako(List seznam, T element) { return seznam.stream().allMatch(e -> e.equals(element)); } // // Vrne true natanko v primeru, če je beseda združljiva s // podanim odzivom na podano izbiro. // private static boolean jeZdruzljiva(String beseda, String izbira, List odziv) { int n = odziv.size(); // Izdelamo seznam znakov besed in // (nizi so nespremenljivi, seznami pa niso). // (npr. "znanka" -> ['z', 'n', 'a', 'n', 'k', 'a']. List crkeBesede = new ArrayList<>(); List crkeIzbire = new ArrayList<>(); for (int i = 0; i < n; i++) { crkeBesede.add(beseda.charAt(i)); crkeIzbire.add(izbira.charAt(i)); } // Preverimo, ali za vse i-je, pri katerih je odziv[i] == '+', // velja beseda[i] == izbira[i]. for (int i = 0; i < n; i++) { if (odziv.get(i) == '+') { if (crkeBesede.get(i) != crkeIzbire.get(i)) { return false; } // Označimo, da smo ta položaj že pregledali // (to je pomembno za pravilno obravnavo odzivov 'o'). crkeBesede.set(i, '#'); crkeIzbire.set(i, '_'); } } // Preverimo, ali za vse i-je, pri katerih je odziv[i] == 'o', // velja, da vsebuje črko izbira[i], a ne na indeksu . // Vsako tako črko beseda je treba povezati z eno samo črko // besede . for (int ixIzbira = 0; ixIzbira < n; ixIzbira++) { if (odziv.get(ixIzbira) == 'o') { char crka = crkeIzbire.get(ixIzbira); int ixBeseda = crkeBesede.indexOf(crka); if (ixBeseda < 0 || crkeBesede.get(ixIzbira) == crka) { return false; } // Označimo, da smo pripadajoča položaja že pregledali. crkeBesede.set(ixBeseda, '#'); crkeIzbire.set(ixIzbira, '_'); } } // Preverimo, ali za vse i-je, pri katerih je odziv[i] == '-', // velja, da ne vsebuje črke izbira[i]. for (int i = 0; i < n; i++) { if (odziv.get(i) == '-' && crkeBesede.indexOf(crkeIzbire.get(i)) >= 0) { return false; } } return true; } }