Your Nim implementation is probably going to look something like this:
#-------------------------------------------------------------------------------
# Name: WordSearch.nim
# Purpose: Find word in a grid of letters in any directions.
#-------------------------------------------------------------------------------
import std/[strutils, strformat, enumerate, sugar, tables, algorithm]
# Implement divmod for nim-lang.
proc divmod(a, b: int): (int, int) =
let
res = a div b # integer division
rem = a mod b # integer modulo operation
(res, rem)
# Procedure to print the grid of letters with row numbers & column letters.
proc print_grid(puzzle: string) =
var lastRow: string
let newGrid = puzzle.replace(" ", "")
for i, row in enumerate(1, newGrid.split('\n')):
# Print top column letters heading.
if i == 1:
stdout.write " "
for m in 0 ..< len(row):
stdout.write fmt"{chr(ord('a')+m)} "
echo()
stdout.write " +"
stdout.write "-".repeat(2 * len(row) + 1)
echo "+"
# Print row numbers heading.
stdout.write fmt"{i:02}| "
for m in row:
stdout.write fmt"{m} "
echo(fmt"|{i:02}")
# row is out of scope after the for-loop in Nim.
# Need a var lastRow to store the last value.
lastRow = row
# Print bottom column letters heading.
stdout.write " +"
stdout.write "-".repeat(2 * len(lastRow) + 1)
echo "+"
stdout.write " "
for m in 0 ..< len(lastRow):
stdout.write fmt"{chr(ord('a')+m)} "
echo()
# Procedure to find word in grid of letters.
proc solve_puzzle(puzzle: string; clues: seq) =
let
newGrid = puzzle.replace(" ", "")
length = newGrid.find('\n') + 1
# Make a list of tuples containing each letter and its row and column.
letters = collect(newSeq):
for index, letter in enumerate(newGrid): (letter, divmod(index,
length))
# Reorder the list to represent each reading direction,
# and add them all to a dictionary.
var lines = initTable[string, typeof(letters)]()
let offsets = {"down": 0, "left down": -1, "right down": 1}.toTable
# Test printing the dictionary/table 'offsets' items.
for dirn, offset in offsets.pairs():
echo fmt"dirn = {dirn}, offset = {offset}"
for direction, offset in offsets:
lines[direction] = @[] # Empty seq.
for i in 0 ..< length:
for j in countup(i, letters.high, length + offset):
lines[direction].add(letters[j])
lines[direction].add(('\n', (0, 0)))
lines["right"] = letters
lines["left"] = letters.reversed
lines["up"] = lines["down"].reversed
lines["left up"] = lines["right down"].reversed
lines["right up"] = lines["left down"].reversed
# Make strings from the letters, find the words in them and retrieve
# their original locations.
var nc = 0
for direction, tup in lines:
let myStr = block:
var x = ""
for line in tup: x &= line[0]
x
for word in clues:
if word.toUpper() in myStr:
nc = nc + 1
var location = tup[myStr.find(word.toUpper())][1]
echo fmt"{word.toUpper()}: row[{location[0] + 1:02}]
col[{chr(ord('a') + location[1])}] {direction}"
if (nc mod 5) == 0 and nc < clues.len:
echo "-".repeat 35
# Function to find word in grid of letters.
proc solve_puzzle(puzzle: string; word: string) =
echo(fmt"{word}:")
let newGrid = puzzle.replace(" ","")
let w = newGrid.find("\n")+1
let L = word.len
var res: seq[(int, int)]
for i in 0 ..< len(newGrid):
for j in @[-w-1, -w, -w+1, -1, 1, w-1, w, w+1]:
for x in i ..< i+(L-1)*j:
if newGrid[i..j][0..L] == word.toUpper(): # nim(124, 25) Error:
expected: ']', but got: '::'
res.add((x div (w + 1), (x mod w) + 1))
for t in res:
echo " --> ".join("Row[t[0]:02] Col[{chr(ord('a') + t[1] - 1)}]")
when is_main_module:
# Define the puzzle.
let puzzle = """I U W S S W E D E N F Q S M V R P B
B M I D F I N D I A H I S P W Y Y L
H T E N I G E R I A I O N V A M C P
Y Y H X R L E B E T G R J L O I A A
H N X A I U E Z F R A N C E A E N N
V R O T I C S N B E L G I U M N A A
N F R R Y L O S G I C V M N V E D M
W N X F W V A I I L T O Z I H A A A
G H A N A A M N X A A A F B K I N B
G R E E C E Y A D A D N L Z U D F Z
T P K P Q J A P A N T Q D Y D L V I
V K A M E R I C A D C H I N A B C X"""
let clues = @["Belgium", "Greece", "Canada", "Japan", "England",
"Italy", "France", "Panama", "India", "Mexico",
"Norway", "Spain", "China", "Thailand", "Sweden",
"Ghana", "Russia", "Finland", "Nigeria", "America"]
# Print the grid.
print_grid(puzzle)
# Find the words.
echo()
echo "=".repeat 40
solve_puzzle(puzzle, clues)
echo "=".repeat 40
Run
A couple of things to note:
* The two errors you had marked out where mostly just type issues. Nim needs
complete type information at the type of instantiation, so just `seq` or `@[]`
isn't good enough. You also tried to add a `'\n'` to a sequence expecting a
`(char, (int, int))` tuple which won't work in Nim, I just added in zeros for
the coordinates there, not sure what Python does in this case but you might
have to tweak that to get the required results.
* You also had an indexing error, Nims iterators are inclusive, so I changed
an instance of `len` into `high` in order to get the highest index in can loop
to and not the length of the sequence.
* Nim uses two spaces instead of two for indentation, using four won't break
anything, but it makes it harder for people like me to go in and edit your code
because my editor automatically tries to add two spaces. I converted the
snippet to use two spaces.
* Nim in general uses `camelCase` but this is mostly down to preference and
the language itself is case and underscore insensitive so you're free to use
`snake_case` if you like (as you have discovered). I haven't converted the code
to `camelCase` but some of that casing might have snuck in there, feel free to
change those to `snake_case`.
* Nim has block variations on `let` and `var`, I threw some of those in there
for you as well.
* Nim has `repeat` in strutils which does the same as `" " * 100` does in
Python. I've replaced your instances of that and removed the repeat
implementation you had. This makes things a bit more type-safe, but if you
can't live without the convenience feel free to create a small template to
bring it back.
* Nim supports Universal Function Call Syntax (UFCS) which means you can call
e.g. `write` and `len` with a dot instead of as a function. You can also call
functions without parenthesis (think `print` from Python 2). I've replaced
`write(stdout, "hello")` with `stdout.write "hello"` in the snippet and
`echo("something")` with `echo "something` as is customary in Nim. I've also
replaced `len(something)` with `something.len`.
* Some functions like `upper` and the collection around `reversed` can be
done in Nim with `toUpper` and just the function `reversed`. So I changed those
to their Nim equivalents.
* I threw in some more whitespace for readability.
* You (like most Python programmers) seem to like untyped lists/tables/tuples
to iterate over things. In Nim you would normally do that with enums in a more
type-safe manner. I haven't really changed anything around that though.