DEV Community

Discussion on: Daily Challenge #8 - Scrabble Word Calculator

Collapse
 
ganderzz profile image
Dylan Paulus

My overly complex (nim) solution :)

from strutils import toLower
from sequtils import filter

type WordType = enum value, multiply, global

type Word = object
  Value: int
  Type: WordType

# a..z
# [97, 122]
const score_mapping = [1, 3, 3, 2, 1, 4, 
                       2, 4, 1, 8, 5, 1, 3, 
                       1, 1, 3, 10, 1, 1, 
                       1, 1, 4, 4, 8 , 4, 10]

# Build a stack, tokenizing the characters
# This will let us apply operations in a reverse order
proc buildStack(word: string): seq[ref Word] =
  result = newSeq[ref Word]()
  let lowerWord = toLower(word)

  for i in 0..(len(lowerWord) - 1):
    let currentWord = new(Word)
    let letter = lowerWord[i]
    let letterAsInt = int(letter)

    if letterAsInt < 97 or letterAsInt > 122:
      if letter == '*':
        currentWord.Value = 2
        currentWord.Type = WordType.multiply
      if letter == '^':
        currentWord.Value = 0
        currentWord.Type = WordType.multiply
      if letter == '(':
        currentWord.Value = if lowerWord[i+1] == 't': 3 else: 2
        currentWord.Type = WordType.global
        result.add(currentWord) # we reached the end of the string
        break
    else:
      let scoreMappingPosition = letterAsInt - 97

      currentWord.Value = score_mapping[scoreMappingPosition]
      currentWord.Type = WordType.value

    result.add(currentWord)

# Gets the value of the operations
proc parseOperations(value: int, operations: seq[ref Word]): int =
  var multiplier = 1

  if len(operations) > 0:
    for operation in operations:
      if operation.Type == Wordtype.multiply:
        if operation.Value == 0:
          return 0
        else:
          multiplier += 1

  result += value * multiplier

proc getScore(stack: seq[ref Word]): int =
  var s = stack # make mutable
  var operations: seq[ref Word]
  var globalMultiplier = 1

  if stack.filter(proc(p: ref Word): bool = p.Type == Wordtype.value).len >= 7:
    result += 50

  while len(s) > 0:
    let item = s.pop()

    if item.Type == WordType.value:
      result += parseOperations(item.Value, operations)
      operations = @[]
    elif item.Type == Wordtype.global:
      globalMultiplier = item.Value
    else:
      operations.add(item)

  result *= globalMultiplier

echo buildStack("d**e*v^(d)").getScore()