University stuff.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358
  1. import java.io.File;
  2. import java.util.Scanner;
  3. import java.util.ArrayList;
  4. import java.util.List;
  5. class Brett {
  6. class Rute {
  7. int verdi;
  8. Rad rad;
  9. Kolonne kolonne;
  10. Boks boks;
  11. Brett brett;
  12. Rute neste = null;
  13. Rute(int verdi, Brett brett) {
  14. this.verdi = verdi;
  15. this.brett = brett;
  16. }
  17. public boolean harVerdi() {
  18. return verdi != -1;
  19. }
  20. public int[] finnAlleMuligeTall() {
  21. ArrayList<Integer> ugyldige = new ArrayList<>();
  22. for (Rute r: rad.ruter) {
  23. if (r.harVerdi()) {
  24. ugyldige.add(r.verdi);
  25. }
  26. }
  27. for (Rute r: kolonne.ruter) {
  28. if (r.harVerdi()) {
  29. ugyldige.add(r.verdi);
  30. }
  31. }
  32. for (Rute r: boks.ruter) {
  33. if (r.harVerdi()) {
  34. ugyldige.add(r.verdi);
  35. }
  36. }
  37. ArrayList<Integer> gyldige = new ArrayList<>();
  38. for (int i = 1; i <= brett.storrelse; ++i) {
  39. if (!ugyldige.contains(i)) {
  40. gyldige.add(i);
  41. }
  42. }
  43. int[] res = new int[gyldige.size()];
  44. for (int i = 0; i < res.length; ++i) {
  45. res[i] = gyldige.get(i);
  46. }
  47. return (int[])res;
  48. }
  49. /*
  50. * fyllUtDenneRuteOgResten
  51. * Jeg ga den et annet navn, som jeg mener er bedre. Maalet er ikke
  52. * aa fylle ut ruten, men aa finne losninger.
  53. */
  54. public List<List<Integer>> finnLosning() {
  55. // Bare skip denne ruten hvis vi har en verdi; ingenting aa lose
  56. if (harVerdi()) {
  57. List<List<Integer>> losninger;
  58. if (neste != null) {
  59. losninger = neste.finnLosning();
  60. } else {
  61. losninger = new ArrayList<>();
  62. losninger.add(new ArrayList<>());
  63. }
  64. for (List<Integer> losning: losninger) {
  65. losning.add(verdi);
  66. }
  67. return losninger;
  68. }
  69. List<List<Integer>> losninger = new ArrayList<>();
  70. int[] mulige = finnAlleMuligeTall();
  71. for (int mulig: mulige) {
  72. verdi = mulig;
  73. List<List<Integer>> nestesLosninger;
  74. if (neste == null) {
  75. nestesLosninger = new ArrayList<>();
  76. List<Integer> l = new ArrayList<Integer>();
  77. nestesLosninger.add(l);
  78. } else {
  79. nestesLosninger = neste.finnLosning();
  80. }
  81. for (List<Integer> l: nestesLosninger) {
  82. l.add(verdi);
  83. losninger.add(l);
  84. }
  85. }
  86. verdi = -1;
  87. return losninger;
  88. }
  89. }
  90. class Kolonne {
  91. private int index = 0;
  92. Rute[] ruter;
  93. Kolonne(int storrelse) {
  94. ruter = new Rute[storrelse];
  95. }
  96. public void settInn(Rute r) {
  97. ruter[index++] = r;
  98. }
  99. }
  100. class Rad {
  101. private int index = 0;
  102. Rute[] ruter;
  103. Rad(int storrelse) {
  104. ruter = new Rute[storrelse];
  105. }
  106. public void settInn(Rute r) {
  107. ruter[index++] = r;
  108. }
  109. }
  110. class Boks {
  111. private int index = 0;
  112. Rute[] ruter;
  113. int bredde;
  114. int hoyde;
  115. Boks(int bredde, int hoyde) {
  116. this.bredde = bredde;
  117. this.hoyde = hoyde;
  118. ruter = new Rute[bredde * hoyde];
  119. }
  120. public void settInn(Rute r) {
  121. ruter[index++] = r;
  122. }
  123. }
  124. File fil;
  125. int raderPerBoks;
  126. int kolonnerPerBoks;
  127. int antallBokserX;
  128. int antallBokserY;
  129. int storrelse;
  130. Rute[] ruter;
  131. Rad[] rader;
  132. Kolonne[] kolonner;
  133. Boks[] bokser;
  134. Brett(File fil) throws Exception {
  135. this.fil = fil;
  136. read();
  137. }
  138. public SudokuBeholder los() {
  139. List<List<Integer>> losninger = ruter[0].finnLosning();
  140. SudokuBeholder sb = new SudokuBeholder(this);
  141. for (List<Integer> losning: losninger) {
  142. SudokuBeholder.Losning l = new SudokuBeholder.Losning();
  143. for (int i = losning.size() - 1; i >= 0; --i) {
  144. Rute r = ruter[losning.size() - 1 - i];
  145. l.leggTil(losning.get(i), r.harVerdi());
  146. }
  147. sb.leggTil(l);
  148. }
  149. return sb;
  150. }
  151. public SudokuBeholder.Losning tilLosning() {
  152. SudokuBeholder.Losning losning = new SudokuBeholder.Losning();
  153. for (Rute r: ruter) {
  154. losning.leggTil(r.verdi, r.harVerdi());
  155. }
  156. return losning;
  157. }
  158. public void print() throws Exception {
  159. int x = 0;
  160. int y = 1;
  161. int modX = storrelse / antallBokserX;
  162. int modY = storrelse / antallBokserY;
  163. for (Rute r: ruter) {
  164. if (x % modX == 0 && x != 0) {
  165. System.out.print("|");
  166. }
  167. if (r.harVerdi()) {
  168. System.out.print(toChar(r.verdi));
  169. } else {
  170. System.out.print(" ");
  171. }
  172. x += 1;
  173. if (x >= storrelse) {
  174. x = 0;
  175. if (y % modY == 0 && y < storrelse) {
  176. System.out.println("");
  177. for (int i = 0; i < storrelse; ++i) {
  178. if (i % modX == 0 && i != 0) {
  179. System.out.print("+");
  180. }
  181. System.out.print("-");
  182. }
  183. }
  184. System.out.println("");
  185. y += 1;
  186. }
  187. }
  188. }
  189. public int toInt(char c) throws Exception {
  190. if (c == '.') {
  191. return -1;
  192. } else if (c >= '1' && c <= '9') {
  193. return (int)c - 49 + 1;
  194. } else if (c >= 'A' && c <= 'Z') {
  195. return (int)c - 65 + 10;
  196. } else if (c == '@') {
  197. return 36;
  198. } else if (c == '#') {
  199. return 37;
  200. } else if (c == '&') {
  201. return 38;
  202. } else if (c >= 'a' && c <= 'z') {
  203. return c - 97 + 39;
  204. } else {
  205. throw new IllegalArgumentException();
  206. }
  207. }
  208. public char toChar(int c) throws Exception {
  209. if (c == -1) {
  210. return '.';
  211. } else if (c >= 1 && c <= 9) {
  212. return (char)(c + 49 -1);
  213. } else if (c >= 10 && c <= 35) {
  214. return (char)(c + 65 - 10);
  215. } else if (c == 36) {
  216. return '@';
  217. } else if (c == 37) {
  218. return '#';
  219. } else if (c == 38) {
  220. return '&';
  221. } else if (c >= 39 && c <= 64) {
  222. return (char)(c + 97 - 39);
  223. } else {
  224. throw new IllegalArgumentException();
  225. }
  226. }
  227. private void read() throws Exception {
  228. Scanner s = new Scanner(fil);
  229. try {
  230. raderPerBoks = Integer.parseInt(s.nextLine());
  231. kolonnerPerBoks = Integer.parseInt(s.nextLine());
  232. } catch (Exception ex) {
  233. throw new Exception("Filen starter ikke med dimensjoner!");
  234. }
  235. try {
  236. storrelse = raderPerBoks * kolonnerPerBoks;
  237. antallBokserX = storrelse / kolonnerPerBoks;
  238. antallBokserY = storrelse / raderPerBoks;
  239. } catch (Exception ex) {
  240. throw new Exception("Filen inneholder feil!");
  241. }
  242. if (storrelse > 64) {
  243. throw new Exception("For stort brett!");
  244. }
  245. ruter = new Rute[storrelse * storrelse];
  246. // Les inn alle ruter
  247. int i = 0;
  248. Rute forrige = null;
  249. for (int y = 0; y < storrelse; ++y) {
  250. if (!s.hasNextLine()) {
  251. throw new Exception("For faa rader!");
  252. }
  253. char[] rad = s.nextLine().toCharArray();
  254. if (rad.length > storrelse) {
  255. throw new Exception("For mange kolonner i rad "+(y+1)+"!");
  256. }
  257. for (int x = 0; x < storrelse; ++x) {
  258. char c;
  259. try {
  260. c = rad[x];
  261. } catch (ArrayIndexOutOfBoundsException ex) {
  262. throw new Exception("For faa kolonner i rad "+(y+1)+"!");
  263. }
  264. Rute r = new Rute(toInt(c), this);
  265. if (forrige != null) {
  266. forrige.neste = r;
  267. }
  268. ruter[i++] = r;
  269. forrige = r;
  270. }
  271. }
  272. if (s.hasNextLine()) {
  273. throw new Exception("For mange rader!");
  274. }
  275. // Opprett rader, kolonner, og bokser
  276. // (obligens `void opprettDatastruktur()`, jeg mener det ikke gir mening
  277. // aa ha det som en egen metode, da det vil skje hvis og bare hvis vi
  278. // leser inn ny informasjon)
  279. rader = new Rad[storrelse];
  280. kolonner = new Kolonne[storrelse];
  281. bokser = new Boks[storrelse];
  282. for (i = 0; i < storrelse; ++i) {
  283. rader[i] = new Rad(storrelse);
  284. kolonner[i] = new Kolonne(storrelse);
  285. bokser[i] = new Boks(kolonnerPerBoks, raderPerBoks);
  286. }
  287. int x = 0;
  288. int y = 0;
  289. for (Rute r: ruter) {
  290. r.rad = rader[y];
  291. rader[y].settInn(r);
  292. r.kolonne = kolonner[x];
  293. kolonner[x].settInn(r);
  294. int boxx = (x / kolonnerPerBoks) % antallBokserX;
  295. int boxy = (y / raderPerBoks) % antallBokserY;
  296. int boxi = boxx + (boxy * antallBokserX);
  297. bokser[boxi].settInn(r);
  298. r.boks = bokser[boxi];
  299. x += 1;
  300. if (x >= storrelse) {
  301. x = 0;
  302. y += 1;
  303. }
  304. }
  305. }
  306. }