something has to parse it. This is AdventOfParsing after all.

if you know all the input strings at compile time one way could be:
    
    
    import macros
    const validCard: set[char] = {'A','J','Q','K','0'..'9'}
    type
      Hand = distinct string
    
    macro validate(s: static string) =
      if (s.len!=5):
        error "length must be 5"
      for i in s:
        if (not (i in validCard)):
          error "invalid card: " & i
    
    proc toHand(s:static string):Hand =
      static: validate(s)
      Hand(s)
    
    proc `$`(x:Hand):string = "Hand: " & string(x)
    
    echo toHand("A3QJ4")
    static: assert not compiles(toHand("ABCDE"))
    
    
    Run

to do your enum solution you might:
    
    
    import std/[enumutils,sequtils]
    macro generateEnum(validCards:static set[char]):type =
      result = nnkEnumTy.newNimNode().add(newEmptyNode())
      for c in validCards:
        result.add nnkEnumFieldDef.newNimNode().add(ident ("C" & c), newLit(c))
      #echo result.treeRepr
    
    type
      Card = generateEnum({'A','J','Q','K','T','2'..'9'})
      Hand2 = array[5,Card]
    
    #still need to validate the input string,
    proc toHand2(s:static string):Hand2 =
      static: validate(s)
      for i,c in s:
        result[i] = Card(c)#warning: conversion to enum with holes is unsafe
    
    echo toHand2("A3QJ4") # [CA, C3, CQ, CJ, C4]
    
    
    Run

Reply via email to