Skip to content

Instantly share code, notes, and snippets.

@foxtran
Created January 21, 2024 12:19
Show Gist options
  • Save foxtran/632a121d444a89dcba5c49d17202cddb to your computer and use it in GitHub Desktop.
Save foxtran/632a121d444a89dcba5c49d17202cddb to your computer and use it in GitHub Desktop.
module helper_mod {
public i32 sudctoi(c8 c) {
consteval i32 C0 = i32('0'), C9 = i32('9'), CA = i32('A'), CZ = i32('Z')
if (irepr >= C0 .and. irepr <= C9) {
return i32(c) - C0
} else if (irepr >= CA .and. irepr <= CZ) {
return i32(c) - CA + 10
} else {
return 0
}
}
public c8 itosudc(i32 i)
if (i == 0) {
return '.'
} else if (i < 10) {
return c8(i+i32('0'))
} else {
return c8(i-10+i32('A'))
}
}
}
module sudoku_solver {
public type sudoku_solver_t {
i32 n, n2
allocatable i32[:,:] field
allocatable i32[:,:,:] tfield
none load_from_file(File)
bool next()
none print()
}
sudoku_solver_t.load_from_file(File LU) {
use helper_mod -> global, only: sudctoi
allocatable c8[:] line
read(LU, fmt="(I)", this.n)
this.n2 = this.n * this.n
if (this%n < 1) {
fatal("Negate field size!")
}
if (this%n > 6) {
fatal("Unsupported size!")
}
this.field = new(fill=0) i32[this.n2, this.n2]
this.tfield = new(fill=0) i32[this.n2, this.n2, this.n2]
line = new(fill=' ') c8[this.n2]
do i32 i = 1, this%n2 {
read(LU, fmt=f"(A{this.n2})", line)
do i32 j = 1, this%n2 {
this.field[i,j] = sudctoi(line[j])
}
}
}
bool sudoku_solver_t.next() {
integer :: pos(1)
next = .false.
this%tfield[..] = -1
do i32 n = 1, this%n2 {
if (count(this.field[..] == n) == this.n2) {
this.tfield[..,n] = 0
cycle
}
do i32 j = 1, this.n2 {
do i32 i = 1, this.n2 {
if (this%tfield[i,j,n] == 0) {
cycle
}
if (this%field[i,j] == n) {
this%tfield[i,j,:] = 0
this%tfield[:,j,n] = 0
this%tfield[i,:,n] = 0
! fill block
i32 imin = ((i-1) / this.n) * this%n + 1
i32 jmin = ((j-1) / this.n) * this%n + 1
i32 imax = imin + this.n - 1
i32 jmax = jmin + this.n - 1
this%tfield[imin:imax, jmin:jmax, n] = 0
}
}
}
}
do i32 j = 1, this.n2 {
do i32 i = 1, this.n2 {
if (count(this.tfield[i,j,:] == -1) == 1) {
next = .true.
pos = findloc(this.tfield[i,j,:], -1)
this%field[i,j] = pos(1)
}
}
}
if (next .and. count(this.field[..] == 0) == 0) next = .false.
}
sudoku_solver_t.print() {
use helper_mod -> global, only: itosudc
print_horizontal()
do i32 i = 1, this%n2 {
do i32 j = 1, this%n2 {
if (j % this.n == 1) {
write(*, fmt="(A3)", " | ")
}
write(*, fmt="(A1)", itosudc(this%field[i,j]))
}
write(*, fmt="(A3)", " |\n")
if (i % this.n == 0) print_horizontal()
}
nested print_horizontal() {
write(*, fmt="(A3)", " +-")
do i32 j = 1, this.n {
write(*, fmt=f"(A{this.n})", this.n * "-")
if (j < this.n) write(*, fmt="(A3)", "-+-")
}
write(*, fmt="(A3)", "-+\n")
}
}
}
program sudoku_solver() {
use sudoku_solver_mod -> global
sudoku_solver_t ss
i32 n
File LU
bool do_next, file_exist
allocatable c8[:] filename
call get_command_argument(1, filename)
inquire(file=filename, exist=file_exist)
if (.not.file_exist) fatal(f"File '{filename}' not found!")
open(newunit=LU, file=filename, form='formatted')
ss.load_from_file(LU)
close(LU)
ss.print()
do_next = .true.
do while (do_next) {
do_next = ss.next()
ss.print()
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment