import java.util.Scanner;

public class NimGame {

    public static void main(String[] args) {
        runGame(12);
    }

    private static void runGame(int tokens) {
        System.out.printf("Nim game.%n%n");

        Scanner in = new Scanner(System.in);;

        do {
            boolean humanInputOk = false;
            int humanTokens = 0;
            while ( ! humanInputOk ) {
                System.out.printf("Human takes how many tokens?  ");
                String input = in.next();
                try {
                    humanTokens = Integer.parseInt(input);
                    if ( humanTokens >= 1 && humanTokens <= 3 ) {
                        humanInputOk = true;
                    }
                    else {
                        System.out.printf("Try a number between 1 and 3.%n");
                    }
                }
                catch (NumberFormatException e) {
                    System.out.printf("Invalid input.  Try a number between 1 and 3.%n");
                }
            }

            tokens -= humanTokens;

            System.out.printf("You take %d token%s.%n%d token%s remaining.%n%n", humanTokens, humanTokens > 1 ? "s" : "", tokens, tokens != 1 ? "s" : "");
            if ( tokens == 0 ) {
                System.out.printf("You win!!.%n%n");
                break;
            }
            int computerTokens = 4 - humanTokens;
            tokens -= computerTokens;

            System.out.printf("Computer takes %d token%s.%n%d token%s remaining.%n%n", computerTokens, computerTokens != 1 ? "s" : "", tokens, tokens != 1 ? "s" : "");
            if ( tokens == 0 ) {
                System.out.printf("Computer wins!!.%n%n");
            }

        } while (tokens > 0);

        in.close();
    }

}


#lang racket
;;; --------------------------------------------------------------------------------------------------
;;; Representaiton is done with bits: the bit patterns for a block being:
;;; -------------------------------------------------------------------------
;;; #b00 (0) - block is not in representation (also a terminator on the left)
;;; #b01 (1) - block is white
;;; #b10 (2) - block is black
;;; #b11 (3) - block is undecided
;;; None of the problems has > 32 columns, so 64-bits should be fine
;;; If we go above 64-bits, then a. we have a difficult problem
;;;                              b. racket will use bignums rather
;;;                                 than fixnums
;;;
;;; A "blocks" is an integer formed of two-bit block codes (above)
;;;
;;; A "representation" is a sequence (list) of black stretch lengths; which need to be separated by at
;;; least one white between, and optionally prefixed and suffied with whites
;;;
;;; A "candidate" is a sequence (list) of <white-length [black-length white-length]...>, specifying
;;; one instance of a "representation".
;;;
;;; A "puzzle" is a sequence (vector) of blocks
;;; -- if the puzzle is <= 32 blocks wide, this could well be an fxvector (but ignore that
;;;    possibility for now)
;;;
;;; "Options" is a sequence (list) of blocks
;;;
;;; white is often abbreviated (in variables etc. to W), black to "B"
;;; --------------------------------------------------------------------------------------------------
(module+ test (require rackunit))
(define *problems-file-name* "nonogram_problems.txt")

