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.


Reply via email to