From 6a4e3620ea8c0b114c299b8d48df7beaaf90e574 Mon Sep 17 00:00:00 2001 From: el_anfr0003 Date: Mon, 9 Mar 2020 12:11:22 +0100 Subject: [PATCH 1/2] Sudoku & fix & rebase --- .../scala/eu/eyan/lister/FileLister3.scala | 281 +++++++++--------- .../scala/eu/eyan/sudoku/OrigSudoku.scala | 67 +++++ src/main/scala/eu/eyan/sudoku/Sudoku.scala | 102 ++++--- .../scala/eu/eyan/sudoku/UglySudoku.scala | 48 +++ .../scala/eu/eyan/sudoku/UglySudokuJava.java | 49 +++ .../eu/eyan/sudoku/UglySudokuJavaRefact.java | 68 +++++ 6 files changed, 428 insertions(+), 187 deletions(-) create mode 100644 src/main/scala/eu/eyan/sudoku/OrigSudoku.scala create mode 100644 src/main/scala/eu/eyan/sudoku/UglySudoku.scala create mode 100644 src/main/scala/eu/eyan/sudoku/UglySudokuJava.java create mode 100644 src/main/scala/eu/eyan/sudoku/UglySudokuJavaRefact.java diff --git a/src/main/scala/eu/eyan/lister/FileLister3.scala b/src/main/scala/eu/eyan/lister/FileLister3.scala index bc751c6..eb8434b 100644 --- a/src/main/scala/eu/eyan/lister/FileLister3.scala +++ b/src/main/scala/eu/eyan/lister/FileLister3.scala @@ -1,141 +1,142 @@ -package eu.eyan.lister - -import eu.eyan.util.swing.JPanelWithFrameLayout -import eu.eyan.log.Log -import eu.eyan.log.LogWindow -import eu.eyan.util.awt.clipboard.ClipboardPlus -import eu.eyan.util.io.FilePlus.FilePlusImplicit -import eu.eyan.util.java.net.URLPlus.URLImplicit -import eu.eyan.util.registry.RegistryPlus -import eu.eyan.util.scala.collection.TraversableOncePlus.TraversableOnceImplicit -import eu.eyan.util.string.StringPlus.StringPlusImplicit -import eu.eyan.util.swing.JButtonPlus.JButtonImplicit -import eu.eyan.util.swing.JCheckBoxPlus.JCheckBoxImplicit -import eu.eyan.util.swing.JFramePlus.JFramePlusImplicit -import eu.eyan.util.swing.JLabelPlus.JLabelImplicit -import eu.eyan.util.swing.JPanelWithFrameLayout -import eu.eyan.util.swing.JTextAreaPlus.JTextAreaImplicit -import eu.eyan.util.swing.JTextFieldPlus.JTextFieldPlusImplicit -import eu.eyan.util.swing.SwingPlus -import javax.swing.JFrame -import javax.swing.JOptionPane -import java.awt.Color -import java.awt.Desktop -import java.net.URI -import java.net.URLEncoder -import javax.swing.filechooser.FileSystemView -import java.io.File -import java.io.BufferedWriter -import java.io.FileWriter -import eu.eyan.util.scala.TryCatchFinally -import java.time.Instant -import eu.eyan.util.java.time.InstantPlus.InstantImplicit -import eu.eyan.util.compress.CompressPlus -import eu.eyan.util.compress.ZipPlus -import eu.eyan.util.compress.SevenZipPlus -import eu.eyan.util.scala.TryCatchFinallyClose -import eu.eyan.util.system.SystemPlus.KeepAlive -import eu.eyan.util.system.SystemPlus -import rx.lang.scala.subjects.BehaviorSubject -import eu.eyan.util.rx.lang.scala.ObservablePlus.ObservableImplicitBoolean -import javax.swing.SwingUtilities -import rx.lang.scala.Observable -import eu.eyan.util.rx.lang.scala.ObservablePlus -import eu.eyan.util.swing.panelbuilder.JPanelBuilder - -/** - * To list all the files on all drives. Also search inside the compressed files. - */ -object FileLister3 extends App { - - Log.activateDebugLevel - // TODO reimplement LogWindow.redirectOutAndErrToFiles("""C:\temp""") - LogWindow.redirectSystemOutAndErrToLogWindow - "1".println - "2".printlnErr - - val TITLE = "File Lister" - - - val targetText = BehaviorSubject[String] - val daysText = BehaviorSubject[String] - val ignoreText = BehaviorSubject[String] - val startButton = BehaviorSubject[String] - val isWorkInProgress = BehaviorSubject(false) - val counter = BehaviorSubject[Int] - - val panel = JPanelBuilder().withBorders.withSeparators.newColumn.newColumnFPG - .newRow.addLabel.text("Target file:") - .nextColumn.addTextField.text("C:\\temp\\AllDrivesFileList.txt").onTextChanged(targetText).remember("targetPath") - - .newRow.addLabel.text("Look into compressed files:") - .nextColumn.addCheckBox.text("").selected(false).onSelectionChanged(selected => {}).remember("lookIntoCompressedFiles") - - .newRow.addLabel.text("Execute after every x day:") - .nextColumn.addTextField.text("7").onTextChanged(daysText).remember("days") - - .newRow.addLabel.text("Ignore if contains:") - .nextColumn.addTextField.text("I:,N:,P:,T:,Y:").onTextChanged(ignoreText).remember("ignore") - - .newRow.addLabel.text("Start to list:") - .nextColumn.addButton.text("Start to list.").onActionEvent(startButton).enabled(isWorkInProgress.negate) - - .newRow.addLabel.text("Count").text(counter.map(_.toString)) - .getPanel - - val frame = new JFrame().title(TITLE).onCloseHide.iconFromChar('L', Color.CYAN).addToSystemTray().withComponent(panel) - .menuItem("File", "Exit", System.exit(0)) - .menuItem("Debug", "Open log window", LogWindow.show(panel)) - .menuItem("Debug", "Copy logs to clipboard", ClipboardPlus.copyToClipboard(LogWindow.getAllLogs)) - .menuItem("Debug", "Clear registry values", RegistryPlus.clear(TITLE)) - .menuItem("Help", "Write email", writeEmail) - .menuItem("Help", "About", alert("This is not an official tool, no responsibilities are taken. Use it at your own risk.")) - .packAndSetVisible - - ObservablePlus.toList(startButton, targetText.map(_.asFile)).map(_(1).asInstanceOf[File]).subscribe(startToList(_)) - def writeEmail = Desktop.getDesktop.mail(new URI("mailto:PVTools@eyan.eu?subject=FileLister&body=" + URLEncoder.encode(LogWindow.getAllLogs, "utf-8").replace("+", "%20"))) - def alert(msg: String) = JOptionPane.showMessageDialog(null, msg) - - var ct = 0 - - def startToList(target: File) = { - println("startToList " + target) - SwingPlus.runInWorker({ isWorkInProgress.onNext(true); listFilesOfAllDrives(target) }, isWorkInProgress.onNext(false)) - } - - def listFilesOfAllDrives(target: File) = SystemPlus.keepAlive { - ct = 0 - val fsv = FileSystemView.getFileSystemView - // val roots = List("""C:\DEV\projects\AndrisTools\src\test\resources\list""".asFile).map(_.fileTreeWithItself) - val roots = File.listRoots /*.filter(_.getAbsolutePath.containsAnyIgnoreCase(ignoreTextField.getText.split(",")))*/ .map(_.fileTreeWithItself) - if (target.exists) target.renameTo(target.extendFileNameWith("_old").generateNewNameIfExists()) - - TryCatchFinallyClose( - new BufferedWriter(new FileWriter(target)), - (bw: BufferedWriter) => roots.foreach(_.foreach(file => bw.write(logFile(file) + "\r\n"))), - t => Log.error(s"Error opening $target to write", t)) - - } - - val DT = "yyyyMMdd HHmmss" - def logFile(file: File) = { - ct += 1 - counter.onNext(ct) - val path = file.getAbsolutePath - val size = file.length - val lastModified = file.lastModified - val date = Instant.ofEpochMilli(lastModified) - - val zipContent = - if (file.isFile && file.endsWith("zip")) { - ZipPlus.listFiles(file).map(zip => formatFileLog(path + "\\" + zip.getName, zip.getLastModifiedTime.toInstant, zip.getSize)).mkString("\r\n", "\r\n", "") - } else if (file.isFile && file.endsWith("7z", "7zip")) { - SevenZipPlus.listFiles(file).map(zip => formatFileLog(path + "\\" + zip.getName, zip.getLastModifiedDate.toInstant, zip.getSize)).mkString("\r\n", "\r\n", "") - } else "" - - formatFileLog(path, date, size) + zipContent - } - - def formatFileLog(path: String, instant: Instant, size: Long) = f"${instant.toString(DT)} $size%10s $path" - +package eu.eyan.lister + +import eu.eyan.util.swing.JPanelWithFrameLayout +import eu.eyan.log.Log +import eu.eyan.log.LogWindow +import eu.eyan.util.awt.clipboard.ClipboardPlus +import eu.eyan.util.io.FilePlus.FilePlusImplicit +import eu.eyan.util.java.net.URLPlus.URLImplicit +import eu.eyan.util.registry.RegistryPlus +import eu.eyan.util.scala.collection.TraversableOncePlus.TraversableOnceImplicit +import eu.eyan.util.string.StringPlus.StringPlusImplicit +import eu.eyan.util.swing.JButtonPlus.JButtonImplicit +import eu.eyan.util.swing.JCheckBoxPlus.JCheckBoxImplicit +import eu.eyan.util.swing.JFramePlus.JFramePlusImplicit +import eu.eyan.util.swing.JLabelPlus.JLabelImplicit +import eu.eyan.util.swing.JPanelWithFrameLayout +import eu.eyan.util.swing.JTextAreaPlus.JTextAreaImplicit +import eu.eyan.util.swing.JTextFieldPlus.JTextFieldPlusImplicit +import eu.eyan.util.swing.SwingPlus +import javax.swing.JFrame +import javax.swing.JOptionPane +import java.awt.Color +import java.awt.Desktop +import java.net.URI +import java.net.URLEncoder +import javax.swing.filechooser.FileSystemView +import java.io.File +import java.io.BufferedWriter +import java.io.FileWriter +import eu.eyan.util.scala.TryCatchFinally +import java.time.Instant +import eu.eyan.util.java.time.InstantPlus.InstantImplicit +import eu.eyan.util.compress.CompressPlus +import eu.eyan.util.compress.ZipPlus +import eu.eyan.util.compress.SevenZipPlus +import eu.eyan.util.scala.TryCatchFinallyClose +import eu.eyan.util.system.SystemPlus.KeepAlive +import eu.eyan.util.system.SystemPlus +import rx.lang.scala.subjects.BehaviorSubject +import eu.eyan.util.rx.lang.scala.ObservablePlus.ObservableImplicitBoolean +import javax.swing.SwingUtilities +import rx.lang.scala.Observable +import eu.eyan.util.rx.lang.scala.ObservablePlus +import eu.eyan.util.swing.panelbuilder.JPanelBuilder +import eu.eyan.util.swing.panelbuilder.Click +import eu.eyan.util.swing.panelbuilder.Click + +/** + * To list all the files on all drives. Also search inside the compressed files. + */ +object FileLister3 extends App { + + Log.activateDebugLevel + // TODO reimplement LogWindow.redirectOutAndErrToFiles("""C:\temp""") + LogWindow.redirectSystemOutAndErrToLogWindow + "1".println + "2".printlnErr + + val TITLE = "File Lister" + + + val targetText = BehaviorSubject[String] + val daysText = BehaviorSubject[String] + val ignoreText = BehaviorSubject[String] + val startButton = BehaviorSubject[Click] + val isWorkInProgress = BehaviorSubject(false) + val counter = BehaviorSubject[Int] + + val panel = JPanelBuilder().withBorders.withSeparators.newColumn.newColumnFPG + .newRow.addLabel.text("Target file:") + .nextColumn.addTextField.text("C:\\temp\\AllDrivesFileList.txt").onTextChanged(targetText).remember("targetPath") + + .newRow.addLabel.text("Look into compressed files:") + .nextColumn.addCheckBox.text("").selected(false).onSelectionChanged(selected => {}).remember("lookIntoCompressedFiles") + + .newRow.addLabel.text("Execute after every x day:") + .nextColumn.addTextField.text("7").onTextChanged(daysText).remember("days") + + .newRow.addLabel.text("Ignore if contains:") + .nextColumn.addTextField.text("I:,N:,P:,T:,Y:").onTextChanged(ignoreText).remember("ignore") + + .newRow.addLabel.text("Start to list:") + .nextColumn.addButton.text("Start to list.").onAction(startButton).enabled(isWorkInProgress.negate) + + .newRow.addLabel.text("Count").text(counter.map(_.toString)) + .getPanel + + val frame = new JFrame().title(TITLE).onCloseHide.iconFromChar('L', Color.CYAN).addToSystemTray().withComponent(panel) + .menuItem("File", "Exit", System.exit(0)) + .menuItem("Debug", "Open log window", LogWindow.show(panel)) + .menuItem("Debug", "Copy logs to clipboard", ClipboardPlus.copyToClipboard(LogWindow.getAllLogs)) + .menuItem("Debug", "Clear registry values", RegistryPlus.clear(TITLE)) + .menuItem("Help", "Write email", writeEmail) + .menuItem("Help", "About", alert("This is not an official tool, no responsibilities are taken. Use it at your own risk.")) + .packAndSetVisible + + ObservablePlus.toList(startButton, targetText.map(_.asFile)).map(_(1).asInstanceOf[File]).subscribe(startToList(_)) + def writeEmail = Desktop.getDesktop.mail(new URI("mailto:PVTools@eyan.eu?subject=FileLister&body=" + URLEncoder.encode(LogWindow.getAllLogs, "utf-8").replace("+", "%20"))) + def alert(msg: String) = JOptionPane.showMessageDialog(null, msg) + + var ct = 0 + + def startToList(target: File) = { + println("startToList " + target) + SwingPlus.runInWorker({ isWorkInProgress.onNext(true); listFilesOfAllDrives(target) }, isWorkInProgress.onNext(false)) + } + + def listFilesOfAllDrives(target: File) = SystemPlus.keepAlive { + ct = 0 + val fsv = FileSystemView.getFileSystemView + // val roots = List("""C:\DEV\projects\AndrisTools\src\test\resources\list""".asFile).map(_.fileTreeWithItself) + val roots = File.listRoots /*.filter(_.getAbsolutePath.containsAnyIgnoreCase(ignoreTextField.getText.split(",")))*/ .map(_.fileTreeWithItself) + if (target.exists) target.renameTo(target.extendFileNameWith("_old").generateNewNameIfExists()) + + TryCatchFinallyClose( + new BufferedWriter(new FileWriter(target)), + (bw: BufferedWriter) => roots.foreach(_.foreach(file => bw.write(logFile(file) + "\r\n"))), + t => Log.error(s"Error opening $target to write", t)) + + } + + val DT = "yyyyMMdd HHmmss" + def logFile(file: File) = { + ct += 1 + counter.onNext(ct) + val path = file.getAbsolutePath + val size = file.length + val lastModified = file.lastModified + val date = Instant.ofEpochMilli(lastModified) + + val zipContent = + if (file.isFile && file.endsWith("zip")) { + ZipPlus.listFiles(file).map(zip => formatFileLog(path + "\\" + zip.getName, zip.getLastModifiedTime.toInstant, zip.getSize)).mkString("\r\n", "\r\n", "") + } else if (file.isFile && file.endsWith("7z", "7zip")) { + SevenZipPlus.listFiles(file).map(zip => formatFileLog(path + "\\" + zip.getName, zip.getLastModifiedDate.toInstant, zip.getSize)).mkString("\r\n", "\r\n", "") + } else "" + + formatFileLog(path, date, size) + zipContent + } + + def formatFileLog(path: String, instant: Instant, size: Long) = f"${instant.toString(DT)} $size%10s $path" } \ No newline at end of file diff --git a/src/main/scala/eu/eyan/sudoku/OrigSudoku.scala b/src/main/scala/eu/eyan/sudoku/OrigSudoku.scala new file mode 100644 index 0000000..c40a04e --- /dev/null +++ b/src/main/scala/eu/eyan/sudoku/OrigSudoku.scala @@ -0,0 +1,67 @@ +package eu.eyan.sudoku + +object OrigSudoku extends App { + case class Col(col: Int) { + def block = ((col - 1) / 3) * 3 + } + case class Row(row: Int) { + def block = ((row - 1) / 3) * 3 + } + + val cols = (1 to 9).map(Col(_)).toList + val rows = (1 to 9).map(Row(_)).toList + + case class Grid(private val grid: Array[Array[Int]]) { + override def toString = grid.map(_.mkString(" ")).mkString("\r\n") + "\r\n" + def get(row: Row, col: Col) = grid(row.row - 1)(col.col - 1) + def set(row: Row, col: Col, n: Int) = grid(row.row - 1)(col.col - 1) = n + } + + val grid = Grid(Array( + Array(5, 3, 0, 0, 7, 0, 0, 0, 0), + Array(6, 0, 0, 1, 9, 5, 0, 0, 0), + Array(0, 9, 8, 0, 0, 0, 0, 6, 0), + + Array(8, 0, 0, 0, 6, 0, 0, 0, 3), + Array(4, 0, 0, 8, 0, 3, 0, 0, 1), + Array(7, 0, 0, 0, 2, 0, 0, 0, 6), + + Array(0, 6, 0, 0, 0, 0, 2, 8, 0), + Array(0, 0, 0, 4, 1, 9, 0, 0, 5), + Array(0, 0, 0, 0, 8, 0, 0, 7, 9))) + + val grid2 = Grid(Array( + Array(5, 3, 0, 0, 7, 0, 0, 0, 0), + Array(6, 0, 0, 1, 9, 5, 0, 0, 0), + Array(0, 9, 8, 0, 0, 0, 0, 6, 0), + + Array(8, 0, 0, 0, 6, 0, 0, 0, 3), + Array(4, 0, 0, 8, 0, 3, 0, 0, 1), + Array(7, 0, 0, 0, 2, 0, 0, 0, 6), + + Array(0, 6, 0, 0, 0, 0, 2, 8, 0), + Array(0, 0, 0, 4, 1, 9, 0, 0, 5), + Array(0, 0, 0, 0, 8, 0, 0, 0, 0))) + + def possible(grid: Grid, row: Row, col: Col, n: Int): Boolean = { + val cb = cols.map(grid.get(row, _) == n) + val rb = rows.map(grid.get(_, col) == n) + val bb = (for (i <- 1 to 3; j <- 1 to 3) yield grid.get(Row(row.block + i), Col(col.block + j)) == n).toList + !(cb ++ rb ++ bb).contains(true) + } + + def solve(grid: Grid): Unit = { + for (row <- rows; col <- cols; if (grid.get(row, col) == 0)) { + for (n <- 1 to 9; if (possible(grid, row, col, n))) { + grid.set(row, col, n) + solve(grid) + grid.set(row, col, 0) + } + return + } + println(grid) + } + + solve(grid) + solve(grid2) +} \ No newline at end of file diff --git a/src/main/scala/eu/eyan/sudoku/Sudoku.scala b/src/main/scala/eu/eyan/sudoku/Sudoku.scala index e016012..f46475b 100644 --- a/src/main/scala/eu/eyan/sudoku/Sudoku.scala +++ b/src/main/scala/eu/eyan/sudoku/Sudoku.scala @@ -1,5 +1,7 @@ package eu.eyan.sudoku +import eu.eyan.util.time.Timer + object Sudoku extends App{ case class Col(col:Int){ def block = ((col-1)/3)*3 @@ -7,64 +9,70 @@ object Sudoku extends App{ case class Row(row:Int){ def block = ((row-1)/3)*3 } - val cols = (1 to 9).map(Col(_)).toList - val rows = (1 to 9).map(Row(_)).toList + case class Pos(col: Col, row: Row) + def cols = (1 to 9).map(Col(_)).toStream + def rows = (1 to 9).map(Row(_)).toStream case class Grid(private val grid: Array[Array[Int]]){ - override def toString = grid.map(_.mkString(" ")).mkString("\r\n")+"\r\n" - def get(row: Row, col: Col) = grid(row.row-1)(col.col-1) - def set(row: Row, col: Col, n: Int) = grid(row.row-1)(col.col-1) = n + override def toString = grid.map(_.mkString(" ")).mkString("\r\n")+"\r\n" + def get(pos:Pos) = grid(pos.row.row-1)(pos.col.col-1) + def set(pos:Pos, n: Int) = grid(pos.row.row-1)(pos.col.col-1) = n + def firstEmptyRow:Option[Row]={ + val rowIndex = grid.indexWhere(_.contains(0)) + if(rowIndex > -1) Option(Row(rowIndex+1)) + else Option.empty + } + def firstEmptyPos:Option[Pos] = firstEmptyRow.flatMap(row=> { + val colIndex = grid(row.row-1).indexWhere(_ == 0) + if(colIndex > -1) Option(Pos(Col(colIndex+1), row)) + else Option.empty + } ) } val grid = Grid(Array( - Array(5,3,0, 0,7,0, 0,0,0), - Array(6,0,0, 1,9,5, 0,0,0), - Array(0,9,8, 0,0,0, 0,6,0), - - Array(8,0,0, 0,6,0, 0,0,3), - Array(4,0,0, 8,0,3, 0,0,1), - Array(7,0,0, 0,2,0, 0,0,6), - - Array(0,6,0, 0,0,0, 2,8,0), - Array(0,0,0, 4,1,9, 0,0,5), - Array(0,0,0, 0,8,0, 0,7,9), + Array(5,3,0,0,7,0,0,0,0), + Array(6,0,0,1,9,5,0,0,0), + Array(0,9,8,0,0,0,0,6,0), + + Array(8,0,0,0,6,0,0,0,3), + Array(4,0,0,8,0,3,0,0,1), + Array(7,0,0,0,2,0,0,0,6), + + Array(0,6,0,0,0,0,2,8,0), + Array(0,0,0,4,1,9,0,0,5), + Array(0,0,0,0,8,0,0,7,9), )) - + val grid2 = Grid(Array( - Array(5,3,0, 0,7,0, 0,0,0), - Array(6,0,0, 1,9,5, 0,0,0), - Array(0,9,8, 0,0,0, 0,6,0), - - Array(8,0,0, 0,6,0, 0,0,3), - Array(4,0,0, 8,0,3, 0,0,1), - Array(7,0,0, 0,2,0, 0,0,6), - - Array(0,6,0, 0,0,0, 2,8,0), - Array(0,0,0, 4,1,9, 0,0,5), - Array(0,0,0, 0,8,0, 0,0,0), - )) + Array(5,3,0,0,7,0,0,0,0), + Array(6,0,0,1,9,5,0,0,0), + Array(0,9,8,0,0,0,0,6,0), + + Array(8,0,0,0,6,0,0,0,3), + Array(4,0,0,8,0,3,0,0,1), + Array(7,0,0,0,2,0,0,0,6), + + Array(0,6,0,0,0,0,2,8,0), + Array(0,0,0,4,1,9,0,0,5), + Array(0,0,0,0,8,0,0,0,0), + )) - def possible(grid: Grid, row:Row, col:Col, n:Int):Boolean={ - val cb = cols.map(grid.get(row, _)==n) - val rb = rows.map(grid.get(_, col)==n) - val bb = (for(i<- 1 to 3; j<- 1 to 3) yield grid.get(Row(row.block+i), Col(col.block+j))==n).toList - !(cb++rb++bb).contains(true) + def possible(grid: Grid, pos:Pos, n:Int):Boolean={ + def colContainsN = cols.map(col => grid.get(Pos(col, pos.row))==n) + def rowContainsN = rows.map(row => grid.get(Pos(pos.col, row))==n) + def blockContainsN = (for(i<- 1 to 3; j<- 1 to 3) yield grid.get(Pos(Col(pos.col.block+j),Row(pos.row.block+i)))==n).toStream + !(colContainsN #::: rowContainsN #::: blockContainsN).contains(true) } - def solve(grid:Grid):Unit = { - for(row<-rows;col <- cols;if(grid.get(row,col)==0)){ - for(n <- 1 to 9;if (possible(grid, row, col,n))){ - grid.set(row, col, n) + def solve(grid:Grid):Unit = + grid.firstEmptyPos.map{emptyPos => + for(n <- 1 to 9;if (possible(grid, emptyPos,n))){ + grid.set(emptyPos, n) solve(grid) - grid.set(row, col, 0) - } - return - } - println(grid) - } + grid.set(emptyPos, 0) + }}.orElse({println(grid); None}) - solve(grid) - solve(grid2) + Timer.time(solve(grid)) + Timer.time(solve(grid2)) } - \ No newline at end of file diff --git a/src/main/scala/eu/eyan/sudoku/UglySudoku.scala b/src/main/scala/eu/eyan/sudoku/UglySudoku.scala new file mode 100644 index 0000000..fe95d22 --- /dev/null +++ b/src/main/scala/eu/eyan/sudoku/UglySudoku.scala @@ -0,0 +1,48 @@ +package eu.eyan.sudoku + +import eu.eyan.util.time.Timer + +object UglySudoku extends App { + val grid = Array( + Array(5, 3, 0, 0, 7, 0, 0, 0, 0), + Array(6, 0, 0, 1, 9, 5, 0, 0, 0), + Array(0, 9, 8, 0, 0, 0, 0, 6, 0), + + Array(8, 0, 0, 0, 6, 0, 0, 0, 3), + Array(4, 0, 0, 8, 0, 3, 0, 0, 1), + Array(7, 0, 0, 0, 2, 0, 0, 0, 6), + + Array(0, 6, 0, 0, 0, 0, 2, 8, 0), + Array(0, 0, 0, 4, 1, 9, 0, 0, 5), + Array(0, 0, 0, 0, 8, 0, 0, 7, 9)) //00 + + def possible(row: Int, col: Int, n: Int): Boolean = { + for (i <- 1 to 9) if (grid(row - 1)(i - 1) == n) return false + for (i <- 1 to 9) if (grid(i - 1)(col - 1) == n) return false + val x0 = ((row - 1) / 3) * 3 + val y0 = ((col - 1) / 3) * 3 + for (i <- 1 to 3) + for (j <- 1 to 3) + if (grid(x0 + i - 1)(y0 + j - 1) == n) return false + return true + } + + def solve: Unit = { + for (row <- 1 to 9) + for (col <- 1 to 9) + if (grid(row - 1)(col - 1) == 0) { + for (n <- 1 to 9) + if (possible(row, col, n)) { + grid(row - 1)(col - 1) = n + solve + grid(row - 1)(col - 1) = 0 + } + return + } + println(grid.map(_.mkString(" ")).mkString("\r\n") + "\r\n") + } + + val st = System.currentTimeMillis + solve + println(System.currentTimeMillis - st + "ms") +} \ No newline at end of file diff --git a/src/main/scala/eu/eyan/sudoku/UglySudokuJava.java b/src/main/scala/eu/eyan/sudoku/UglySudokuJava.java new file mode 100644 index 0000000..da67cd0 --- /dev/null +++ b/src/main/scala/eu/eyan/sudoku/UglySudokuJava.java @@ -0,0 +1,49 @@ +package eu.eyan.sudoku; + +public class UglySudokuJava { + + static int[][] grid = + {{5, 3, 0, 0, 7, 0, 0, 0, 0}, {6, 0, 0, 1, 9, 5, 0, 0, 0}, {0, 9, 8, 0, 0, 0, 0, 6, 0}, + {8, 0, 0, 0, 6, 0, 0, 0, 3}, {4, 0, 0, 8, 0, 3, 0, 0, 1}, {7, 0, 0, 0, 2, 0, 0, 0, 6}, + {0, 6, 0, 0, 0, 0, 2, 8, 0}, {0, 0, 0, 4, 1, 9, 0, 0, 5}, {0, 0, 0, 0, 8, 0, 0, 7, 9}}; + + static boolean possible(int x, int y, int n) { + for (int i = 1; i < 10; i++) + if (grid[x - 1][i - 1] == n) + return false; + for (int i = 1; i < 10; i++) + if (grid[i - 1][y - 1] == n) + return false; + int x0 = ((x - 1) / 3) * 3; + int y0 = ((y - 1) / 3) * 3; + for (int i = 1; i < 4; i++) + for (int j = 1; j < 4; j++) + if (grid[x0 + i - 1][y0 + j - 1] == n) + return false; + + return true; + } + + static void solve() { + for (int i = 1; i < 10; i++) + for (int j = 1; j < 10; j++) + if (grid[i - 1][j - 1] == 0) { + for (int n = 1; n < 10; n++) + if (possible(i, j, n)) { + grid[i - 1][j - 1] = n; + solve(); + grid[i - 1][j - 1] = 0; + } + return; + } + for (int i = 1; i < 10; i++) + for (int j = 1; j < 10; j++) + System.out.print(" " + grid[i - 1][j - 1] + (j % 9 == 0 ? "\r\n" : "")); + } + + public static void main(String[] args) { + long st = System.currentTimeMillis(); + solve(); + System.out.println(System.currentTimeMillis() - st + "ms"); + } +} diff --git a/src/main/scala/eu/eyan/sudoku/UglySudokuJavaRefact.java b/src/main/scala/eu/eyan/sudoku/UglySudokuJavaRefact.java new file mode 100644 index 0000000..b0cc36c --- /dev/null +++ b/src/main/scala/eu/eyan/sudoku/UglySudokuJavaRefact.java @@ -0,0 +1,68 @@ +package eu.eyan.sudoku; + +/* +1. Lack of tests +2. Name not from domain +3. Name not expressing intent +4. Unnecessary if +5. Unnecessary else +6. Duplication of constant +7. Method does more than one thing +8. Primitive obsession +9. Feature envy +10. Method too long (more than 6 lines) +11. Too many parameters (more than 3) +12. Test: not unitary +13. Test: setup too complex +14. Test: unclear action +15. Test: more than one assert +16. Test: no assert +17. Test: too many paths + */ +public class UglySudokuJavaRefact { + + static int[][] grid = + {{5, 3, 0, 0, 7, 0, 0, 0, 0}, {6, 0, 0, 1, 9, 5, 0, 0, 0}, {0, 9, 8, 0, 0, 0, 0, 6, 0}, + {8, 0, 0, 0, 6, 0, 0, 0, 3}, {4, 0, 0, 8, 0, 3, 0, 0, 1}, {7, 0, 0, 0, 2, 0, 0, 0, 6}, + {0, 6, 0, 0, 0, 0, 2, 8, 0}, {0, 0, 0, 4, 1, 9, 0, 0, 5}, {0, 0, 0, 0, 8, 0, 0, 7, 9}}; + + static boolean possible(int x, int y, int n) { + for (int i = 1; i < 10; i++) + if (grid[x - 1][i - 1] == n) + return false; + for (int i = 1; i < 10; i++) + if (grid[i - 1][y - 1] == n) + return false; + int x0 = ((x - 1) / 3) * 3; + int y0 = ((y - 1) / 3) * 3; + for (int i = 1; i < 4; i++) + for (int j = 1; j < 4; j++) + if (grid[x0 + i - 1][y0 + j - 1] == n) + return false; + + return true; + } + + static void solve() { + for (int i = 1; i < 10; i++) + for (int j = 1; j < 10; j++) + if (grid[i - 1][j - 1] == 0) { + for (int n = 1; n < 10; n++) + if (possible(i, j, n)) { + grid[i - 1][j - 1] = n; + solve(); + grid[i - 1][j - 1] = 0; + } + return; + } + for (int i = 1; i < 10; i++) + for (int j = 1; j < 10; j++) + System.out.print(" " + grid[i - 1][j - 1] + (j % 9 == 0 ? "\r\n" : "")); + } + + public static void main(String[] args) { + long st = System.currentTimeMillis(); + solve(); + System.out.println(System.currentTimeMillis() - st + "ms"); + } +} From 23dc426a4283f5423fe25b9577d3f06864ab7f67 Mon Sep 17 00:00:00 2001 From: el_anfr0003 Date: Mon, 9 Mar 2020 12:35:02 +0100 Subject: [PATCH 2/2] filelister react --- src/main/scala/eu/eyan/lister/FileLister3.scala | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/scala/eu/eyan/lister/FileLister3.scala b/src/main/scala/eu/eyan/lister/FileLister3.scala index eb8434b..7365554 100644 --- a/src/main/scala/eu/eyan/lister/FileLister3.scala +++ b/src/main/scala/eu/eyan/lister/FileLister3.scala @@ -43,7 +43,8 @@ import rx.lang.scala.Observable import eu.eyan.util.rx.lang.scala.ObservablePlus import eu.eyan.util.swing.panelbuilder.JPanelBuilder import eu.eyan.util.swing.panelbuilder.Click -import eu.eyan.util.swing.panelbuilder.Click +import eu.eyan.util.rx.lang.scala.ObservablePlus.ObservableImplicitT +import eu.eyan.util.rx.lang.scala.subjects.BehaviorSubjectPlus.BehaviorSubjectImplicitT /** * To list all the files on all drives. Also search inside the compressed files. @@ -94,7 +95,7 @@ object FileLister3 extends App { .menuItem("Help", "About", alert("This is not an official tool, no responsibilities are taken. Use it at your own risk.")) .packAndSetVisible - ObservablePlus.toList(startButton, targetText.map(_.asFile)).map(_(1).asInstanceOf[File]).subscribe(startToList(_)) + startButton.takeLatestOf(targetText.map(_.asFile)).map(_.asInstanceOf[File]).subscribe(startToList(_)) def writeEmail = Desktop.getDesktop.mail(new URI("mailto:PVTools@eyan.eu?subject=FileLister&body=" + URLEncoder.encode(LogWindow.getAllLogs, "utf-8").replace("+", "%20"))) def alert(msg: String) = JOptionPane.showMessageDialog(null, msg)