How to resolve the algorithm Wordiff step by step in the Nim programming language

Published on 12 May 2024 09:40 PM

How to resolve the algorithm Wordiff step by step in the Nim programming language

Table of Contents

Problem Statement

Wordiff is an original game in which contestants take turns spelling new dictionary words of three or more characters that only differ from the last by a change in one letter.

The change can be either:

Note:

Create a program to aid in the playing of the game by:

Let's start with the solution:

Step by Step solution about How to resolve the algorithm Wordiff step by step in the Nim programming language

Source code in the nim programming language

import httpclient, sequtils, sets, strutils, sugar
from unicode import capitalize

const
  DictFname = "unixdict.txt"
  DictUrl1 = "http://wiki.puzzlers.org/pub/wordlists/unixdict.txt"    # ~25K words
  DictUrl2 = "https://raw.githubusercontent.com/dwyl/english-words/master/words.txt"  # ~470K words


type Dictionary = HashSet[string]


proc loadDictionary(fname = DictFname): Dictionary =
  ## Return appropriate words from a dictionary file.
  for word in fname.lines():
    if word.len >= 3 and word.allCharsInSet(Letters): result.incl word.toLowerAscii


proc loadWebDictionary(url: string): Dictionary =
  ## Return appropriate words from a dictionary web page.
  let client = newHttpClient()
  for word in client.getContent(url).splitLines():
    if word.len >= 3 and word.allCharsInSet(Letters): result.incl word.toLowerAscii


proc getPlayers(): seq[string] =
  ## Return inputted ordered list of contestant names.
  try:
    stdout.write "Space separated list of contestants: "
    stdout.flushFile()
    result = stdin.readLine().splitWhitespace().map(capitalize)
    if result.len == 0:
      quit "Empty list of names. Quitting.", QuitFailure
  except EOFError:
    echo()
    quit "Encountered end of file. Quitting.", QuitFailure


proc isWordiffRemoval(word, prev: string; comment = true): bool =
  ## Is "word" derived from "prev" by removing one letter?
  for i in 0..prev.high:
    if word == prev[0..<i] & prev[i+1..^1]: return true
  if comment: echo "Word is not derived from previous by removal of one letter."
  result = false


proc isWordiffInsertion(word, prev: string; comment = true): bool =
  ## Is "word" derived from "prev" by adding one letter?
  for i in 0..word.high:
    if prev == word[0..<i] & word[i+1..^1]: return true
  if comment: echo "Word is not derived from previous by insertion of one letter."
  return false


proc isWordiffChange(word, prev: string; comment = true): bool =
  ## Is "word" derived from "prev" by changing exactly one letter?
  var diffcount = 0
  for i in 0..word.high:
    diffcount += ord(word[i] != prev[i])
  if diffcount != 1:
    if comment:
      echo "More or less than exactly one character changed."
    return false
  result = true


proc isWordiff(word: string; wordiffs: seq[string]; dict: Dictionary; comment = true): bool =
  ## Is "word" a valid wordiff from "wordiffs[^1]"?
  if word notin dict:
    if comment:
      echo "That word is not in my dictionary."
      return false
  if word in wordiffs:
    if comment:
      echo "That word was already used."
      return false
  result = if word.len < wordiffs[^1].len: word.isWordiffRemoval(wordiffs[^1], comment)
           elif word.len > wordiffs[^1].len: word.isWordiffInsertion(wordiffs[^1], comment)
           else: word.isWordiffChange(wordiffs[^1], comment)


proc couldHaveGot(wordiffs: seq[string]; dict: Dictionary): seq[string] =
  for word in dict - wordiffs.toHashSet:
    if word.isWordiff(wordiffs, dict, comment = false):
      result.add word


when isMainModule:
  import random

  randomize()
  let dict = loadDictionary(DictFname)
  let dict34 = collect(newSeq):
                 for word in dict:
                   if word.len in [3, 4]: word
  let start = sample(dict34)
  var wordiffs = @[start]
  let players = getPlayers()
  var iplayer = 0
  var word: string
  while true:
    let name = players[iplayer]
    while true:
      stdout.write "$1, input a wordiff from “$2”: ".format(name, wordiffs[^1])
      stdout.flushFile()
      try:
        word = stdin.readLine().strip()
        if word.len > 0: break
      except EOFError:
        quit "Encountered end of file. Quitting.", QuitFailure
    if word.isWordiff(wordiffs, dict):
      wordiffs.add word
    else:
      echo "You have lost, $#.".format(name)
      let possibleWords = couldHaveGot(wordiffs, dict)
      if possibleWords.len > 0:
        echo "You could have used: ", possibleWords[0..min(possibleWords.high, 20)].join(" ")
      break
    iplayer = (iplayer + 1) mod players.len


  

You may also check:How to resolve the algorithm Box the compass step by step in the QBasic programming language
You may also check:How to resolve the algorithm Window creation step by step in the PowerShell programming language
You may also check:How to resolve the algorithm Arrays step by step in the Lisaac programming language
You may also check:How to resolve the algorithm K-d tree step by step in the Rust programming language
You may also check:How to resolve the algorithm Horner's rule for polynomial evaluation step by step in the HicEst programming language