Thanks very much, @PMunch!  
I've learnt a lot.  
  
But for the 2nd algo, in the Python slice g[i::j][:L] is to loop from index i 
to end with step j. Not i to j => g[i:j].  
Python has this [start:end:step] slice.  
Hence, I don't know how to convert this in nim.  

    
    
    
#-------------------------------------------------------------------------------
    # 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()
    
    # Algo1: Procedure to find word in grid of letters using Table.
    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
      
      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
    
    
    # Algo2: Function to find word in grid of letters using Array.
    proc find_word(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():
              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
      
      # Another algo to find words.
      echo()
      echo "=".repeat 40
      var nw: int = 0
      for word in clues:
        nw = nw + 1
        find_word(puzzle, word)
        if nw mod 5 == 0 and nw < len(clues):
          echo "-".repeat 35
        else:
          if nw!=len(clues):
            echo()
      
      echo "=".repeat 40
      echo()
    
    
    Run

I renamed the 2nd algo procedure to find_word().  
Running this, I hit this runtime error:  

    
    
    ========================================
    Belgium:
    /usercode/in.nim(141)    in
    /usercode/in.nim(103)    find_word
    /playground/nim/lib/system.nim(2566) []
    /playground/nim/lib/system/fatal.nim(53) sysFatal
    Error: unhandled exception: index 2 not in 0 .. 1 [IndexDefect]

Reply via email to