;;; --------------------------------------------------------------------------------------------------
;;; Parsing Input
;;; --------------------------------------------------------------------------------------------------
(define (letter-rep->number-rep c) (+ 1 (- (char->integer (char-upcase c)) (char->integer #\A))))

;; takes the letters representation, returns a list of list of numbers. The list returned is an
;; "option" - a list of ([white-width black-width] ... white-width)
(define (letters-rep->list²-rep s)
  (for/list ((b (regexp-split #rx" +" s)))
    (map letter-rep->number-rep (string->list b))))

(define (read-nonogram-description prt)
  (match (read-line prt)
    [(? eof-object?) #f]
    ["" (read-nonogram-description prt)]
    [(? string? l)
     (vector (letters-rep->list²-rep l)
             (letters-rep->list²-rep (read-line prt)))]))

(define (read-one-nonogram-from-file file-name)
  (call-with-input-file file-name read-nonogram-description))

(module+ test
  (check-equal? (map letter-rep->number-rep '(#\A #\a #\B #\C)) '(1 1 2 3))
  (check-equal? (letters-rep->list²-rep "C BA CB BB F AE F A B")
                '([3] [2 1] [3 2] [2 2] [6] [1 5] [6] [1] [2]))
  (check-equal? (letters-rep->list²-rep "AB CA AE GA E C D C")
                '([1 2]  [3 1]  [1 5]  [7 1]  [5]  [3]  [4] [3]))
  (check-equal? (read-one-nonogram-from-file *problems-file-name*)
                #(([3] [2 1] [3 2] [2 2] [6] [1 5] [6] [1] [2])
                  ([1 2]  [3 1]  [1 5]  [7 1]  [5]  [3]  [4] [3]))))

;;; --------------------------------------------------------------------------------------------------
;;; Generate Candidates
;;; --------------------------------------------------------------------------------------------------
(define (rep->candidates n-cells blacks)
  (define (inr cells-remain bs leftmost?)
    (define bs-l (sequence-length bs))
    (define min-space-needed (- (apply + bs-l bs) 1))
    (cond
      [(null? bs) (list (list cells-remain))]
      [(> min-space-needed cells-remain) null]
      [else
       (define initial-whites-min-size (if leftmost? 0 1))
       (define intial-whites-range
         (in-range initial-whites-min-size (add1 (- cells-remain min-space-needed))))
       (for*/list ((intial-whites intial-whites-range)
                   (tl (in-list (inr (- cells-remain intial-whites (car bs)) (cdr bs) #f))))
         (list* intial-whites (car bs) tl))]))
  (inr n-cells blacks #t))

(module+ test
  (check-match
   (rep->candidates 5 '(1)) (list-no-order '(0 1 4) '(1 1 3) '(2 1 2) '(3 1 1) '(4 1 0)))
  (check-match
   (rep->candidates 5 '(1 1))
   (list-no-order '(0 1 1 1 2) '(0 1 2 1 1) '(0 1 3 1 0) '(1 1 1 1 1) '(1 1 2 1 0) '(2 1 1 1 0))))

(define (make-Ws l) (for/fold ((rv 0)) ((_ l)) (+ (* 4 rv) #b01)))
(define (make-Bs l) (* 2 (make-Ws l)))
(module+ test
  (check-eq? (make-Ws 0) #b00)
  (check-eq? (make-Bs 0) #b00)
  (check-eq? (make-Ws 1) #b01)
  (check-eq? (make-Bs 1) #b10)
  (check-eq? (make-Ws 3) #b010101)
  (check-eq? (make-Bs 3) #b101010))

(define (candidate->blocks cand)
  (define (inr cand rv)
    (match cand
      [(list (and W (app make-Ws Ws)) (and B (app make-Bs Bs)) r ...)
       (inr r (+ (arithmetic-shift rv (* 2 (+ B W))) (arithmetic-shift Ws (* 2 B)) Bs))]
      [(list (and W (app make-Ws Ws))) (+ (arithmetic-shift rv (* 2 W)) Ws)]))
  (inr cand 0))

(module+ test
  (check-eq? (candidate->blocks '(0)) 0)
  (check-eq? (candidate->blocks '(1)) #b01)
  (check-eq? (candidate->blocks '(1 1 1)) #b011001)
  (check-equal?
   (map candidate->blocks
        '((0 1 1 1 2) (0 1 2 1 1) (0 1 3 1 0) (1 1 1 1 1) (1 1 2 1 0) (2 1 1 1 0)))
   '(#b1001100101 #b1001011001 #b1001010110 #b0110011001 #b0110010110 #b0101100110)))

;; Given a (non-empty) sequence of blocks return a list of blocks which must be black, must be
;; white or have to be dertermined another way (through matching along the other axis).
(define (find-definite-blocks blocks)
  (for/fold ((known (sequence-ref blocks 0))) ((merge blocks))
    (bitwise-ior known merge)))

(module+ test
  (check-eq? (find-definite-blocks '(#b010101 #b010110 #b100110)) #b110111)
  )

;; returns the list of blocks (from options) that can be overlaid over the solution
;; this means that the following must hold false for all bits (if it holds false, we can do a zero?
;; test, which is easiser than an all-significant-bits-set? test:
;; pattern cand
;;    0      0     F
;;    0      1     T
;;    1      0     F
;;    1      1     F
;; (cand !bitwise-impl pattern) = !(pattern | !cand) = (!pattern & cand)
(define (filter-against-partial-solution part-sltn options)
  (define not-part-sltn (bitwise-not part-sltn))
  (define (option-fits? cand) (zero? (bitwise-and cand not-part-sltn)))
  (filter option-fits? options))

(module+ test
  (check-equal?
   (filter-against-partial-solution #b011110 '(#b101010 #b010110 #b011010))
   '(#b010110 #b011010)))

;;; --------------------------------------------------------------------------------------------------
;;; Rendering -- it's pretty tough to see what's going on, when you have no pictures!
;;; --------------------------------------------------------------------------------------------------
(define ((render-puzzle knil kons-W kons-B kons-_ compose-lines) pzl)
  (define (render-blocks bs)
    (define (inr bs acc)
      (match (bitwise-and bs #b11)
        [#b00 acc]
        [#b01 (inr (arithmetic-shift bs -2) (kons-W acc))]
        [#b10 (inr (arithmetic-shift bs -2) (kons-B acc))]
        [#b11 (inr (arithmetic-shift bs -2) (kons-_ acc))]))
    (inr bs knil))
  (compose-lines (map render-blocks pzl)))

(define string-render-puzzle
  (render-puzzle ""
                 (curry string-append ".")
                 (curry string-append "#")
                 (curry string-append "?")
                 (curryr string-join "\n")))

(module+ test
  (check-equal? (string-render-puzzle '(#b101010 #b010101 #b111111)) "###\n...\n???"))

;;; We need to work on x and y blocks uniformly, so this will convert from one to t'other
;;; Rotates a sequence of blocks
(define (rotate-blocks x-blocks)
  (define x-width- (integer-length (sequence-ref x-blocks 0)))
  (define x-width (if (odd? x-width-) (add1 x-width-) x-width-))
  ;(printf "~a ~a" x-width x-blocks)
  (for/list ((block-idx (in-range x-width 0 -2)))
    (for/fold ((y-block 0))
      ((x-block x-blocks))
      (+ (arithmetic-shift y-block 2)
         (bitwise-bit-field x-block (- block-idx 2) block-idx)))))

(module+ test
  (check-equal? (rotate-blocks '(#b1110 #b0111)) '(#b1101 #b1011))
  (check-equal? (rotate-blocks '(#b0110 #b0111)) '(#b0101 #b1011)))

;;; --------------------------------------------------------------------------------------------------
;;; SOLVER (finally!):
;;; --------------------------------------------------------------------------------------------------
;;; solve the nonogram... both "solvers" return as values:
;;;   solution-changed? did the solution change -- if not we either have a solution or as good a
;;;                     solution as the program can provide
;;;   new-solution      the newly-changed solution
;;;   new-x-blocks      x-blocks that are now available as candidates
;;;   new-y-blocks      y-blocks that are now available as candidates
(define (solved? blocks) (for/and ((b blocks)) (= (sequence-length b) 1)))

(define (solve-nonogram x-rep.y-rep) ; pair of reps as read from e.g. read-nonogram-from-file
  (match-define (vector x-rep y-rep) x-rep.y-rep)
  (define width (sequence-length y-rep))
  (define height  (sequence-length x-rep))
  (define x-candidates (map (curry rep->candidates width) x-rep))
  (define y-candidates (map (curry rep->candidates height) y-rep))
  (define x-options    (for/list ((cnds x-candidates)) (map candidate->blocks cnds)))
  (define y-options    (for/list ((cnds y-candidates)) (map candidate->blocks cnds)))

  (define-values (solution complete?) (sub-solve-nonogram x-options y-options))
  (unless complete? (displayln "INCOMPLETE SOLUTION"))
  solution)

(define (sub-solve-nonogram x-options y-options)
  (define known-x (map find-definite-blocks x-options))
  (define known-y (map find-definite-blocks y-options))
  (cond
    [(solved? x-options) (values known-x #t)]
    [else
     (define new-y-options (map filter-against-partial-solution (rotate-blocks known-x) y-options))
     (define new-x-options (map filter-against-partial-solution (rotate-blocks known-y) x-options))
     (displayln (string-render-puzzle (map find-definite-blocks new-x-options)) (current-error-port))
     (newline (current-error-port))
     (if (and (equal? x-options new-x-options) (equal? y-options new-y-options))
         (values known-x #f) ; oh... we can't get any further
         (sub-solve-nonogram new-x-options new-y-options))]))

;;;; TESTING
(module+ test
  (define chicken #<<EOS
.###....
##.#....
.###..##
..##..##
..######
#.#####.
######..
....#...
...##...
EOS
    )
  (check-equal?
   (string-render-puzzle (solve-nonogram (read-one-nonogram-from-file *problems-file-name*)))
   chicken))

;;; IMAGE RENDERING
(require pict racket/gui/base)

(define *cell-size* 10)
(define ((paint-cell fill-colour) dc dx dy)
  (define C (- *cell-size* 1))
  (define old-brush (send dc get-brush))
  (define old-pen (send dc get-pen))
  (define path (new dc-path%))
  (send path rectangle 0 0 C C)
  (send* dc
    (set-brush (new brush% [color fill-colour]))
    (set-pen (new pen% [width 1] [color "black"]))
    (draw-path path dx dy)
    (set-brush old-brush)
    (set-pen old-pen)))

(define (draw-cell fill-colour)
  (dc (paint-cell fill-colour)
      *cell-size* *cell-size*))

(define ((row-append-cell colour) row-so-far)
  (hc-append (draw-cell colour)  row-so-far))

(define image-render-puzzle
  (render-puzzle
   (blank)
   (row-append-cell "white")
   (row-append-cell "black")
   (row-append-cell "yellow")
   (λ (rows) (apply vc-append rows))))

(module+ test
  ; test though visual inspection... it's a style thing, really
  (image-render-puzzle (solve-nonogram (read-one-nonogram-from-file *problems-file-name*))))

;;; MAIN
(module+ main
  (unless (directory-exists? "images") (make-directory "images"))

  (call-with-input-file *problems-file-name*
    (lambda (prt)
      (let loop ((idx 1) (pzl (read-nonogram-description prt)) (collage (blank)))
        (cond
          [pzl
           (define img (image-render-puzzle (solve-nonogram pzl)))
           (send (pict->bitmap img) save-file (build-path "images" (format "nonogram-~a.png" idx))
                 'png)
           (displayln (image-render-puzzle (solve-nonogram pzl)))
           (loop (add1 idx) (read-nonogram-description prt) (vl-append 2 collage img))]
          [else
           (send (pict->bitmap collage) save-file (build-path "images" (format "nonogram-all.png"))
                 'png)
           (displayln collage)])))))


# 20220401 Raku programming solution

sub reduce(\a, \b) {
   my \countRemoved = $ = 0;
   for ^+a -> \i {
      my \commonOn  = @ =  True xx b.elems;
      my \commonOff = @ = False xx b.elems;

      a[i].map: -> \candidate { commonOn  <<?&=>> candidate ;
                                commonOff <<?|=>> candidate }
      # remove from b[j] all candidates that don't share the forced values
      for ^+b -> \j {
         my (\fi,\fj) = i, j;
         for ((+b[j])^...0) -> \k {
            my \cnd = b[j][k];
            if (commonOn[fj] ?& !cnd[fi]) ?| (!commonOff[fj] ?& cnd[fi]) {
	       b[j][k..*-2] = b[j][k+1..*-1];
               b[j].pop;
               countRemoved++
            }
         }
         return -1 if b[j].elems == 0
      }
   }
   return countRemoved
}

sub genSequence(\ones, \numZeros) {
   if ( my \le = ones.elems ) == 0 { return [~] '0' xx numZeros }

   my @result;
   loop ( my $x = 1; $x < ( numZeros -le+2); $x++ ) {
      my @skipOne = ones[1..*];
      for genSequence(@skipOne, numZeros -$x) -> \tail {
         @result.push:  ( '0' x $x )~ones[0]~tail
      }
   }
   return @result
}

# If all the candidates for a row have a value in common for a certain cell,
#   then it's the only possible outcome, and all the candidates from the
#   corresponding column need to have that value for that cell too. The ones
#   that don't, are removed. The same for all columns. It goes back and forth,
#   until no more candidates can be removed or a list is empty (failure).

sub reduceMutual(\cols, \rows) {
   return -1 if ( my \countRemoved1 = reduce(cols, rows) ) == -1 ;
   return -1 if ( my \countRemoved2 = reduce(rows, cols) ) == -1 ;

   return countRemoved1 + countRemoved2
}

# collect all possible solutions for the given clues
sub getCandidates(@data, \len) {
   return gather for @data -> \s {
      my \sumBytes = [+] (my @a = s.ords)>>.&{ $_ - 'A'.ord + 1 }
      my @prep = @a.values.map: { [~] '1' xx ($_ - 'A'.ord + 1) }
      take ( gather for genSequence(@prep, len -sumBytes+1) -> \r {
         my \bits = r.substr(1..*).ords;
	 take ( bits.values.map: *.chr == '1' ).Array
      } ).Array
   }
}

sub  newPuzzle (@data) {

   my (@rowData,@colData) := @data.map: *.split: ' ' ;

   my \rows = getCandidates(@rowData, @colData.elems);
   my \cols = getCandidates(@colData, @rowData.elems);

   loop {
      my \numChanged = reduceMutual(cols, rows);
      given (numChanged) { when -1 { say "No solution" andthen return }
                           when  0 { last }                             }
   }

   for rows -> \row {
      for ^+cols -> \k { print row[0][k] ?? '# ' !! '. ' }
      print "\n"
   }
   print "\n"
}

newPuzzle $_ for (
   ( "C BA CB BB F AE F A B", "AB CA AE GA E C D C" ),

   ( "F CAC ACAC CN AAA AABB EBB EAA ECCC HCCC",
     "D D AE CD AE A DA BBB CC AAB BAA AAB DA AAB AAA BAB AAA CD BBA DA" ),

   ( "CA BDA ACC BD CCAC CBBAC BBBBB BAABAA ABAD AABB BBH "
       ~"BBBD ABBAAA CCEA AACAAB BCACC ACBH DCH ADBE ADBB DBE ECE DAA DB CC",
     "BC CAC CBAB BDD CDBDE BEBDF ADCDFA DCCFB DBCFC ABDBA BBF AAF BADB DBF "
        ~"AAAAD BDG CEF CBDB BBB FC" ),

   ( "E BCB BEA BH BEK AABAF ABAC BAA BFB OD JH BADCF Q Q R AN AAN EI H G",
     "E CB BAB AAA AAA AC BB ACC ACCA AGB AIA AJ AJ "
        ~"ACE AH BAF CAG DAG FAH FJ GJ ADK ABK BL CM" ),
);


class Nim {
	constructor(tokens, printFun) {
		this.startTokens = tokens;
		this.tokens = tokens;
		this.printFun = printFun;
	}

	playerTurn(take) {
		take = Math.round(take);

		if (take < 1 || take > 3) {
			this.printFun("take must be between 1 and 3.\n")
			return false;
		}
		this.tokens -= take;
		this.printFun("Player takes " + take + " tokens.");
		this.printRemaining()

		if (this.tokens === 0) {
			this.printFun("Player wins!\n");
		}
		return true;
	}

	computerTurn() {
		let take = this.tokens % 4;
		this.tokens -= take;
		this.printFun("Computer takes " + take + " tokens.");
		this.printRemaining();

		if (this.tokens === 0) {
			this.printFun("Computer wins.\n");
		}

	}

	printRemaining() {
		this.printFun(this.tokens + " tokens remaining.\n");
	}
}

let game = new Nim(12, console.log);
while (true) {
	if (game.playerTurn(parseInt(prompt("How many tokens would you like to take?")))){
		game.computerTurn();
	}
	if (game.tokens == 0) {
		break;
	}
}


function nimgame()
    tcount = 12
    takenum = 0
    while true
        while true
            permitted = collect(1:min(3,tcount))
            println("$tcount tokens remain.\nHow many do you take ($permitted)? ")
            takenum = parse(Int, strip(readline(stdin)))
            if takenum in permitted
                break
            end
        end
        tcount -= 4
        println("Computer takes $(4 - takenum). There are $tcount tokens left.")
        if tcount < 1
            println("Computer wins as expected.")
            break
        end
    end
end

nimgame()


/*REXX*/
    Parse Arg fn
    Parse Var fn ou'.'
    maxpn = 10000               /* maximum possibilities to check through */
    output = ou'.out.txt'
 /* read row/col values into rowpp. and colpp. arrays */
    cc = linein(fn)
    rows = words(cc)
    dd = linein(fn)
    cols = words(dd)
    char = '0ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijk'
    cntr = 0
    Do i = 1 To rows
       rowpp.i = CV(cc,i)
       cntr = cntr + sum
    End
    cntc = 0
    Do i = 1 To cols
       colpp.i = CV(dd,i)
       cntc = cntc + sum
    End
    If (cntr <> cntc)|(cntr = 0) Then Do
       Say 'error Sum of rows <> sum of cols'
       Exit 999
    End
    Say cntr 'colored cells'
    ar = copies('-',rows*cols)
 /* values are -=unknown .=blank @=Color */
 /* PREFILL  array */
    'erase' output
 /**********COL PREFILL ************/
    Do col = 1 To cols
       r = colpp.col
       Parse Var r z r
       Do While r <> ''
          Parse Var r q r
          z = z + q + 1
       End
       result = copies('-',rows)
       If z = rows Then result = FILL_LINE(colpp.col)
       Else If z = 0 Then result = copies('.',rows)
       Do row = 1 To rows
          ar = overlay(substr(result,row,1),ar,(row-1)*cols+col)
       End
    End
 /**********ROW PREFILL ************/
    Do row = 1 To rows
       c = rowpp.row
       Parse Var c t c
       Do While c <> ''
          Parse Var c q c
          t = t + q + 1
       End
       result = substr(ar,(row-1)*cols+1,cols)
       If t = cols Then result = left(FILL_LINE(rowpp.row),cols)
       Else If t = 0 Then result = copies('.',cols)
       ar = overlay(result,ar,(row-1)*cols+1)
    End
 /********** ok here we loop ************/
    cnttry = 1
    nexttry = 2
    next.cnttry = ar
    sol = 0
    Do label nextpos While cnttry < nexttry
       Say 'trying' cnttry 'of' nexttry-1
       ar = next.cnttry
       cnttry = cnttry + 1
       Do Until sar = ar
          sar = ar
          Do row = 1 To rows
             /**********process rows ************/
             rowcol = substr(ar,(row-1)*cols+1,cols)
             pp = rowpp.row
             If PROCESSROW() Then Iterate nextpos
             Else ar = overlay(left(rowcol,cols),ar,(row-1)*cols+1)
          End
          Do col = 1 To cols
             rowcol = ''
             Do row = 1 To rows
                rowcol = rowcol || substr(ar,(row-1)*cols+ col,1)
             End
             pp = colpp.col
             If PROCESSROW() Then Iterate nextpos
             Do row = 1 To rows
                ar = overlay(substr(rowcol,row,1),ar,(row-1)*cols + col)
             End
          End
          If pos('-',ar) = 0 Then Do       /* hurray we have a solution */
             /* at this point we need to verify solution */
             If CHECKBOARD() Then Iterate nextpos   /* too bad didn't match */
             sol = sol + 1
             Call LINEOUT output,'This is solution no:' sol
             Call DUMPBOARD
             Iterate nextpos
          End
          If sar = ar Then Do
             fnd = pos('-',ar)
             next.nexttry = overlay('.',ar,fnd)
             nexttry = nexttry + 1
             ar = overlay('@',ar,fnd)
          End
       End
    End nextpos
    If sol = 0 Then sol = 'No'
    Say sol 'solutions found'
    Exit

 CHECKBOARD:
    Do row = 1 To rows
      /**********process rows ************/
       rowcol = substr(ar,(row-1)*cols+1,cols)
       pp = rowpp.row
       If CHECKROW() Then Return 1
    End
    Do col = 1 To cols
       rowcol = ''
       Do row = 1 To rows
          rowcol = rowcol || substr(ar,(row-1)*cols+ col,1)
       End
       pp = colpp.col
       If CHECKROW() Then Return 1
    End
    Return 0                                               /* we did it */

 CHECKROW:
    len_item = length(rowcol)
    st = 1
    If pp = 0 Then Return rowcol <> copies('.',len_item)
    Else If pp = len_item Then Return rowcol <> copies('@',len_item)
    Do While (pp <> '') & (st <= len_item)
       Parse Var pp p1 pp
       of = pos('@',rowcol'@',st)
       If of > len_item Then Return 1
       If substr(rowcol,of,p1) <> copies('@',p1) Then Return 1
       st = of + p1
       If substr(rowcol'.',st,1) <> '.' Then Return 1
    End
    Return 0

 DUMPBOARD:
    Parse Arg qr
    p = '..'
    q = '..'
    Do i = 1 To cols
       n = right(i,2)
       p = p left(n,1)
       q = q right(n,1)
    End
    Call LINEOUT output, p
    Call LINEOUT output, q
    Do i = 1 To rows
       o = right(i,2)
       p = substr(ar,(i-1)*cols+1,cols)
       Do j = 1 To cols
          Parse Var p z +1 p
          o = o z
       End
       Call LINEOUT output, o
    End
    Return

 FILL_LINE:
    Parse Arg items
    oo = ''
    Do While items <> ''
       Parse Var items a items
       oo = oo||copies('@',a)'.'
    End
    Return oo

 CV:
    Parse Arg cnts, rwcl
    str = word(cnts,rwcl)
    ret = ''
    sum = 0
    Do k = 1 To length(str)
       this = pos(substr(str,k,1),char)-1
       ret = ret this
       sum = sum + this
    End
    Return space(ret)

 PROCESSROW:                           /* rowcol pp in, rowcol pp of ol */
    prerow = rowcol
    len_item = length(rowcol)
    If pos('-',rowcol) = 0 Then Do
       pp = ''
       Return 0
    End
    of = 1
    kcnt = 0
    /* reduce the left side with already populated values */
    Do While (of < len_item) & (pp <> '')
       kcnt = kcnt + 1
       If kcnt > len_item Then Return 1
       If substr(rowcol,of,1) = '.' Then Do
          k = verify(substr(rowcol,of)'%','.')
          of = of + k - 1
          Iterate
       End
       nl = word(pp,1)
       len = verify(substr(rowcol,of)'%','[email protected]') - 1
       If len < nl Then Do
          rowcol = overlay(copies('.',len),rowcol,of)
          of = of + len
          Iterate
       End
       If (len = nl) & (pos('@',substr(rowcol,of,nl))>0) Then Do
          rowcol = overlay(copies('@',nl),rowcol,of)
          of = of + nl
          pp = subword(pp,2)
          Iterate
       End
       If substr(rowcol,of,1) = '@' Then Do
          rowcol = overlay(copies('@',nl)'.',rowcol,of)
          of = of + nl
          pp = subword(pp,2)
          Iterate
       End
       Leave
    End
    /* reduce the right side with already populated values */
    ofm = len_item + 1 - of
    ol = 1
    kcnt = 0
    Do While (ol < ofm) & (pp <> '')
       kcnt = kcnt + 1
       If kcnt > len_item Then Return 1
       revrow = reverse(rowcol)
       If substr(revrow,ol,1) = '.' Then Do
          k = verify(substr(revrow,ol)'%','.')
          ol = ol + k - 1
          Iterate
       End
       nl = word(pp,words(pp))
       len = verify(substr(revrow,ol)'%','[email protected]') - 1
       If len < nl Then Do
          rowcol = overlay(copies('.',len),rowcol,len_item-ol-len+2)
          ol = ol + len
          Iterate
       End
       If (len = nl) & (pos('@',substr(revrow,ol,nl))>0) Then Do
          rowcol = overlay(copies('@',nl),rowcol,len_item-ol-nl+2)
          ol = ol + nl
          pp = subword(pp,1,words(pp)-1)
          Iterate
       End
       If substr(revrow,ol,1) = '@' Then Do
          rowcol = overlay('.'copies('@',nl),rowcol,len_item-ol-nl+1)
          ol = ol + nl
          pp = subword(pp,1,words(pp)-1)
          Iterate
       End
       Leave
    End
    If pp = 0 Then pp = ''
    If pp = '' Then rowcol = changestr('-',rowcol,'.')
    If pp <> '' Then Do
       lv = len_item-of-ol+2
       pos. = ''
       pn = 0
       pi = substr(rowcol,of,lv)
       If (copies('-',length(pi)) = pi) Then Do
          len = CNT(pp)
          If (len + mx) <= lv Then Do
             Return 0
          End
       End
       /* oh oh need to check for posibilities */
       Call TRY '',pp
       If pn > maxpn Then Do
          over = over + 1
          Return 0
       End
       fnd = 0
       fu = pos.1
       Do z = 2 To pn
          Do j = 1 To lv
             If substr(fu,j,1) <> substr(pos.z,j,1) Then fu = overlay('-',fu,j)
          End
       End
       Do z = 1 To lv
          If substr(fu,z,1) <> '-' Then rowcol = overlay(substr(fu,z,1),rowcol,of+z-1)
       End
    End
    Return 0
 TRY: Procedure Expose pn pos. maxpn lv pi
    Parse Arg prev,pp
    If pp = '' Then Do
       rem = substr(pi,length(prev)+1)
       If translate(rem,'..','.-') <> copies('.',length(rem)) Then Return
       prev = left(prev||copies('.',lv),lv)
       pn = pn + 1
       If pn > maxpn Then Return
       pos.pn = prev
       Return
    End
    Parse Var pp p1 pp
    If length(prev)+p1 > lv Then Return
    Do i = 0 To lv - length(prev)-p1
       If translate(substr(pi,length(prev)+1,i),'..','.-') = copies('.',i) Then
         If translate(substr(pi,length(prev)+i+1,p1),'@@','@-') = copies('@',p1) Then
           If substr(pi,length(prev)+i+p1+1,1) <> '@' Then
             Call TRY prev||copies('.',i)||copies('@',p1)'.',pp
    End
    Return
 CNT: Procedure Expose mx
    Parse Arg len items
    mx = len
    Do While items <> ''
       Parse Var items ii items
       len = len + ii + 1
       If ii > mx Then mx = ii
    End
    Return len


// Version 1.3.21

fun showTokens(tokens: Int) {
    println("Tokens remaining $tokens\n")
}

fun main() {
    var tokens = 12
    while (true) {
        showTokens(tokens)
        print("  How many tokens 1, 2 or 3? ")
        var t = readLine()!!.toIntOrNull()
        if (t == null || t < 1 || t > 3) {
            println("\nMust be a number between 1 and 3, try again.\n")
        } else {
            var ct = 4 - t
            var s = if (ct > 1) "s" else ""
            println("  Computer takes $ct token$s\n")
            tokens -= 4
        }
        if (tokens == 0) {
            showTokens(0)
            println("  Computer wins!")
            return
        }
    }
}


tokens = 12

print("Nim Game\n")
print("Starting with " .. tokens .. " tokens.\n\n")

function printRemaining()
	print(tokens .. " tokens remaining.\n")
end

function playerTurn(take)
	take = math.floor(take)
	if (take < 1 or take > 3) then
		print ("\nTake must be between 1 and 3.\n")
		return false
	end

	tokens = tokens - take

	print ("\nPlayer takes " .. take .. " tokens.")
	printRemaining()
	return true
end

function computerTurn()
	take = tokens % 4
	tokens = tokens - take

	print("Computer takes " .. take .. " tokens.")
	printRemaining()
end

while (tokens > 0) do
	io.write("How many tokens would you like to take?: ")
	if playerTurn(io.read("*n")) then
		computerTurn()
	end
end

print ("Computer wins.")


import "/pattern" for Pattern
import "/math" for Nums, Boolean
import "/fmt" for Conv

var p = Pattern.new("/s")

var genSequence // recursive
genSequence = Fn.new { |ones, numZeros|
    if (ones.isEmpty) return ["0" * numZeros]
    var result = []
    var x = 1
    while (x < numZeros - ones.count + 2) {
        var skipOne = ones.skip(1).toList
        for (tail in genSequence.call(skipOne, numZeros - x)) {
            result.add("0" * x + ones[0] + tail)
        }
        x = x + 1
    }
    return result
}

/* If all the candidates for a row have a value in common for a certain cell,
    then it's the only possible outcome, and all the candidates from the
    corresponding column need to have that value for that cell too. The ones
    that don't, are removed. The same for all columns. It goes back and forth,
    until no more candidates can be removed or a list is empty (failure).
*/
var reduce =  Fn.new { |a, b|
    var countRemoved = 0
    for (i in 0...a.count) {
        var commonOn  = List.filled(b.count, true)
        var commonOff = List.filled(b.count, false)

        // determine which values all candidates of a[i] have in common
        for (candidate in a[i]) {
            for (i in 0...b.count) {
                commonOn[i]  = Boolean.and(commonOn[i], candidate[i])
                commonOff[i] = Boolean.or(commonOff[i], candidate[i])
            }
        }

        // remove from b[j] all candidates that don't share the forced values
        for (j in 0...b.count) {
            var fi = i
            var fj = j
            var removals = false
            b[j].each { |cnd|
                if ((commonOn[fj] && !cnd[fi]) || (!commonOff[fj] && cnd[fi])) {
                    b[j].remove(cnd)
                    removals = true
                }
            }
            if (removals) countRemoved = countRemoved + 1
            if (b[j].isEmpty) return -1
        }
    }
    return countRemoved
}

var reduceMutual = Fn.new { |cols, rows|
    var countRemoved1 = reduce.call(cols, rows)
    if (countRemoved1 == -1) return -1
    var countRemoved2 = reduce.call(rows, cols)
    if (countRemoved2 == -1) return -1
    return countRemoved1 + countRemoved2
}

// collect all possible solutions for the given clues
var getCandidates = Fn.new { |data, len|
    var result = []
    for (s in data) {
        var lst = []
        var a = s.bytes
        var sumChars = Nums.sum(a.map { |b| b - 64 })
        var prep = a.map { |b| "1" * (b - 64) }.toList

        for (r in genSequence.call(prep, len - sumChars + 1)) {
            var bits = r[1..-1].bytes
            var len = bits.count
            if (len % 64 != 0) len = (len/64).ceil * 64
            var bitset = List.filled(len, false)
            for (i in 0...bits.count.min(bitset.count)) bitset[i] = bits[i] == 49
            lst.add(bitset)
        }
        result.add(lst)
    }
    return result
}

var newPuzzle = Fn.new { |data|
    var rowData = p.splitAll(data[0])
    var colData = p.splitAll(data[1])
    var rows = getCandidates.call(rowData, colData.count)
    var cols = getCandidates.call(colData, rowData.count)

    while (true) {
        var numChanged = reduceMutual.call(cols, rows)
        if (numChanged == -1) {
            System.print("No solution")
            return
        }
        if (numChanged <= 0) break
    }

    for (row in rows) {
        for (i in 0...cols.count) {
            System.write(row[0][i] ? "# " : ". ")
        }
        System.print()
    }
    System.print()
}

var p1 = ["C BA CB BB F AE F A B", "AB CA AE GA E C D C"]

var p2 = [
    "F CAC ACAC CN AAA AABB EBB EAA ECCC HCCC",
    "D D AE CD AE A DA BBB CC AAB BAA AAB DA AAB AAA BAB AAA CD BBA DA"
]

var p3 = [
    "CA BDA ACC BD CCAC CBBAC BBBBB BAABAA ABAD AABB BBH " +
    "BBBD ABBAAA CCEA AACAAB BCACC ACBH DCH ADBE ADBB DBE ECE DAA DB CC",
    "BC CAC CBAB BDD CDBDE BEBDF ADCDFA DCCFB DBCFC ABDBA BBF AAF BADB DBF " +
    "AAAAD BDG CEF CBDB BBB FC"
]

var p4 = [
    "E BCB BEA BH BEK AABAF ABAC BAA BFB OD JH BADCF Q Q R AN AAN EI H G",
    "E CB BAB AAA AAA AC BB ACC ACCA AGB AIA AJ AJ " +
    "ACE AH BAF CAG DAG FAH FJ GJ ADK ABK BL CM"
]

for (puzzleData in [p1, p2, p3, p4]) newPuzzle.call(puzzleData)


n = 12;
While[n > 0,
 c = ChoiceDialog["Current amount = " <> ToString[n] <> "\nHow many do you want to pick?", {1 -> 1, 2 -> 2, 3 -> 3}];
 n -= c;
 ChoiceDialog["Current amount = " <> ToString[n] <> "\nComputer takes " <> ToString[4 - c]];
 n -= (4 - c);
 ]
ChoiceDialog["Current amount = " <> ToString[n] <> "\n You lost!"]


tokens = 12

print "Nim Game"
print "Starting with " + tokens + " tokens."
print

printRemaining = function()
	print tokens + " tokens remaining."
	print
end function

playerTurn = function(take)
	take = floor(val(take))
	if take < 1 or take > 3 then
		print "Take must be between 1 and 3."
		return false
	end if

	globals.tokens = tokens - take

	print "Player takes " + take + " tokens."
	printRemaining
	return true
end function

computerTurn = function()
	take = tokens % 4
	globals.tokens = tokens - take

	print "Computer takes " + take + " tokens."
	printRemaining
end function

while tokens > 0
	if playerTurn(input("How many tokens would you like to take? ")) then
		computerTurn
	end if
end while

print "Computer wins."


import strutils
import terminal

var tokens = 12

styledEcho(styleBright, "Nim in Nim\n")

proc echoTokens() =
  styledEcho(styleBright, "Tokens remaining: ", resetStyle, $tokens, "\n")

proc player() =
  var take = '0'
  styledEcho(styleBright, "- Your turn -")
  echo "How many tokens will you take?"
  while true:
    stdout.styledWrite(styleDim, "Take (1–3): ", resetStyle)
    take = getch()
    stdout.write(take, '\n')
    if take in {'1'..'3'}:
      tokens -= parseInt($take)
      break
    else:
      echo "Please choose a number between 1 and 3."
  echoTokens()

proc computer() =
  styledEcho(styleBright, "- Computer's turn -")
  let take = tokens mod 4
  tokens -= take
  styledEcho("Computer took ", styleBright, $take, " ",
             if take == 1: "token"
             else: "tokens")
  echoTokens()

while tokens > 0:
  player()
  computer()

styledEcho(styleBright, "Computer wins!")


let rec player_turn () =
  print_string "How many tokens would you like to take? ";
  let n = read_int_opt () |> Option.value ~default:0 in
  if n >= 1 && n <= 3 then n
  else (
    print_endline "Number must be between 1 and 3";
    player_turn ())

let computer_turn tokens = tokens mod 4

let plural_suffix = function 1 -> "" | _ -> "s"

let turn_report prefix taken tokens =
  Printf.printf "%s %d token%s.\n%d token%s remaining.\n%!" prefix taken
    (plural_suffix taken) tokens (plural_suffix tokens)

let rec play_game tokens =
  let player_tokens = player_turn () in
  let tokens = tokens - player_tokens in
  turn_report "You take" player_tokens tokens;
  let computer_tokens = computer_turn tokens in
  let tokens = tokens - computer_tokens in
  turn_report "Computer takes" computer_tokens tokens;
  if tokens = 0 then print_endline "Computer wins!" else play_game tokens

let () = play_game 12


use strict;
use warnings;
use feature 'say';

my $tokens = 12;
say "$tokens tokens remaining.\n";

while (1) {
    print "How many tokens do you want to remove; 1, 2 or 3? : ";
    (my $player = <>) =~ s/\s//g;
    say "Nice try. $tokens tokens remaining.\n" and next
        unless $player =~ /^[123]$/;
    $tokens -= 4;
    say "Computer takes @{[4 - $player]}.\n$tokens tokens remaining.\n";
    say "Computer wins." and last
        if $tokens <= 0;
}


without js -- getc
integer tokens = 12, player = 0

while true do
    printf(1,"%2d tokens remaining. ",tokens)
    if tokens=0 then printf(1,"Computer wins.\n") exit end if
    printf(1,"How many tokens do you want to remove; 1, 2, or 3?:")
    while player<1 or player>3 do player=getc(0)-'0' end while
    printf(1,"%d. Computer takes %d.\n",{player,4-player})
    tokens -= 4; player = 0
end while


int tokens = 12;

void get_tokens(int cur_tokens) {
	write("How many tokens would you like to take? ");
	int take = (int)Stdio.stdin->gets();

	if (take < 1 || take > 3) {
		write("Number must be between 1 and 3.\n");
		get_tokens(cur_tokens);
	}
	else {
		tokens = cur_tokens - take;
		write("You take " + (string)take + " tokens\n");
		write((string)tokens + " tokens remaing\n\n");
	}
}

void comp_turn(int cur_tokens) {
	int take = cur_tokens % 4;
	tokens = cur_tokens - take;
	write("Computer take " + (string)take + " tokens\n");
	write((string)tokens + " tokens remaing\n\n");
}

int main() {
	write("Pike Nim\n\n");
	while(tokens > 0) {
		get_tokens(tokens);
		comp_turn(tokens);
	}
	write("Computer wins!\n");
	return 0;
}


To run:
Start up.
Play the game of Nim.
Write "The computer wins! Press esc to exit." on the console.
Wait for the escape key.
Shut down.

A piece is a number.

To play the game of Nim:
Put 12 into a piece count.
Loop.
If the piece count is 0, exit.
Write "There are " then the piece count then " pieces remaining." on the console.
Ask the player to take some pieces.
Subtract the pieces from the piece count.
Ask the computer to take some other pieces given the pieces.
Subtract the other pieces from the piece count.
Repeat.

To ask the player to take some pieces:
Write "Would you like to take 1, 2, or 3 pieces? " on the console without advancing.
Read a count from the console.
If the count is not between 1 and 3, repeat.
Format the count and "piece" or "pieces" into a string.
Write "You took " then the string then "." on the console.
Put the count into the pieces.

To ask the computer to take some pieces given some other pieces:
Put 4 minus the other pieces into a count.
Format the count and "piece" or "pieces" into a string.
Write "The computer took " then the string then "." on the console.
Put the count into the pieces.


nim :- next_turn(12), !.

next_turn(N) :-
	% Player Turn
	format('How many dots would you like to take? '),
	read_line_to_codes(user_input, Line),
	number_codes(PlayerGuess, Line),
	member(PlayerGuess,[1,2,3]),
	N1 is N - PlayerGuess,
	format('You take ~d dots~n~d dots remaining.~n~n', [PlayerGuess, N1]),

	% Computer Turn
	CompGuess is 4 - PlayerGuess,
	N2 is N1 - CompGuess,
	format('Computer takes ~d dots~n~d dots remaining.~n~n', [CompGuess, N2]),
	(
		N2 = 0
		-> format('Computer wins!')
		; next_turn(N2)
	).


print("Py Nim\n")

def getTokens(curTokens):
	global tokens

	print("How many tokens would you like to take? ", end='')
	take = int(input())

	if (take < 1 or take > 3):
		print("Number must be between 1 and 3.\n")
		getTokens(curTokens)
		return

	tokens = curTokens - take
	print(f'You take {take} tokens.')
	print(f'{tokens} tokens remaining.\n')

def compTurn(curTokens):
	global tokens

	take = curTokens % 4
	tokens = curTokens - take
	print (f'Computer takes {take} tokens.')
	print (f'{tokens} tokens remaining.\n')

tokens = 12
while (tokens > 0):
	getTokens(tokens)
	compTurn(tokens)

print("Computer wins!")


## Nim game
##

tokens <- 12

while(tokens > 0) {
  print(paste("Tokens remaining:",tokens))
  playertaken <- 0
  while(playertaken == 0) {
    playeropts <- c(1:min(c(tokens,3)))
    playertaken <- menu(playeropts, title = "Your go, how many tokens will you take? ")
    tokens <- tokens - playertaken
    if(tokens == 0) {print("Well done you won, that shouldn't be possible!")}
  }
  cputaken <- 4 - playertaken
  tokens <- tokens - cputaken
  print(paste("I take",cputaken,"tokens,",tokens,"remain"))
  if(tokens == 0) {print("I win!")}

}


#lang racket

(define (print-remaining tokens-remaining)
  (printf "~a tokens remain.\n" tokens-remaining))

(define (read-tokens)
  (define num (read))
  (cond
    [(and (natural? num) (< num 4)) num]
    [else
     (display "Please enter a number between 1 to 3\n")
     (read-tokens)]))

(define (pturn tokens-remaining)
  (cond
    [(not (zero? tokens-remaining))
        (print-remaining tokens-remaining)
        (display "Your turn. How many tokens? ")
        (define n (read-tokens))
        (cturn (- tokens-remaining n) n)]
    [else (display "Computer wins!")]))

(define (cturn tokens-remaining p-took)
  (cond
    [(not (zero? tokens-remaining))
      (print-remaining tokens-remaining)
      (define c-take (- 4 p-took))
      (printf "Computer takes ~a tokens\n" c-take)
      (pturn (- tokens-remaining c-take))]
  [else (display "You win!")]))

(pturn 12)


say my $tokens = 12, " tokens remaining.\n";

loop {
    my $player = trim prompt "How many tokens do you want to remove; 1, 2 or 3? : ";
    say "Nice try. $tokens tokens remaining.\n" and
    next unless $player eq any <1 2 3>;
    $tokens -= 4;
    say "Computer takes {4 - $player}.\n$tokens tokens remaining.\n";
    say "Computer wins." and last if $tokens <= 0;
}


Red [
    date: 2021-10-24
    version: 0.6.4
    summary: "Demonstrate the game of Nim in Red for Rosetta Code"
]

take-tokens: function [
    "Ask the user to take between 1 and 3 tokens."
][
    forever [
        n: trim ask "Would you like to take 1, 2, or 3 tokens (q to quit)? "
        if n = "q" [quit]
        n: try [to-integer n]
        case [
            not integer? n [print "Please enter an integer."]
            any [n < 1 n > 3] [print "Please enter a number between 1 and 3."]
            true [return n]
        ]
    ]
]

tokens: 12
while [tokens > 0][
    print ["There are" tokens "tokens remaining."]
    n: take-tokens
    print ["You took" n "tokens."]
    tokens: tokens - n
    print ["Computer takes" 4 - n "tokens."]
    tokens: subtract tokens subtract 4 n
]
print "Computer wins!"


/*REXX program plays the NIM game with a human opponent; the pot size can be specified. */
parse arg pot _ . 1 __                           /*obtain optional argument from the CL.*/
if pot=='' | pot==","  then pot= 12              /*Not specified?  Then use the default.*/
if _\==''       then do; call ser "Too many arguments entered: "    __;     exit 13;   end
if \isNum(pot)  then do; call ser "argument isn't numeric: "       pot;     exit 13;   end
if \isInt(pot)  then do; call ser "argument isn't an integer: "    pot;     exit 13;   end
if pot<4        then do; call ser "The pot number is too small: "  pot;     exit 13;   end
if pot>100      then do; call ser "The pot number is too large: "  pot;     exit 13;   end
pad= copies('─', 8)                              /*literal used as an eyecatcher in msgs*/
pot= pot/1                                       /*normalize the pot  (number).         */
t= pot//4
if pot>12 & t\==0  then do;        say pad 'The computer takes '      t      " token"s(t).
                                   pot= pot - t
                        end

     do forever;   call show pot
            do  until ok;                   ok= 1;              say
            say pad "How many tokens do you want to take away  (1, 2, or 3)    (or QUIT)?"
            parse pull t _ . 1 q 1 __;      upper q;            say
            if abbrev('QUIT',q,1)  then do;  say pad 'Quitting.';         exit 1;      end
            if t=''                then call ser "No arguments entered."
            if _\==''              then call ser "Too many arguments entered: "        __
            if \isNum(t)           then call ser "Argument isn't numeric: "             t
            if \isInt(t)           then call ser "Argument isn't an integer: "          t
            if t<1                 then call ser "Argument can't be less than 1: "      t
            if t>3                 then call ser "Argument can't be greater than 3: "   t
            end   /*while*/
     t= t/1                                      /*Normalize the number:  001   2.  +3  */
     #= max(1, 4-t)                              /*calculate the computer's take─away.  */
     say pad 'The computer takes '    #    " token"s(#).
     pot= pot - t - #                            /*calculate the number of tokens in pot*/
     if pot==0  then do;   say pad 'No tokens left.'       /*No tokens left in the pot? */
                           say pad "The computer wins!"    /*Display a braggart message.*/
                           exit                            /*exit this computer program.*/
                     end
     end   /*forever*/                           /*keep looping until there's a winner. */
exit                                             /*stick a fork in it,  we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
isNum: return datatype( arg(1), 'N')             /*verify that the arg is a  number.    */
isInt: return datatype( arg(1), 'W')             /*   "     "   "   "   " an integer.   */
show:  say;  say pad "Tokens remaining: "  arg(1)' ' pad;  say;  return
s:     if arg(1)==1  then return arg(3);                         return word(arg(2) 's',1)
ser:   if ok  then say pad '***error***' arg(1);       ok= 0;    return


# Project : CalmoSoft Nim Game
# Date    : 16/04/2020-13:27:07
# Update  : 31/03/2021-19:41:09
# Author  : Gal Zsolt (~ CalmoSoft ~)
# Email   : <[email protected]>

load "stdlib.ring"
load "guilib.ring"

limit = 4
limit1 = 1
limit2 = 3
limit3 = 5
limit4 = 7

match1 = limit1
match2 = limit2
match3 = limit3
match4 = limit4

move1 = 0
move2 = 0
move3 = 0
move4 = 0

Button1 = list(limit1)
Button2 = list(limit2)
Button3 = list(limit3)
Button4 = list(limit4)

pcMove = 0

width = 60
height = 60

yourScore = 0
pcScore = 0

C_FONTSIZE = 15
C_NIM = "images/nim.jpg"
C_COMPUTER = "images/computer.jpg"
C_PROGRAMMER = "images/programmer.jpg"

app = new qApp
{
      win = new qWidget() {
            app.StyleFusionBlack()
	    setWindowTitle('CalmoSoft Nim Game')
	    setWinIcon(self,"images/nim.jpg")
	    setWindowFlags(Qt_SplashScreen | Qt_CustomizeWindowHint)
	    reSize(620,460)

            for Col = 1 to limit1
		Button1[Col] = new QPushButton(win) {
                          y = 230+(Col-1)*height
                          setgeometry(y+10,70,width,height)
                          setSizePolicy(1,1)
                          seticon(new qicon(new qpixmap(C_NIM)))
                          setIconSize(new qSize(60,60))
                          }
	    next

            for Col = 1 to limit2
		Button2[Col] = new QPushButton(win) {
                          y = 170+(Col-1)*height
                          setgeometry(y+10,150,width,height)
                          setSizePolicy(1,1)
                          seticon(new qicon(new qpixmap(C_NIM)))
                          setIconSize(new qSize(60,60))
                          }
	    next

            for Col = 1 to limit3
		Button3[Col] = new QPushButton(win) {
                          y = 110+(Col-1)*height
                          setgeometry(y+10,230,width,height)
                          setSizePolicy(1,1)
                          seticon(new qicon(new qpixmap(C_NIM)))
                          setIconSize(new qSize(60,60))
                          }
	    next

            for Col = 1 to limit4
		Button4[Col] = new QPushButton(win) {
                          y = 50+(Col-1)*height
                          setgeometry(y+10,310,width,height)
                          setSizePolicy(1,1)
                          seticon(new qicon(new qpixmap(C_NIM)))
                          setIconSize(new qSize(60,60))
                          }
	    next

	    Row1 = new QPushButton(win) {
                   setgeometry(500,70,width,height)
                   setStyleSheet("color:Black;background-color:Orange")
                   setSizePolicy(1,1)
                   setclickevent("deleteRow1()")
                   settext("Row1") }

	    Row2 = new QPushButton(win) {
                   setgeometry(500,150,width,height)
                   setStyleSheet("color:Black;background-color:Orange")
                   setSizePolicy(1,1)
                   setclickevent("deleteRow2()")
                   settext("Row2") }

	    Row3 = new QPushButton(win) {
                   setgeometry(500,230,width,height)
                   setStyleSheet("color:Black;background-color:Orange")
                   setSizePolicy(1,1)
                   setclickevent("deleteRow3()")
                   settext("Row3") }

	    Row4 = new QPushButton(win) {
                   setgeometry(500,310,width,height)
                   setStyleSheet("color:Black;background-color:Orange")
                   setSizePolicy(1,1)
                   setclickevent("deleteRow4()")
                   settext("Row4") }

	    labelYourScore = new QLabel(win) { setgeometry(60,20,150,30)
		             setFont(new qFont("Verdana",C_FONTSIZE,50,0))
                             settext("Your score: 0") }

	    labelComputerScore = new QLabel(win) { setgeometry(350,20,150,30)
		                setFont(new qFont("Verdana",C_FONTSIZE,50,0))
                                settext("PC score: 0") }

	    btnNewGame = new QPushButton(win) { setgeometry(60,400,80,30)
			     setFont(new qFont("Verdana",C_FONTSIZE,50,0))
                             settext("New")
                             setclickevent("newGame()") }

	    btnExit = new QPushButton(win) { setgeometry(400,400,80,30)
			  setFont(new qFont("Verdana",C_FONTSIZE,50,0))
                          settext("Exit")
                          setclickevent("pQuit()") }

	    btnPcMove = new QPushButton(win) { setgeometry(200,400,140,30)
		        setFont(new qFont("Verdana",C_FONTSIZE,50,0))
                        settext("PC move")
                        setclickevent("pcMove()") }

            show()
   }
   exec()
}

func deleteRow1()
     if move2 = 1 or move3 = 1 or move4 = 1
        move1 = 0
        return
     else
        move1 = 1
     ok
     if (match1 > 0) and (move1 = 1)
        if pcMove = 1
        Button1[match1] { seticon(new qicon(new qpixmap(C_COMPUTER)))
                          setIconSize(new qSize(55,55))
                          setenabled(false) }
        match1 = match1 - 1
        move1 = 0
        ok

        if pcMove = 0
        Button1[match1] { seticon(new qicon(new qpixmap(C_PROGRAMMER)))
                          setIconSize(new qSize(55,55))
                          setenabled(false) }
        match1 = match1 - 1
        ok
        gameOver()
     ok

func deleteRow2()
     if move1 = 1 or move3 = 1 or move4 = 1
        move2 = 0
        return
     else
        move2 = 1
     ok
     if match2 > 0 and move2 = 1
        if pcMove = 1
        Button2[match2] { seticon(new qicon(new qpixmap(C_COMPUTER)))
                          setIconSize(new qSize(55,55))
                          setenabled(false) }
        match2 = match2 - 1
        move2 = 0
        ok

        if pcMove = 0
        Button2[match2] { seticon(new qicon(new qpixmap(C_PROGRAMMER)))
                          setIconSize(new qSize(55,55))
                          setenabled(false) }
        match2 = match2 - 1
        ok
        gameOver()
     ok

func deleteRow3()
     if move1 = 1 or move2 = 1 or move4 = 1
        move3 = 0
        return
     else
        move3 = 1
     ok
     if match3 > 0 and move3 = 1
        if pcMove = 1
        Button3[match3] { seticon(new qicon(new qpixmap(C_COMPUTER)))
                          setIconSize(new qSize(55,55))
                          setenabled(false) }
        match3 = match3 - 1
        move3 = 0
        ok

        if pcMove = 0
        Button3[match3] { seticon(new qicon(new qpixmap(C_PROGRAMMER)))
                          setIconSize(new qSize(55,55))
                          setenabled(false) }
        match3 = match3 - 1
        ok
        gameOver()
     ok

func deleteRow4()
     if move1 = 1 or move2 = 1 or move3 = 1
        move4 = 0
        return
     else
        move4 = 1
     ok
     if match4 > 0 and move4 = 1
        if pcMove = 1
        Button4[match4] { seticon(new qicon(new qpixmap(C_COMPUTER)))
                          setIconSize(new qSize(55,55))
                          setenabled(false) }
        match4 = match4 - 1
        move4 = 0
        ok

        if pcMove = 0
        Button4[match4] { seticon(new qicon(new qpixmap(C_PROGRAMMER)))
                          setIconSize(new qSize(55,55))
                          setenabled(false) }
        match4 = match4 - 1
        ok
        gameOver()
     ok

func pcMove()

     move1 = 0
     move2 = 0
     move3 = 0
     move4 = 0
     pcMove = 1
     for n = 1 to limit
         if match1 > 0
            rnd = random(match1-1)+1
            for m = 1 to rnd
                deleteRow1()
            next
            exit
         ok

         if match2 > 0
            rnd = random(match2-1)+1
            for m = 1 to rnd
                deleteRow2()
            next
            exit
         ok

         if match3 > 0
             rnd = random(match3-1)+1
             for m = 1 to rnd
                 deleteRow3()
             next
             exit
          ok

          if match4 > 0
             rnd = random(match4-1)+1
             for m = 1 to rnd
                 deleteRow4()
             next
             exit
          ok
     next
     pcMove = 0

func gameOver()
     if (match1 = 0) and (match2 = 0) and (match3 = 0) and (match4 = 0)
        if pcMove = 0
           pcScore = pcScore + 1
           labelComputerScore.settext("PC score: " + string(pcScore))
           msgBox("Game Over! You Lost!")
        else
           yourScore = yourScore + 1
           labelYourScore.settext("Your score: " + string(yourScore))
           msgBox("Game Over! You Win!")
        ok
     ok

func newGame()

     match1 = limit1
     match2 = limit2
     match3 = limit3
     match4 = limit4

     move1 = 0
     move2 = 0
     move3 = 0
     move4 = 0

     pcMove = 0

     for Col = 1 to limit1
	 Button1[Col] = new QPushButton(win) {
                        y = 230+(Col-1)*height
                        setgeometry(y+10,70,width,height)
                        setSizePolicy(1,1)
                        seticon(new qicon(new qpixmap(C_NIM)))
                        setIconSize(new qSize(60,60))
                        show()
                        }
	next

        for Col = 1 to limit2
	    Button2[Col] = new QPushButton(win) {
                           y = 170+(Col-1)*height
                           setgeometry(y+10,150,width,height)
                           setSizePolicy(1,1)
                           seticon(new qicon(new qpixmap(C_NIM)))
                           setIconSize(new qSize(60,60))
                           show()
                           }
	next

        for Col = 1 to limit3
	    Button3[Col] = new QPushButton(win) {
                           y = 110+(Col-1)*height
                           setgeometry(y+10,230,width,height)
                           setSizePolicy(1,1)
                           seticon(new qicon(new qpixmap(C_NIM)))
                           setIconSize(new qSize(60,60))
                           show()
                           }
	next

        for Col = 1 to limit4
	    Button4[Col] = new QPushButton(win) {
                           y = 50+(Col-1)*height
                           setgeometry(y+10,310,width,height)
                           setSizePolicy(1,1)
                           seticon(new qicon(new qpixmap(C_NIM)))
                           setIconSize(new qSize(60,60))
                           show()
                           }
	next

func msgBox(cText)
     mb = new qMessageBox(win) {
	  setWindowTitle('CalmoSoft Nim Game')
	  setText(cText)
          setstandardbuttons(QMessageBox_OK)
          result = exec()
     }

func pQuit()
     win.close()
     app.Quit()


[12, 8, 4].each do |remaining|
  puts "There are #{remaining} dots.\nHow many dots would you like to take? "
  unless (num=gets.to_i).between?(1, 3)
    puts "Please enter one of 1, 2 or 3"
    redo
  end
  puts "You took #{num} dots, leaving #{remaining-num}.\nComputer takes #{4-num}.\n\n"
end

puts "Computer took the last and wins."


fn main() {
    let mut tokens = 12;
    println!("Nim game");
    println!("Starting with {} tokens.", tokens);
    println!("");

    loop {
        tokens = p_turn(&tokens);
        print_remaining(&tokens);
        tokens = c_turn(&tokens);
        print_remaining(&tokens);

        if tokens == 0 {
            println!("Computer wins!");
            break;
        }
    }
}

fn p_turn(tokens: &i32) -> i32 {
    loop {  //try until we get a good number
        println!("How many tokens would you like to take?");

        let mut take = String::new();
        io::stdin().read_line(&mut take)
            .expect("Sorry, I didn't understand that.");

        let take: i32 = match take.trim().parse() {
            Ok(num) => num,
            Err(_) => {
                println!("Invalid input");
                println!("");
                continue;
            }
        };

        if take > 3 || take < 1 {
            println!("Take must be between 1 and 3.");
            println!("");
            continue;
        }

        return tokens - take;
    }
}

fn c_turn(tokens: &i32) -> i32 {
    let take = tokens % 4;

    println!("Computer takes {} tokens.", take);

    return tokens - take;
}

fn print_remaining(tokens: &i32) {
    println!("{} tokens remaining.", tokens);
    println!("");
}


$constant maxtokens = 12
$constant machine = 0
$constant human = 1
$constant false = 0
$constant true = 0FFFFH

procedure welcome
  print "Welcome to the Game of Nim."
  print "We begin with";maxtokens;" tokens. On each turn, a player"
  print "may take between 1 and 3 tokens. The player who takes the"
  print "last token wins."
  print
end

procedure show(n = integer)
  var i = integer
  print "Available tokens:";n;"  ";
  rem - provide a visual display
  for i =  1 to n
    print "o ";
  next i
  print
end

function getnum(lowlim, toplim = integer) = integer
  var ok, n = integer
  repeat
    begin
      input "You take:";n
      if n < lowlim or n > toplim then
        begin
          print "Must take between";lowlim;" and";toplim
          print "Try again."
          ok = false
        end
      else
        ok = true
    end
  until ok
end = n

function play(player, tokens, taken = integer) = integer
  if player = human then
      taken = getnum(1,3)
  else
      taken = 4 - taken
end = taken

procedure report(player = integer)
  if player = human then
    print "You took the last one. You win. Congratulations!"
  else
    print "I took the last one, so I win. Sorry about that."
end

var player, tokens, taken  = integer

welcome
tokens = maxtokens
taken = 0
player = human
print "You go first."
repeat
  begin
    show tokens
    taken = play(player, tokens, taken)
    tokens = tokens - taken
    if player = machine then print "I took:";taken
    if tokens > 0 then player = 1 - player
  end
until tokens = 0
report player
print "Thanks for playing!"

end


var tokens = 12

def playerTurn(curTokens: Int): Unit =
{
  val take = readLine("How many tokens would you like to take? ").toInt
  if (take < 1 || take > 3) {
    println("Number must be between 1 and 3.")
    playerTurn(curTokens)
  }
  else {
    tokens = curTokens - take
    println(s"You take $take tokens. $tokens tokens remaining.\n")
  }
}

def compTurn(curTokens: Int): Unit =
{
  val take = curTokens % 4
  tokens = curTokens - take
  println(s"Computer takes $take tokens. $tokens remaining.\n")
}

def main(args: Array[String]): Unit =
{
  while (tokens > 0)
  {
    playerTurn(tokens)
    compTurn(tokens)
  }
  println("Computer wins!")
}


Object subclass: Nim [
    | tokens |
    <comment: 'I am a game of nim'>
    Nim class >> new [
        <category: 'instance creation'>
        ^(super new) init: 12
    ]

    init: t [
        <category: 'instance creation'>
        tokens := t.
        ^self
    ]

    pTurn [
        | take |
        <category: 'gameplay'>
        Transcript nextPutAll: 'How many tokens will you take?: '.
        take := (stdin nextLine) asNumber.
        ((take < 1) | (take > 3))
            ifTrue: [Transcript nextPutAll: 'Invalid input';nl;nl. self pTurn]
            ifFalse: [tokens := tokens - take]
    ]

    cTurn [
        | take |
        <category: 'gameplay'>
        take := tokens - (4 * (tokens // 4)).    "tokens % 4"
        Transcript nextPutAll: 'Computer takes '.
        take printOn: Transcript.
        Transcript nextPutAll: ' tokens';nl.
        tokens := tokens - take
    ]

    mainLoop [
        <category: 'main loop'>
        Transcript nextPutAll: 'Nim game';nl.
        Transcript nextPutAll: 'Starting with '.
        tokens printOn: Transcript.
        Transcript nextPutAll: ' tokens';nl;nl.
        1 to: 3 do: [ :n |    "The computer always wins on the 3rd turn"
            self pTurn.
            self printRemaining.
            self cTurn.
            self printRemaining.
            (tokens = 0)
                ifTrue:[Transcript nextPutAll: 'Computer wins!';nl. ^0]
        ]
    ]

    printRemaining [
        <category: 'information'>
        tokens printOn: Transcript.
        Transcript nextPutAll: ' tokens remaining';nl;nl
    ]
]

g := Nim new.
g mainLoop.


var tokens = 12

while tokens != 0 {
  print("Tokens remaining: \(tokens)\nPlease enter a number between 1 and 3: ", terminator: "")

  guard let input = readLine(), let n = Int(input), n >= 1 && n <= 3 else {
    fatalError("Invalid input")
  }

  tokens -= n

  if tokens == 0 {
    print("You win!")

    break
  }

  print("I'll remove \(4 - n) tokens.")

  tokens -= 4 - n

  if tokens == 0 {
    print("I win!")
  }

  print()
}


10 LET H = 12
20 PRINT "There are"
30 PRINT H
40 PRINT "tokens remaining. How many would you like to take?"
50 INPUT T
60 IF T > 3 THEN GOTO 170
70 IF T < 1 THEN GOTO 170
80 LET H = H - T
90 IF H = 0 THEN GOTO 190
100 LET T = 4 - T
110 PRINT "I will take"
120 PRINT T
130 PRINT "tokens."
140 LET H = H - T
150 IF H = 0 THEN GOTO 210
160 GOTO 20
170 PRINT "You must take 1, 2, or 3 tokens."
180 GOTO 50
190 PRINT "Congratulations. You got the last token."
200 END
210 PRINT "I got the last token. I win. Better luck next time."
220 END


LET monton = 12
LET llevar = 0

DO WHILE monton > 0
   PRINT "Quedan"; monton; "fichas. ¿Cuántas te gustaría tomar";
   INPUT llevar
   DO WHILE llevar = 0 OR llevar > 3
      PRINT "Debes tomar 1, 2, o 3 fichas. ¿Cuántas te gustaría tomar";
      INPUT llevar
   LOOP

   PRINT "Es mi turno, tomaré"; 4-llevar; "ficha(s)."
   LET monton = monton - 4
LOOP

PRINT
SET COLOR 2
PRINT "Obtuve la última ficha. ¡Gané! Mejor suerte la próxima vez."
END


import os { input }

fn show_tokens(tokens int) {
    println('Tokens remaining $tokens\n')
}

fn main() {
    mut tokens := 12
    for {
        show_tokens(tokens)
        t := input('  How many tokens 1, 2, or 3? ').int()
        if t !in [1, 2, 3] {
            println('\nMust be a number between 1 and 3, try again.\n')
        } else {
            ct := 4 - t
            mut s := 's'
            if ct == 1 {
                s = ''
            }
            println('  Computer takes $ct token$s \n')
            tokens -= 4
        }
        if tokens == 0 {
            show_tokens(0)
            println('  Computer wins!')
            return
        }
    }
}


import "io" for Stdin, Stdout

var showTokens = Fn.new { |tokens| System.print("Tokens remaining %(tokens)\n") }

var tokens = 12
while (true) {
    showTokens.call(tokens)
    System.write("  How many tokens 1, 2 or 3? ")
    Stdout.flush()
    var t = Num.fromString(Stdin.readLine())
    if (t.type != Num || !t.isInteger || t < 1 || t > 3) {
        System.print("\nMust be an integer between 1 and 3, try again.\n")
    } else {
        var ct = 4 - t
        var s = (ct != 1) ? "s" : ""
        System.write("  Computer takes %(ct) token%(s)\n\n")
        tokens = tokens - 4
    }
    if (tokens == 0) {
        showTokens.call(0)
        System.print("  Computer wins!")
        break
    }
}


F makeList(separator)
   V counter = 1

   F makeItem(item)
      -V result = @counter‘’@separator‘’item"\n"
      @counter++
      R result

   R makeItem(‘first’)‘’makeItem(‘second’)‘’makeItem(‘third’)

print(makeList(‘. ’))


with Ada.Text_IO;

procedure Nested_Functions is -- 'Nested_Functions' is the name of 'main'

   type List is array(Natural range <>) of String(1 .. 10);

   function Make_List(Separator: String) return List is
      Counter: Natural := 0;

      function Make_Item(Item_Name: String) return String is
      begin
	 Counter := Counter + 1; -- local in Make_List, global in Make_Item
	 return(Natural'Image(Counter) & Separator & Item_Name);
      end Make_Item;

   begin
      return (Make_Item("First "), Make_Item("Second"), Make_Item("Third "));
   end Make_List;

begin -- iterate through the result of Make_List
   for Item of Make_List(". ") loop
      Ada.Text_IO.Put_Line(Item);
   end loop;
end Nested_Functions;


;program starts here, after loading palettes etc.
MOVE.W #3,D1
MOVE.W #'.',D4

JSR MakeList

jmp *              ;halt

MakeList:
	MOVE.W #1,D0
loop_MakeList:
	MOVE.W D0,-(SP)
	        JSR PrintHex
		MOVE.B D4,D0             ;load separator into D0
		JSR PrintChar
		MOVE.B #' ',D0
		JSR PrintChar
	MOVE.W (SP)+,D0
	JSR MakeItem
	CMP.W D0,D1
	BCC loop_MakeList		 ;back to start
	RTS

MakeItem:
	MOVE.W D0,D2
	SUBQ.W #1,D2
	LSL.W #2,D2
	LEA PointerToText,A0
	MOVE.L (A0,D2),A3
	JSR PrintString
	JSR NewLine
	ADDQ.W #1,D0
	RTS

PointerToText:
	DC.L FIRST,SECOND,THIRD

FIRST:
	DC.B "FIRST",0
	EVEN
SECOND:
	DC.B "SECOND",0
	EVEN
THIRD:
	DC.B "THIRD",0
	EVEN


PROC make list = ( STRING separator )STRING:
     BEGIN
        INT counter := 0;
        PROC make item = ( STRING item )STRING:
             BEGIN
                counter +:= 1;
                whole( counter, 0 ) + separator + item + REPR 10
             END; # make item #
        make item( "first" ) + make item( "second" ) + make item( "third" )
     END; # make list #

print( ( make list( ". " ) ) )


begin
    string(30) procedure makeList ( string(2) value separator ) ;
        begin
            string(30) listValue;
            integer counter;
            string(10) procedure makeItem ( string(6) value item
                                          ; integer   value length
                                          ) ;
                begin
                    string(10) listItem;
                    counter := counter + 1;
                    listItem( 0 // 1 ) := code( decode( "0" ) + counter );
                    listItem( 1 // 2 ) := separator;
                    listItem( 3 // 6 ) := item;
                    listItem( 3 + length // 1 ) := code( 10 );
                    listItem
                end; % makeItem %
                counter   := 0;
                listValue := makeItem( "first", 5 );
                listValue(  9 // 10 ) := makeItem( "second", 6 );
                listValue( 19 // 10 ) := makeItem( "third",  5 );
                listValue
         end; % makeList %
    write( makeList( ". " ) )
end.


--------------------- NESTED FUNCTION --------------------

-- makeList :: String -> String
on makeList(separator)
    set counter to 0

    -- makeItem :: String -> String
    script makeItem
        on |λ|(x)
            set counter to counter + 1

            (counter & separator & x & linefeed) as string
        end |λ|
    end script

    map(makeItem, ["first", "second", "third"]) as string
end makeList

--------------------------- TEST -------------------------
on run

    makeList(". ")

end run

-------------------- GENERIC FUNCTIONS -------------------

-- mReturn :: First-class m => (a -> b) -> m (a -> b)
on mReturn(f)
    -- 2nd class handler function lifted into 1st class script wrapper.
    if script is class of f then
        f
    else
        script
            property |λ| : f
        end script
    end if
end mReturn

-- map :: (a -> b) -> [a] -> [b]
on map(f, xs)
    -- The list obtained by applying f
    -- to each element of xs.
    tell mReturn(f)
        set lng to length of xs
        set lst to {}
        repeat with i from 1 to lng
            set end of lst to |λ|(item i of xs, i, xs)
        end repeat
        return lst
    end tell
end map


makeList: function [separator][
    counter: 1

    makeItem: function [item] .export:[counter][
        result: ~"|counter||separator||item|"
        counter: counter+1
        return result
    ]

    @[
        makeItem "first"
        makeItem "second"
        makeItem "third"
    ]
]

print join.with:"\n" makeList ". "


(* ****** ****** *)
//
#include
"share/atspre_staload.hats"
//
(* ****** ****** *)

fun
MakeList
(
  sep: string
) : void = let
//
var count: int = 0
//
val count =
  $UNSAFE.cast{ref(int)}([email protected])
//
fun
MakeItem
(
  item: string
) : void = let
  val () = !count := !count+1
in
  println! (!count, sep, item)
end // end of [MakeItem]
//
in
  MakeItem"first"; MakeItem"second"; MakeItem"third"
end // end of [MakeList]

(* ****** ****** *)

implement main0() = { val () = MakeList". " }

(* ****** ****** *)


MakeList ← {
    nl←@+10 ⋄ s←𝕩 ⋄ i←0
    MakeItem ← {i+↩1 ⋄ (•Fmt i)∾s∾𝕩}
    (⊣∾nl∾⊢)´MakeItem¨"first"‿"second"‿"third"
}


#include<stdlib.h>
#include<stdio.h>

typedef struct{
	char str[30];
}item;

item* makeList(char* separator){
	int counter = 0,i;
	item* list = (item*)malloc(3*sizeof(item));

	item makeItem(){
		item holder;

		char names[5][10] = {"first","second","third","fourth","fifth"};

		sprintf(holder.str,"%d%s%s",++counter,separator,names[counter]);

		return holder;
	}

	for(i=0;i<3;i++)
		list[i] = makeItem();

	return list;
}

int main()
{
	int i;
	item* list = makeList(". ");

	for(i=0;i<3;i++)
		printf("\n%s",list[i].str);

	return 0;
}


string MakeList(string separator)
{
    int counter = 1;

    Func<string, string> makeItem = item => counter++ + separator + item + "\n";

    return makeItem("first") + makeItem("second") + makeItem("third");
}

Console.WriteLine(MakeList(". "));


#include <iostream>
#include <string>
#include <vector>

std::vector<std::string> makeList(std::string separator) {
  auto counter = 0;
  auto makeItem = [&](std::string item) {
    return std::to_string(++counter) + separator + item;
  };
  return {makeItem("first"), makeItem("second"), makeItem("third")};
}

int main() {
  for (auto item : makeList(". "))
    std::cout << item << "\n";
}


(defn make-list [separator]
  (let [x (atom 0)]
    (letfn [(make-item [item] (swap! x inc) (println (format "%s%s%s" @x separator item)))]
      (make-item "first")
      (make-item "second")
      (make-item "third"))))

(make-list ". ")


(defun my-make-list (separator)
  (let ((counter 0))
    (flet ((make-item (item)
              (format nil "~a~a~a~%" (incf counter) separator item)))
      (concatenate 'string
                   (make-item "first")
                   (make-item "second")
                   (make-item "third")))))

(format t (my-make-list ". "))


include "cowgol.coh";
include "strings.coh";

sub MakeList(sep: [uint8], buf: [uint8]): (out: [uint8]) is
    out := buf; # return begin of buffer for ease of use
    var counter: uint32 := 0;

    # Add item to string
    sub AddStr(str: [uint8]) is
        var length := StrLen(str);
        MemCopy(str, length, buf);
        buf := buf + length;
    end sub;

    sub MakeItem(item: [uint8]) is
        counter := counter + 1;
        buf := UIToA(counter, 10, buf);
        AddStr(sep);
        AddStr(item);
        AddStr("\n");
    end sub;

    MakeItem("first");
    MakeItem("second");
    MakeItem("third");
    [buf] := 0; # terminate string
end sub;

var buffer: uint8[100];

print(MakeList(". ", &buffer as [uint8]));


string makeList(string seperator) {
    int counter = 1;

    string makeItem(string item) {
        import std.conv : to;
        return to!string(counter++) ~ seperator ~ item ~ "\n";
    }

    return makeItem("first") ~ makeItem("second") ~ makeItem("third");
}

void main() {
    import std.stdio : writeln;
    writeln(makeList(". "));
}


import extensions;

MakeList(separator)
{
    var counter := 1;

    var makeItem := (item){ var retVal := counter.toPrintable() + separator + item + (forward newLine); counter += 1; ^ retVal };

    ^ makeItem("first") + makeItem("second") + makeItem("third")
}

public program()
{
    console.printLine(MakeList(". "))
}


defmodule Nested do
  def makeList(separator) do
    counter = 1

    makeItem = fn {}, item ->
                      {"#{counter}#{separator}#{item}\n", counter+1}
                  {result, counter}, item ->
                      {result <> "#{counter}#{separator}#{item}\n", counter+1}
               end

    {} |> makeItem.("first") |> makeItem.("second") |> makeItem.("third") |> elem(0)
  end
end

IO.write Nested.makeList(". ")


USING: io kernel math math.parser locals qw sequences ;
IN: rosetta-code.nested-functions

:: make-list ( separator -- str )
    1 :> counter!
    [| item |
        counter number>string separator append item append
        counter 1 + counter!
    ] :> make-item
    qw{ first second third } [ make-item call ] map "\n" join
;

". " make-list write


      FUNCTION F(X)
       REAL X
       DIST(U,V,W) = X*SQRT(U**2 + V**2 + W**2)    !The contained function.
        T = EXP(X)
        F = T + DIST(T,SIN(X),ATAN(X) + 7)         !Invoked...
      END


// In Pascal, functions always _have_ to return _some_ value,
// but the the task doesn’t specify what to return.
// Hence makeList and makeItem became procedures.
procedure makeList(const separator: string);
// The var-section for variables that ought to be accessible
// in the routine’s body as well as the /nested/ routines
// has to appear /before/ the nested routines’ definitions.
var
	counter: 1..high(integer);

	procedure makeItem;
	begin
		write(counter, separator);
		case counter of
			1:
			begin
				write('first');
			end;
			2:
			begin
				write('second');
			end;
			3:
			begin
				write('third');
			end;
		end;
		writeLn();
		counter := counter + 1;
	end;
// You can insert another var-section here, but variables declared
// in this block would _not_ be accessible in the /nested/ routine.
begin
	counter := 1;
	makeItem;
	makeItem;
	makeItem;
end;


' FB 1.05.0 Win64

Sub makeItem(sep As String, ByRef counter As Integer, text As String)
  counter += 1
  Print counter; sep; text
End Sub

Sub makeList(sep As String)
  Dim a(0 To 2) As String = {"first", "second", "third"}
  Dim counter As Integer = 0
  While counter < 3
    makeItem(sep, counter, a(counter))
  Wend
End Sub

makeList ". "
Print
Print "Press any key to quit"
Sleep


package main
import "fmt"

func makeList(separator string) string {
    counter := 1

    makeItem := func(item string) string {
        result := fmt.Sprintf("%d%s%s\n", counter, separator, item)
        counter += 1
        return result
    }

    return makeItem("first") + makeItem("second") + makeItem("third")
}

func main() {
    fmt.Print(makeList(". "))
}


import Control.Monad.ST
import Data.STRef

makeList :: String -> String
makeList separator = concat $ runST $ do
  counter <- newSTRef 1
  let makeItem item = do
        x <- readSTRef counter
        let result = show x ++ separator ++ item ++ "\n"
        modifySTRef counter (+ 1)
        return result
  mapM makeItem ["first", "second", "third"]

main :: IO ()
main = putStr $ makeList ". "


makeList := method(separator,
    counter := 1
    makeItem := method(item,
        result := counter .. separator .. item .. "\n"
        counter = counter + 1
        result
    )
    makeItem("first") .. makeItem("second") .. makeItem("third")
)
makeList(". ") print


MakeList=: dyad define
  sep_MakeList_=: x
  cnt_MakeList_=: 0
  ;MakeItem each y
)

MakeItem=: verb define
  cnt_MakeList_=: cnt_MakeList_+1
  (":cnt_MakeList_),sep_MakeList_,y,LF
)


import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Function;

public class NestedFunctionsDemo {

    static String makeList(String separator) {
        AtomicInteger counter = new AtomicInteger(1);

        Function<String, String> makeItem = item -> counter.getAndIncrement() + separator + item + "\n";

        return makeItem.apply("first") + makeItem.apply("second") + makeItem.apply("third");
    }

    public static void main(String[] args) {
        System.out.println(makeList(". "));
    }
}


function makeList(separator) {
  var counter = 1;

  function makeItem(item) {
    return counter++ + separator + item + "\n";
  }

  return makeItem("first") + makeItem("second") + makeItem("third");
}

console.log(makeList(". "));


def makeList(separator):
  # input: {text: _, counter: _}
  def makeItem(item):
     (.counter + 1) as $counter
     | .text += "\($counter)\(separator)\(item)\n"
     | .counter = $counter;

   {text:"", counter:0} | makeItem("first") | makeItem("second") | makeItem("third")
   | .text
;

makeList(". ")


/* Nested function, in Jsish */
function makeList(separator) {
  var counter = 1;

  function makeItem(item) {
    return counter++ + separator + item + "\n";
  }

  return makeItem("first") + makeItem("second") + makeItem("third");
}

;makeList('. ');

/*
=!EXPECTSTART!=
makeList('. ') ==> 1. first
2. second
3. third

=!EXPECTEND!=
*/


function makelist(sep::String)
    cnt = 1

    function makeitem(item::String)
        rst = string(cnt, sep, item, '\n')
        cnt += 1
        return rst
    end

    return makeitem("first") * makeitem("second") * makeitem("third")
end

print(makelist(". "))


// version 1.0.6

fun makeList(sep: String): String {
    var count = 0
    fun makeItem(item: String): String {
        count++
        return "$count$sep$item\n"
    }
    return makeItem("first") + makeItem("second") + makeItem("third")
}

fun main(args: Array<String>) {
    print(makeList(". "))
}


function makeList (separator)
    local counter = 0
    local function makeItem(item)
            counter = counter + 1
            return counter .. separator .. item .. "\n"
        end
    return makeItem("first") .. makeItem("second") .. makeItem("third")
end

print(makeList(". "))


Module Checkit {
      Make_List(". ")
      Sub Make_List(Separator$)
            Local Counter=0
            Make_Item("First")
            Make_Item("Second")
            Make_Item("Third")
      End Sub
      Sub Make_Item(Item_Name$)
            Counter++
            Print Str$(Counter,"")+Separator$+Item_Name$
      End Sub
}
Checkit

Module Make_List  {
      Global Counter=0, Separator$=Letter$
      Make_Item("First")
      Make_Item("Second")
      Make_Item("Third")

      Sub Make_Item(Item_Name$)
            Counter++
            Print Str$(Counter,"")+Separator$+Item_Name$
      End Sub
}

Make_List ". "

Module Make_List1  {
      Global Counter=0, Separator$=Letter$
      Module Make_Item (Item_Name$) {
            Counter++
            Print Str$(Counter,"")+Separator$+Item_Name$
      }
      Make_Item "First"
      Make_Item "Second"
      Make_Item "Third"
}

Make_List1 ". "


makelist:=proc()
	local makeitem,i;
	i:=1;
	makeitem:=proc(i)
		if i=1 then
			printf("%a\n", "1. first");
		elif i=2 then
			printf("%a\n","2. second");
		elif i=3 then
			printf("%a\n", "3. third");
		else
			return NULL;
		end if;
	end proc;
	while i<4 do
		makeitem(i);
		i:=i+1;
	end do;
end proc;


makeList[sep_String]:=Block[
  {counter=0, makeItem},
  makeItem[item_String]:=ToString[++counter]<>sep<>item;
  makeItem /@ {"first", "second", "third"}
  ]
Scan[Print, makeList[". "]]


(
  :separator
  1 :counter
  (
    :item
    item separator counter string ' append append "" join
    counter succ @counter
  ) :make-item
  ("first" "second" "third") 'make-item map "\n" join
) :make-list

". " make-list print


makeList = function(sep)
    counter = 0
    makeItem = function(item)
        outer.counter = counter + 1
        return counter + sep + item
    end function
    return [makeItem("first"), makeItem("second"), makeItem("third")]
end function

print makeList(". ")


def makeList(separator)
	counter = 1

	def makeItem(item)
		result = str(counter) + separator + item + "\n"
		counter += 1
		return result
	end

	return makeItem("first") + makeItem("second") + makeItem("third")
end

println makeList(". ")


proc makeList(separator: string): string =
  var counter = 1

  proc makeItem(item: string): string =
    result = $counter & separator & item & "\n"
    inc counter

  makeItem("first") & makeItem("second") & makeItem("third")

echo $makeList(". ")


NSString *makeList(NSString *separator) {
  __block int counter = 1;

  NSString *(^makeItem)(NSString *) = ^(NSString *item) {
    return [NSString stringWithFormat:@"%d%@%@\n", counter++, separator, item];
  };

  return [NSString stringWithFormat:@"%@%@%@", makeItem(@"first"), makeItem(@"second"), makeItem(@"third")];
}

int main() {
  NSLog(@"%@", makeList(@". "));
  return 0;
}


let make_list separator =
  let counter = ref 1 in

  let make_item item =
    let result = string_of_int !counter ^ separator ^ item ^ "\n" in
    incr counter;
    result
  in

  make_item "first" ^ make_item "second" ^ make_item "third"

let () =
  print_string (make_list ". ")


sub makeList {
    my $separator = shift;
    my $counter = 1;

    sub makeItem { $counter++ . $separator . shift . "\n" }

    makeItem("first") . makeItem("second") . makeItem("third")
}

print makeList(". ");


function MakeList(string sep=".  ")
    function MakeItem(integer env, string sep)
        integer counter = getd("counter",env)+1
        setd("counter",counter,env)
        return sprintf("%d%s%s",{counter,sep,{"first","second","third"}[counter]})
    end function
    integer counter = new_dict({{"counter",0}})
    sequence res = {}
    for i=1 to 3 do
        res = append(res,MakeItem(counter,sep))
    end for
    return res
end function

?MakeList()


<?
function makeList($separator) {
  $counter = 1;

  $makeItem = function ($item) use ($separator, &$counter) {
    return $counter++ . $separator . $item . "\n";
  };

  return $makeItem("first") . $makeItem("second") . $makeItem("third");
}

echo makeList(". ");
?>


(de makeList (Sep)
   (let (Cnt 0  makeItem '((Str) (prinl (inc 'Cnt) Sep Str)))
      (makeItem "first")
      (makeItem "second")
      (makeItem "third") ) )

(makeList ". ")


def makeList(separator):
    counter = 1

    def makeItem(item):
        nonlocal counter
        result = str(counter) + separator + item + "\n"
        counter += 1
        return result

    return makeItem("first") + makeItem("second") + makeItem("third")

print(makeList(". "))


MakeList <- function(sep)
{
  counter <- 0
  MakeItem <- function() paste0(counter <<- counter + 1, sep, c("first", "second", "third")[counter])
  cat(replicate(3, MakeItem()), sep = "\n")
}
MakeList(". ")


#lang racket

(define (make-list separator)
  (define counter 1)

  (define (make-item item)
    (begin0
      (format "~a~a~a~%" counter separator item)
      (set! counter (add1 counter))))

  (apply string-append (map make-item '(first second third))))

(display (make-list ". "))


sub make-List ($separator = ') '){
    my $count = 1;

    sub make-Item ($item) { "{$count++}$separator$item" }

    join "\n", <first second third>».&make-Item;
}

put make-List('. ');


/*REXX program demonstrates that functions can be nested  (an outer and inner function).*/
ctr= 0                                           /*initialize the   CTR   REXX variable.*/
call MakeList '. '                               /*invoke  MakeList  with the separator.*/
exit 0                                           /*stick a fork in it,  we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
MakeItem: parse arg sep,text;    ctr= ctr + 1    /*bump the counter variable.           */
          say ctr  ||  sep  ||  word($, ctr)     /*display three thingys ───► terminal. */
          return
/*──────────────────────────────────────────────────────────────────────────────────────*/
MakeList: parse arg sep; $= 'first second third' /*obtain an argument;  define a string.*/
                     do  while  ctr<3            /*keep truckin'  until  finished.      */
                     call MakeItem  sep, $       /*invoke the   MakeItem   function.    */
                     end   /*while*/
          return


# Project : Nested function

makeList(". ")
func makeitem(sep, counter, text)
       see "" + counter + sep + text + nl

func makelist(sep)
       a = ["first", "second", "third"]
       counter = 0
       while counter < 3
                counter = counter + 1
                makeitem(sep, counter, a[counter])
       end


def makeList(separator)
  counter = 1

  makeItem = lambda {|item|
    result = "#{counter}#{separator}#{item}\n"
    counter += 1
    result
  }

  makeItem["first"] + makeItem["second"] + makeItem["third"]
end

print makeList(". ")


fn make_list(sep: &str) -> String {
    let mut counter = 0;
    let mut make_item = |label| {
        counter += 1;
        format!("{}{}{}", counter, sep, label)
    };
    format!(
        "{}\n{}\n{}",
        make_item("First"),
        make_item("Second"),
        make_item("Third")
    )
}

fn main() {
    println!("{}", make_list(". "))
}


   def main(args: Array[String]) {
      val sep: String=". "
      var c:Int=1;
      def go(s: String):Unit={
          println(c+sep+s)
          c=c+1
      }
      go("first")
      go("second")
      go("third")
   }


(define (make-list separator)
  (define counter 1)

  (define (make-item item)
    (let ((result (string-append (number->string counter) separator item "\n")))
      (set! counter (+ counter 1))
      result))

  (string-append (make-item "first") (make-item "second") (make-item "third")))

(display (make-list ". "))


$ include "seed7_05.s7i";

const func string: makeList (in string: separator) is func
  result
    var string: itemList is "";
  local
    var integer: counter is 1;

    const func string: makeItem (in string: item) is func
      result
        var string: anItem is "";
      begin
        anItem := counter <& separator <& item <& "\n";
	incr(counter);
      end func

  begin
    itemList := makeItem("first") & makeItem("second") & makeItem("third");
  end func;

const proc: main is func
  begin
    write(makeList(". "));
  end func;


func make_list(separator = ') ') {

    var count = 1
    func make_item(item) {
        [count++, separator, item].join
    }

    <first second third>.map(make_item).join("\n")
}

say make_list('. ')


COMMENT CLASS SIMSET IS SIMULA'S STANDARD LINKED LIST DATA TYPE
        CLASS HEAD IS THE LIST ITSELF
        CLASS LINK IS THE ELEMENT OF A LIST
        PROCEDURE IS THE TERM USED FOR FUNCTIONS IN SIMULA
        TEXT IS THE TERM USED FOR STRINGS IN SIMULA ;
SIMSET
BEGIN

    LINK CLASS ITEM(TXT); TEXT TXT;;

    COMMENT CREATING THE LIST AS A WHOLE WITH THE SEPARATOR ". "
            GIVEN AS AN ARGUMENT;
    REF(HEAD) PROCEDURE MAKELIST(SEPARATOR); TEXT SEPARATOR;
    BEGIN
        COMMENT VARIABLE TO KEEP TRACK OF THE ITEM NUMBER ;
        INTEGER COUNTER;

        COMMENT THIS IS THE NESTED FUNCTION ;
        REF(ITEM) PROCEDURE MAKEITEM(TXT); TEXT TXT;
        BEGIN
            TEXT NUM;
            TEXT ITEMTEXT;

            COMMENT CONVERT NUMBER TO STRING ;
            NUM :- BLANKS(5);
            NUM.PUTINT(COUNTER);

            COMMENT ACCESS SEPARATOR AND MODIFY COUNTER;
            COUNTER := COUNTER + 1;
            ITEMTEXT :- NUM & SEPARATOR & TXT;

            MAKEITEM :- NEW ITEM(ITEMTEXT);
        END MAKEITEM;

        REF(HEAD) HD;
        HD :- NEW HEAD;
        COUNTER := 1;
        MAKEITEM("FIRST").INTO(HD);
        MAKEITEM("SECOND").INTO(HD);
        MAKEITEM("THIRD").INTO(HD);
        MAKELIST :- HD;
    END MAKELIST;

    REF(HEAD) LIST;
    REF(ITEM) IT;
    LIST :- MAKELIST(". ");

    COMMENT NAVIGATE THROUGH THE LIST ;
    IT :- LIST.FIRST;
    WHILE IT =/= NONE DO
    BEGIN
        OUTTEXT(IT.TXT);
        OUTIMAGE;
        IT :- IT.SUC;
    END;

END.


fun make_list separator =
  let
    val counter = ref 1;
    fun make_item item =
      let
        val result = Int.toString (!counter) ^ separator ^ item ^ "\n"
      in
        counter := !counter + 1;
        result
      end
  in
    make_item "first" ^ make_item "second" ^ make_item "third"
  end;

print (make_list ". ")


(
f = { |separator|
	var count = 0;
	var counting = { |name|
		count = count + 1;
		count.asString ++ separator + name ++ "\n"
	};
	counting.("first") + counting.("second") + counting.("third")
};
)

f.(".")


func makeList(_ separator: String) -> String {
  var counter = 1

  func makeItem(_ item: String) -> String {
    let result = String(counter) + separator + item + "\n"
    counter += 1
    return result
  }

  return makeItem("first") + makeItem("second") + makeItem("third")
}

print(makeList(". "))


#!/usr/bin/env tclsh

proc MakeList separator {
    set counter 1
    proc MakeItem string {
	upvar 1 separator separator counter counter
	set res $counter$separator$string\n
	incr counter
	return $res
    }
    set res [MakeItem first][MakeItem second][MakeItem third]
    rename MakeItem {}
    return $res
}
puts [MakeList ". "]


Option Explicit

Private Const Sep As String = ". "
Private Counter As Integer
Sub Main()
Dim L As Variant
    Counter = 0
    L = MakeList(Array("first", "second", "third"))
    Debug.Print L
End Sub
Function MakeList(Datas) As Variant
Dim i As Integer
    For i = LBound(Datas) To UBound(Datas)
        MakeList = MakeList & MakeItem(Datas(i))
    Next i
End Function
Function MakeItem(Item As Variant) As Variant
    Counter = Counter + 1
    MakeItem = Counter & Sep & Item & vbCrLf
End Function


var makeList = Fn.new { |sep|
    var counter = 0
    var makeItem = Fn.new { |name|
        counter = counter + 1
        return "%(counter)%(sep)%(name)"
    }
    var items = []
    for (name in ["first", "second", "third"]) {
        items.add(makeItem.call(name))
    }
    System.print(items.join("\n"))
}

makeList.call(". ")


proc    MakeList(Separator);
char    Separator;
int     Counter;

    proc MakeItem;
    int  Ordinals;
    [IntOut(0, Counter);
    Text(0, Separator);
    Ordinals:= [0, "first", "second", "third"];
    Text(0, Ordinals(Counter));
    CrLf(0);
    ];

for Counter:= 1 to 3 do MakeItem;       \MakeList procedure

MakeList(". ")                          \main procedure


fcn makeList(separator){
  counter:=Ref(1);  // a container holding a one. A reference.
  // 'wrap is partial application, in this case binding counter and separator
  makeItem:='wrap(item){ c:=counter.inc(); String(c,separator,item,"\n") };
  makeItem("first") + makeItem("second") + makeItem("third")
}

print(makeList(". "));


;-----------------------------------------------------------
Nested_templated_data(template, Payload){
	UsedP := [], UnusedP := [], UnusedI := []
	result := template.Clone()
	x := ArrMap(template, Payload, result, UsedP, UnusedI, [])
	for i, v in Payload
		if !UsedP[v]
			UnusedP.Push(v)
	return [x.1, x.2, UnusedP]
}
;-----------------------------------------------------------
ArrMap(Template, Payload, result, UsedP, UnusedI, pth){
	for i, index in Template	{
		if IsObject(index)
			pth.Push(i),	Arrmap(index, Payload, result, UsedP, UnusedI, pth)
		else{
			pth.Push(i),	ArrSetPath(result, pth, Payload[index])
			if Payload[index]
				UsedP[Payload[index]] := 1
			else
				UnusedI.Push(index)
		}
		pth.Pop()
	}
	return [result, UnusedI, UsedP]
}
;-----------------------------------------------------------
ArrSetPath(Arr, pth, newVal){
	temp := []
	for k, v in pth{
		temp.push(v)
		if !IsObject(Arr[temp*])
			Arr[temp*] := []
	}
	return Arr[temp*] := newVal
}
;-----------------------------------------------------------
objcopy(obj){
	nobj := obj.Clone()
	for k, v in nobj
		if IsObject(v)
			nobj[k] := objcopy(v)
	return nobj
}
;-----------------------------------------------------------


(   get$("[
    [[1, 2],
     [3, 4, 1],
     5]]",MEM,JSN)
  : ?template
&     (0.payload#0)
      (1.payload#1)
      (2.payload#2)
      (3.payload#3)
      (4.payload#4)
      (5.payload#5)
      (6.payload#6)
  : ?payloads
& ( instantiate
  =   tmplt plds pld a b
    .   !arg:(?tmplt.?plds)
      & (   !tmplt:#
          & !plds:? (!tmplt.?pld) ?
          & !pld
        |   !tmplt:%?a_%?b
          & (instantiate$(!a.!plds))_(instantiate$(!b.!plds))
        )
  )
& out$(jsn$(instantiate$(!template.!payloads)))
);


#include <iostream>
#include <set>
#include <tuple>
#include <vector>

using namespace std;

// print a single payload
template<typename P>
void PrintPayloads(const P &payloads, int index, bool isLast)
{
    if(index < 0 || index >= (int)size(payloads)) cout << "null";
    else cout << "'" << payloads[index] << "'";
    if (!isLast) cout << ", ";  // add a comma between elements
}

// print a tuple of playloads
template<typename P, typename... Ts>
void PrintPayloads(const P &payloads, tuple<Ts...> const& nestedTuple, bool isLast = true)
{
    std::apply  // recursively call PrintPayloads on each element of the tuple
    (
        [&payloads, isLast](Ts const&... tupleArgs)
        {
            size_t n{0};
            cout << "[";
            (PrintPayloads(payloads, tupleArgs, (++n == sizeof...(Ts)) ), ...);
            cout << "]";
            cout << (isLast ? "\n" : ",\n");
        }, nestedTuple
    );
}

// find the unique index of a single index (helper for the function below)
void FindUniqueIndexes(set<int> &indexes, int index)
{
    indexes.insert(index);
}

// find the unique indexes in the tuples
template<typename... Ts>
void FindUniqueIndexes(set<int> &indexes, std::tuple<Ts...> const& nestedTuple)
{
    std::apply
    (
        [&indexes](Ts const&... tupleArgs)
        {
            (FindUniqueIndexes(indexes, tupleArgs),...);
        }, nestedTuple
    );
}

// print the payloads that were not used
template<typename P>
void PrintUnusedPayloads(const set<int> &usedIndexes, const P &payloads)
{
    for(size_t i = 0; i < size(payloads); i++)
    {
        if(usedIndexes.find(i) == usedIndexes.end() ) cout << payloads[i] << "\n";
    }
}

int main()
{
    // define the playloads, they can be in most containers
    vector payloads {"Payload#0", "Payload#1", "Payload#2", "Payload#3", "Payload#4", "Payload#5", "Payload#6"};
    const char *shortPayloads[] {"Payload#0", "Payload#1", "Payload#2", "Payload#3"}; // as a C array

    // define the indexes as a nested tuple
    auto tpl = make_tuple(make_tuple(
        make_tuple(1, 2),
        make_tuple(3, 4, 1),
        5));

    cout << "Mapping indexes to payloads:\n";
    PrintPayloads(payloads, tpl);

    cout << "\nFinding unused payloads:\n";
    set<int> usedIndexes;
    FindUniqueIndexes(usedIndexes, tpl);
    PrintUnusedPayloads(usedIndexes, payloads);

    cout << "\nMapping to some out of range payloads:\n";
    PrintPayloads(shortPayloads, tpl);

    return 0;
}


def with_payload(template, payload, used = nil)
    template.map do |item|
      if item.is_a? Enumerable
        with_payload(item, payload, used)
      else
        used << item
        payload[item]
      end
    end
end

p = {"Payload#0", "Payload#1", "Payload#2", "Payload#3", "Payload#4", "Payload#5", "Payload#6"}
t = { { {1, 2}, {3, 4, 1}, 5}}
used = Set(Int32).new
puts with_payload(t, p, used)

unused = Set(Int32).new((0..6).to_a) - used
puts "Unused indices: #{unused}"


USING: formatting kernel literals math sequences sequences.deep ;
IN: rosetta-code.nested-template-data

CONSTANT: payloads $[ 7 <iota> [ "Payload#%d" sprintf ] map ]

: insert-payloads ( template -- data-structure )
    [ dup fixnum? [ payloads ?nth ] when ] deep-map ;

{ { { 1 2 }
    { 3 4 1 }
    5 } }

{ { { 1 2 }
    { 10 4 1 }
    5 } }

[ dup insert-payloads "Template: %u\nData Structure: %u\n"
printf ] [email protected]


{-# language DeriveTraversable #-}

data Template a = Val a | List [Template a]
  deriving ( Show
           , Functor
           , Foldable
           , Traversable )


   Substitute=: ({[email protected]:[)`([email protected]:(= {:)~)`]}

   NB. aside: demonstrate Substitution
   ] A =: ;/ i. 8
┌─┬─┬─┬─┬─┬─┬─┬─┐
│0│1│2│3│4│5│6│7│
└─┴─┴─┴─┴─┴─┴─┴─┘

   ] B =: ('xxxx' ; 3)
┌────┬─┐
│xxxx│3│
└────┴─┘

   B Substitute A
┌─┬─┬─┬────┬─┬─┬─┬─┐
│0│1│2│xxxx│4│5│6│7│
└─┴─┴─┴────┴─┴─┴─┴─┘

   B Substitute A , < 3
┌─┬─┬─┬────┬─┬─┬─┬─┬────┐
│0│1│2│xxxx│4│5│6│7│xxxx│
└─┴─┴─┴────┴─┴─┴─┴─┴────┘


#!/bin/bash
function template {
  cat<<EOF
  [
    [[1, 2],
     [3, 4, 1],
      5 ]]
EOF
}

function payload {
  for i in $(seq 0 6) ; do
    echo Payload#$i
  done
}

# Task 1: Template instantiation
payload | jq -Rn --argfile t <(template) '
  ([inputs] | with_entries(.key |= tostring)) as $dict
  | $t
  | walk(if type == "number" then $dict[tostring] else . end)
'


t = ([Any[Any[1, 2],
          Any[3, 4, 1],
          5]])

p = ["Payload#$x" for x in 0:6]

for (i, e) in enumerate(t)
    if e isa Number
        t[i] = p[e + 1]
    else
        for (j, f) in enumerate(e)
            if f isa Number
                e[j] = p[f + 1]
            else
                for (k, g) in enumerate(f)
                    if g isa Number
                        f[k] = p[g + 1]
                    end
                end
            end
        end
    end
end

show(t)