import std/[os, tempfiles]

let (file, path) = createTempFile(prefix = "", suffix = "")
echo path, " created."
file.writeLine("This is a secure temporary file.")
file.close()
for line in path.lines:
  echo line
removeFile(path)


# Filename.temp_file "prefix." ".suffix" ;;
- : string = "/home/blue_prawn/tmp/prefix.301f82.suffix"


  [FID, MSG] = tmpfile();    % Return the file ID corresponding to a new temporary
  filename = tmpnam (...);   % generates temporary file name, but does not open file
  [FID, NAME, MSG] = mkstemp (TEMPLATE, DELETE);    % Return the file ID corresponding to a new temporary file with a unique name created from TEMPLATE.


Program TempFileDemo;

uses
  SysUtils;

var
  tempFile: text;

begin
  assign (Tempfile, GetTempFileName);
  rewrite (tempFile);
  writeln (tempFile, 5);
  close (tempFile);
end.


$ include "seed7_05.s7i";

const func boolean: semiPrime (in var integer: n) is func
  result
    var boolean: isSemiPrime is TRUE;
  local
    var integer: p is 2;
    var integer: f is 0;
  begin
    while f < 2 and p**2 <= n do
      while n rem p = 0 do
        n := n div p;
        incr(f);
      end while;
      incr(p);
    end while;
    isSemiPrime := f + ord(n > 1) = 2;
  end func;

const proc: main is func
  local
    var integer: v is 0;
  begin
    for v range 1675 to 1680 do
      writeln(v <& " -> " <& semiPrime(v));
    end for;
  end func;


say is_semiprime(2**128 + 1)   #=> true
say is_semiprime(2**256 - 1)   #=> false


import Foundation

func primes(n: Int) -> AnyGenerator<Int> {

  var (seive, i) = ([Int](0..<n), 1)
  let lim = Int(sqrt(Double(n)))

  return anyGenerator {
    while ++i < n {
      if seive[i] != 0 {
        if i <= lim {
          for notPrime in stride(from: i*i, to: n, by: i) {
            seive[notPrime] = 0
          }
        }
        return i
      }
    }
    return nil
  }
}

func isSemiPrime(n: Int) -> Bool {
  let g = primes(n)
  while let first = g.next() {
    if n % first == 0 {
      if first * first == n {
        return true
      } else {
        while let second = g.next() {
          if first * second == n { return true }
        }
      }
    }
  }
  return false
}


package require math::numtheory

proc isSemiprime n {
    if {!($n & 1)} {
	return [::math::numtheory::isprime [expr {$n >> 1}]]
    }
    for {set i 3} {$i*$i < $n} {incr i 2} {
	if {$n / $i * $i != $n && [::math::numtheory::isprime $i]} {
	    if {[::math::numtheory::isprime [expr {$n/$i}]]} {
		return 1
	    }
	}
    }
    return 0
}

for {set n 1675} {$n <= 1680} {incr n} {
    puts -nonewline "$n is ... "
    if {[isSemiprime $n]} {
	puts "a semiprime"
    } else {
	puts "NOT a semiprime"
    }
}


use File::Temp qw(tempfile);
$fh = tempfile();
($fh2, $filename) = tempfile(); # this file stays around by default
print "$filename\n";
close $fh;
close $fh2;


without js -- (file i/o)
pp(temp_file())
{integer fn, string name} = temp_file("myapp/tmp","data","log","wb")
pp({fn,name})
close(fn)
{} = delete_file(name)


$fh = tmpfile();
// do stuff with $fh
fclose($fh);
// file removed when closed

// or:
$filename = tempnam('/tmp', 'prefix');
echo "$filename\n";
// open $filename and do stuff with it


: (out (tmp "foo") (println 123))         # Write tempfile
-> 123

: (in (tmp "foo") (read))                 # Read tempfile
-> 123

: (let F (tmp "foo")
   (ctl F                                 # Get exclusive lock
      (in F
         (let N (read)                    # Atomic increment
            (out F (println (inc N))) ) ) ) )
-> 124


$tempFile = [System.IO.Path]::GetTempFileName()
Set-Content -Path $tempFile -Value "FileName = $tempFile"
Get-Content -Path $tempFile
Remove-Item -Path $tempFile


Procedure.s TempFile()
  Protected a, Result$

  For a = 0 To 9999
    Result$ = GetTemporaryDirectory() + StringField(GetFilePart(ProgramFilename()),1,".")
    Result$ + "_" + Str(ElapsedMilliseconds()) + "_(" + RSet(Str(a),4,"0") + ").tmp"
    If FileSize(Result$) = -1                                      ;  -1 = File not found
      ProcedureReturn Result$
    EndIf
  Next

  ProcedureReturn ""
EndProcedure

Define File, File$

File$ = TempFile()
If File$ <> ""
  File = CreateFile(#PB_Any, File$)
  If File <> 0
    WriteString(File, "Some temporary data here...")
    CloseFile(File)
  EndIf
EndIf


// Semiprime

function primeFactorsCount(n: number): number {
  n = Math.abs(n);
  var count = 0; // Result
  if (n >= 2)
    for (factor = 2; factor <= n; factor++)
      while n % factor == 0) {
        count++;
        n /= factor;
      }
  return count;
}

const readline = require('readline').createInterface({
  input: process.stdin, output: process.stdout
});

readline.question('Enter an integer: ', sn => {
  var n = parseInt(sn);
  console.log(primeFactorsCount(n) == 2 ?
    "It is a semiprime." : "It is not a semiprime.");
  readline.close();
});


var semiprime = Fn.new { |n|
    if (n < 3) return false
    var nf = 0
    for (i in 2..n) {
        while (n%i == 0) {
            if (nf == 2) return false
            nf = nf + 1
            n = (n/i).floor
        }
    }
    return nf == 2
}

for (v in 1675..1680) {
    System.print("%(v) -> %(semiprime.call(v) ? "is" : "is not") semi-prime")
}


func Semiprime(N);      \Return 'true' if N is semiprime
int  N, F, C;
[C:= 0;  F:= 2;
repeat  if rem(N/F) = 0 then
                [C:= C+1;
                N:= N/F;
                ]
        else    F:= F+1;
until   F > N;
return C = 2;
];

int N;
[for N:= 1 to 100 do
    if Semiprime(N) then
        [IntOut(0, N);  ChOut(0, ^ )];
]


fcn semiprime(n){
   reg f = 0;
   p:=2; while(f < 2 and p*p <= n){
      while(0 == n % p){ n /= p; f+=1; }
      p+=1;
   }
   return(f + (n > 1) == 2);
}


>>> import tempfile
>>> invisible = tempfile.TemporaryFile()
>>> invisible.name
'<fdopen>'
>>> visible = tempfile.NamedTemporaryFile()
>>> visible.name
'/tmp/tmpZNfc_s'
>>> visible.close()
>>> invisible.close()


use File::Temp;

# Generate a temp file in a temp dir
my ($filename0,$filehandle0) = tempfile;

# specify a template for the filename
#  * are replaced with random characters
my ($filename1,$filehandle1) = tempfile("******");

# Automatically unlink files at DESTROY (this is the default)
my ($filename2,$filehandle2) = tempfile("******", :unlink);

# Specify the directory where the tempfile will be created
my ($filename3,$filehandle3) = tempfile(:tempdir("/path/to/my/dir"));

# don't unlink this one
my ($filename4,$filehandle4) = tempfile(:tempdir('.'), :!unlink);

# specify a prefix, a suffix, or both for the filename
my ($filename5,$filehandle5) = tempfile(:prefix('foo'), :suffix(".txt"));


/*REXX pgm secures (a temporary file), writes to it, displays the file, then deletes it.*/
parse arg tFID # .                               /*obtain optional argument from the CL.*/
if tFID=='' | tFID==","  then tFID= 'TEMP.FILE'  /*Not specified?  Then use the default.*/
if    #=='' |    #==","  then    #= 6            /* "      "         "   "   "     "    */
call lineout tFID                                /*insure file is closed.               */
rc= 0
say '··· creating file: '  tFID
call lineout tFID,,1                             /*insure file is open and at record 1. */
if rc\==0  then call ser rc 'creating file' tFID /*issue error if can't open the file.  */
say '··· writing  file: '  tFID

    do j=1  for #                                /*write a half-dozen records to file.  */
    call lineout tFID, 'line' j                  /*write a  record  to the file.        */
    if rc\==0  then call ser rc 'writing file'  tFID    /*Have an error?  Issue err msg.*/
    end   /*j*/

call lineout tFID                                /*close the file.                      */
say '··· reading/display file: '  tFID

    do j=1  while lines(tFID)>0                  /*read the entire file and display it. */
    x= linein(tFID)                              /*read a record from the file.         */
    if rc\==0  then call ser rc 'reading file'  tFID    /*Have an error?  Issue err msg.*/
    say 'line ' j  " of file" tFID":"  x                /*display a record to the term. */
    end   /*j*/

call lineout tFID                                /*close the file.                      */
say '··· erasing file: '  tFID
'ERASE' tFID                                     /*erase the file.                      */
exit 0                                           /*stick a fork in it,  we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
ser: say; say '***error***' arg(1); say; exit 13 /*issue an error message to the term.  */


irb(main):001:0> require 'tempfile'
=> true
irb(main):002:0> f = Tempfile.new('foo')
=> #<File:/tmp/foo20081226-307-10p746n-0>
irb(main):003:0> f.path
=> "/tmp/foo20081226-307-10p746n-0"
irb(main):004:0> f.close
=> nil
irb(main):005:0> f.unlink
=> #<Tempfile: (closed)>


// 202100322 Rust programming solution

use tempfile::tempfile;

fn main() {

    let fh = tempfile();

    println!("{:?}", fh);
}


import java.io.{File, FileWriter, IOException}

  def writeStringToFile(file: File, data: String, appending: Boolean = false) =
    using(new FileWriter(file, appending))(_.write(data))

  def using[A <: {def close() : Unit}, B](resource: A)(f: A => B): B =
    try f(resource) finally resource.close()

  try {
    val file = File.createTempFile("_rosetta", ".passwd")
    // Just an example how you can fill a file
    using(new FileWriter(file))(writer => rawDataIter.foreach(line => writer.write(line)))
    scala.compat.Platform.collectGarbage() // JVM Windows related bug workaround JDK-4715154
    file.deleteOnExit()
    println(file)
  } catch {
    case e: IOException => println(s"Running Example failed: ${e.getMessage}")
  }


var tmpfile = require('File::Temp');
var fh = tmpfile.new(UNLINK => 0);
say fh.filename;
fh.print("Hello, World!\n");
fh.close;


$$ MODE TUSCRIPT
tmpfile="test.txt"
ERROR/STOP CREATE (tmpfile,seq-E,-std-)
text="hello world"
FILE $tmpfile = text
- tmpfile "test.txt" can only be accessed by one user an will be deleted upon programm termination


RESTOREUMASK=$(umask)
TRY=0
while :; do
   TRY=$(( TRY + 1 ))
   umask 0077
   MYTMP=${TMPDIR:-/tmp}/$(basename $0).$$.$(date +%s).$TRY
   trap "rm -fr $MYTMP" EXIT
   mkdir "$MYTMP" 2>/dev/null && break
done
umask "$RESTOREUMASK"
cd "$MYTMP" || {
   echo "Temporary directory failure on $MYTMP" >&2
   exit 1; }


import "random" for Random
import "/ioutil" for File, FileUtil
import "/fmt" for Fmt

var rand = Random.new()

var createTempFile = Fn.new { |lines|
    var tmp
    while (true) {
        // create a name which includes a random 6 digit number
        tmp = "/tmp/temp%(Fmt.swrite("$06d", rand.int(1e6))).tmp"
        if (!File.exists(tmp)) break
    }
    FileUtil.writeLines(tmp, lines)
    return tmp
}

var lines = ["one", "two", "three"]
var tmp = createTempFile.call(lines)
System.print("Temporary file path: %(tmp)")
System.print("Original contents of temporary file:")
System.print(File.read(tmp))

// append some more lines
var lines2 = ["four", "five", "six"]
FileUtil.appendLines(tmp, lines2)
System.print("Updated contents of temporary file:")
System.print(File.read(tmp))
File.delete(tmp)
System.print("Temporary file deleted.")


IF PROC x = ...;
   ...
THEN
    # can call x here #
    PROC y = ...;
    ...
    GO TO l1 # invalid!! #
ELSE
    # can call x here, but not y #
    ...
    l1: ...
FI


# This program outputs a greeting
BEGIN {
  sayhello()    # Call the function defined below
  exit
}

function sayhello {
   print "Hello World!"    # Outputs a message to the terminal
}


V x = ‘From global scope’

F outerfunc()
   V x = ‘From scope at outerfunc’

   F scoped_local()
      V x = ‘scope local’
      R ‘scoped_local scope gives x = ’x
   print(scoped_local())

   F scoped_nonlocal()
      R ‘scoped_nonlocal scope gives x = ’@x
   print(scoped_nonlocal())

   F scoped_global()
      R ‘scoped_global scope gives x = ’:x
   print(scoped_global())

outerfunc()


f(1)              /* First output line */
define f(x) {
    return(x)
}
f(3)              /* Second output line */

define f(x) {
    return(x - 1)
}
f(3)              /* Third output line */


#include <stdio.h>

#define sqr(x) ((x) * (x))
#define greet printf("Hello There!\n")

int twice(int x)
{
	return 2 * x;
}

int main(void)
{
	int x;

	printf("This will demonstrate function and label scopes.\n");
	printf("All output is happening through printf(), a function declared in the header stdio.h, which is external to this program.\n");
	printf("Enter a number: ");
	if (scanf("%d", &x) != 1)
		return 0;

	switch (x % 2) {
	default:
		printf("Case labels in switch statements have scope local to the switch block.\n");
	case 0:
		printf("You entered an even number.\n");
		printf("Its square is %d, which was computed by a macro. It has global scope within the translation unit.\n", sqr(x));
		break;
	case 1:
		printf("You entered an odd number.\n");
		goto sayhello;
	jumpin:
		printf("2 times %d is %d, which was computed by a function defined in this file. It has global scope within the translation unit.\n", x, twice(x));
		printf("Since you jumped in, you will now be greeted, again!\n");
	sayhello:
		greet;
		if (x == -1)
			goto scram;
		break;
	}

	printf("We now come to goto, it's extremely powerful but it's also prone to misuse. Its use is discouraged and it wasn't even adopted by Java and later languages.\n");

	if (x != -1) {
		x = -1;   /* To break goto infinite loop. */
	 	goto jumpin;
	}

scram:
	printf("If you are trying to figure out what happened, you now understand goto.\n");
	return 0;
}


--assume A, B and C to be valid classes
class X
feature -- alias for "feature {ANY}"
-- ANY is the class at the top of the class hierarchy and all classes inherit from it
-- features following this clause are given "global" scope: these features are visible to every class

feature {A, B, C, X}
-- features following this clause are only visible to the specified classes (and their descendants)
-- classes not in this set do not even know of the existence of these features

feature {A, B, C}
-- similar to above, except other instances of X cannot access these features

feature {X}
-- features following this clause are only visible to instances of X (and its descendants)

feature {NONE}
-- NONE is the class at the bottom of the class hierarchy and inherits from every class
-- features following this clause are only visible to this particular instance of X

end


macro LDIR,source,dest,count
;LoaD, Increment, Repeat
lda #<source
sta $00
lda #>source
sta $01

lda #<dest
sta $02
lda #>dest
sta $03

ldx count
ldy #0
\@:         ;this is a local label

lda ($00),y ;load a byte from the source address
sta ($02),y ;store in destination address
iny         ;increment
dex
bne \@      ;repeat until x=0
endm


package P is
   ... -- Declarations placed here are publicly visible
private
   ... -- These declarations are visible only to the children of P
end P;


singleton = "global variable"

assume_global()
{
  Global  ; assume all variables declared in this function are global in scope
  Static callcount := 0   ; except this one declared static, initialized once only
  MsgBox % singleton  ; usefull to initialize a bunch of singletons
  callcount++
}

assume_global2()
{
  Local var1  ; assume global except for var1  (similar to global scope declaration)
  MsgBox % singleton
}

object(member, value = 0, null = 0)
{
  Static  ; assume all variables in this function to be static
  If value    ; can be used to simulate objects
	_%member% := value
  Else If null
	_%member% := ""
  Return (_%member%)
}


-module( a_module ).

-export( [exported_function/0] ).

exported_function() -> 1 + local_function().

local_function() -> 2.


package main

import (
    "fmt"
    "runtime"

    "ex"
)

func main() {
    // func nested() { ... not allowed here

    // this is okay, variable f declared and assigned a function literal.
    f := func() {
        // this mess prints the name of the function to show that it's an
        // anonymous function defined in package main
        pc, _, _, _ := runtime.Caller(0)
        fmt.Println(runtime.FuncForPC(pc).Name(), "here!")
    }

    ex.X(f) // function value passed to exported function

    // ex.x() non-exported function not visible here
}


add3 :: Int -> Int-> Int-> Int
add3 x y z = add2 x y + z

add2 :: Int -> Int -> Int
add2 x y = x + y

main :: putStrLn(show (add3 5 6 5))


 10 X = 1
 20  DEF  FN F(X) = X
 30  DEF  FN G(N) = X
 40  PRINT  FN F(2)
 50  PRINT  FN G(3)


def NAME:
  def NAME: 2;
  1, NAME;  # this calls the inner function, not the outer function

NAME # => 1, 2


Type of scope | block/construct introducing this kind of scope
----------------------------------------------------------------
Global Scope  |	module, baremodule, at interactive prompt (REPL)
Local Scope   |  Soft Local Scope: for, while, comprehensions, try-catch-finally, let
Local Scope   |  Hard Local Scope: functions (either syntax, anonymous & do-blocks), struct, macro


// version 1.1.2

// top level function visible anywhere within the current module
internal fun a() = println("calling a")

object B {
    // object level function visible everywhere, by default
    fun f() = println("calling f")
}

open class C {
    // class level function visible everywhere, by default
    fun g() = println("calling g")

    // class level function only visible within C
    private fun h() = println("calling h")

    // class level function only visible within C and its subclasses
    protected fun i() {
        println("calling i")
        println("calling h")  // OK as h within same class
        // nested function in scope until end of i
        fun j() = println("calling j")
        j()
    }
}

class D : C(), E {
    // class level function visible anywhere within the same module
    fun k() {
        println("calling k")
        i()  // OK as C.i is protected
        m()  // OK as E.m is public and has a body
    }
}

interface E {
    fun m() {
        println("calling m")
    }
}

fun main(args: Array<String>) {
    a()    // OK as a is internal
    B.f()  // OK as f is public
    val c = C()
    c.g()  // OK as g is public but can't call h or i via c
    val d = D()
    d.k()  // OK as k is public
    // labelled lambda expression assigned to variable 'l'
    val l = lambda@ { ->
        outer@ for (i in 1..3) {
            for (j in 1..3) {
                if (i == 3) break@outer    // jumps out of outer loop
                if (j == 2) continue@outer // continues with next iteration of outer loop
                println ("i = $i, j = $j")
            }
            if (i > 1) println ("i = $i")  // never executed
        }
        val n = 1
        if (n == 1) return@lambda  // returns from lambda
        println("n = $n")  // never executed
    }
    l()  // invokes lambda
    println("Good-bye!")   // will be executed
}


define g(a) {
    auto b

    b = 3

    "Inside g: a = "; a
    "Inside g: b = "; b
    "Inside g: c = "; c
    "Inside g: d = "; d

    a = 3; b = 3; c = 3; d = 3
}

define f(a) {
    auto b, c

    b = 2; c = 2
    "Inside f (before call): a = "; a
    "Inside f (before call): b = "; b
    "Inside f (before call): c = "; c
    "Inside f (before call): d = "; d
    x = g(2)    /* Assignment prevents output of the return value */
    "Inside f (after call): a = "; a
    "Inside f (after call): b = "; b
    "Inside f (after call): c = "; c
    "Inside f (after call): d = "; d

    a = 2; b = 2; c = 2; d = 2
}

a = 1; b = 1; c = 1; d = 1
"Global scope (before call): a = "; a
"Global scope (before call): b = "; b
"Global scope (before call): c = "; c
"Global scope (before call): d = "; d
x = f(1)
"Global scope (before call): a = "; a
"Global scope (before call): b = "; b
"Global scope (before call): c = "; c
"Global scope (before call): d = "; d


  67:?x           {x has global scope}
& 77:?y           { y has global scope }
& ( double
  =
    .  !y+!y      { y refers to the variable declared in myFunc, which
                    shadows the global variable with the same name }
  )
& ( myFunc
  =   y,z         { y and z have dynamic scope. z is never used. }
    .   !arg:?y   { arg is dynamically scoped }
      & double$
      & !x+!y
  )


int a;          // a is global
static int p;   // p is "locale" and can be seen only from file1.c

extern float v; // a global declared somewhere else

// a "global" function
int code(int arg)
{
  int myp;        // 1) this can be seen only from inside code
                  // 2) In recursive code this variable will be in a
                  //    different stack frame (like a closure)
  static int myc; // 3) still a variable that can be seen only from
                  //    inside code, but its value will be kept
                  //    among different code calls
                  // 4) In recursive code this variable will be the
                  //    same in every stack frame - a significant scoping difference
}

// a "local" function; can be seen only inside file1.c
static void code2(void)
{
  v = v * 1.02;    // update global v
  // ...
}


public //visible to anything.
protected //visible to current class and to derived classes.
internal //visible to anything inside the same assembly (.dll/.exe).
protected internal //visible to anything inside the same assembly and also to derived classes outside the assembly.
private //visible only to the current class.
//C# 7.2 adds:
private protected //visible to current class and to derived classes inside the same assembly.

//                   |       |     subclass     |    other class   ||     subclass     |    other class
//Modifier           | class | in same assembly | in same assembly || outside assembly | outside assembly
//-------------------------------------------------------------------------------------------------------
//public             |  Yes  |        Yes       |        Yes       ||        Yes       |       Yes
//protected internal |  Yes  |        Yes       |        Yes       ||        Yes       |       No
//protected          |  Yes  |        Yes       |        No        ||        Yes       |       No
//internal           |  Yes  |        Yes       |        Yes       ||        No        |       No
//private            |  Yes  |        No        |        No        ||        No        |       No
// C# 7.2:
//private protected  |  Yes  |        Yes       |        No        ||        No        |       No


;; *bug* shall have a dynamic binding.
(declaim (special *bug*))

(let ((shape "triangle") (*bug* "ant"))
  (flet ((speak ()
           (format t "~%  There is some ~A in my ~A!" *bug* shape)))
    (format t "~%Put ~A in your ~A..." *bug* shape)
    (speak)

    (let ((shape "circle") (*bug* "cockroach"))
      (format t "~%Put ~A in your ~A..." *bug* shape)
      (speak))))


function foo() print("global") end -- global scope by default
foo()
local function foo() print("local module") end -- local to the current block (which is the module)
foo() -- local obscures the global
_G.foo() -- bug global still exists
do -- create a new block
  foo() -- outer module-level scope still visible
  local function foo() print("local block") end
  foo() -- obscures outer module-level local
  local function foo() -- redefine at local block level
    print("local block redef")
    local function foo() -- define again inside redef
      print("local block redef inner")
    end
    foo() -- call block-level redef inner
  end
  foo() -- call block-level redef
end -- close the block (and thus its scope)
foo() -- module-level local still exists
_G.foo() -- global still exists


Function Master {
	Module Alfa {
		Gosub 100
		Global M=1000
		\\ delta print 1000
		delta
		End
	100	Print Module(Beta)=False
		Print Module(Delta)=True
		Return
	}
	Group Object1 {
		Function Master {
			=M
		}
		Module Final Beta {
			\\ delta print 500
			delta
			alfa()
			Sub alfa()
				Local [email protected](3)
				Global M=N
				\\ delta print 1500
				Delta
				Print This.Master()=1500
				[email protected](6)
				\\ change value of M, not shadow M like Global M
				M<=N
				\\ delta print 9000
				Delta
				Print .Master()=9000
			End Sub
			Function Kappa(K)
				=M*K
			End Function
		}
	}
	Module Global Delta {
		Goto name1
		\\ a remark here

	name1:
		Print Module(Alfa)=False
		Print Module(Beta)=False
		Print Module(Delta)=True
		Print M
	}

	\\ This is the program
	K=100
	Global M=500
	Alfa
	Object1.Beta
	Print Object1.Master()=500
	Print K=100, M=500
}
Call Master()
\\ No variables exist after the return from Master()
Print Valid(M)=False


no warnings 'redefine';

sub logger { print shift . ": Dicitur clamantis in deserto." };   # discarded

logger('A');                                                      # can use before defined
HighLander::logger('B');                                          # ditto, but referring to another package

package HighLander {
logger('C');
sub logger { print shift . ": I have something to say.\n" };       # discarded
sub down_one_level {
    sub logger { print shift . ": I am a man, not a fish.\n" };    # discarded
    sub down_two_levels {
        sub logger { print shift . ": There can be only one!\n" }; # routine for 'Highlander' package
    }
}
logger('D');
}

logger('E');
sub logger {
   print shift . ": This thought intentionally left blank.\n"      # routine for 'main' package
};


set :a "global"
if true:
    !print a
    local :a "local"
    !print a
    !print getglobal :a
!print a


feature
	some_procedure(int: INTEGER; char: CHARACTER)
		local
			r: REAL
			i: INTEGER
		do
			-- r, i and s have scope here
			-- as well as int and char
			-- some_procedure and some_function additionally have scope here
		end

	s: STRING

	some_function(int: INTEGER): INTEGER
		do
			-- s and Result have scope here
			-- as well as int (int here differs from the int of some_procedure)
			-- some_procedure and some_function additionally have scope here
		end

	-- s, some_procedure and some_function have scope here


Functions are normally internal to a program. If they are at the nesting level
immediately within the program, they are accessible from anywhere in the program.

Functions can also be encapsuled in a package, and the function name exported.

Functions can be compiled separately, and then linked with a program
in which case they are globally accessible.


pi # private
pi = 3.14159

sum # private
sum x y = x + y


-module( a_module ).

-export( [double/1] ).

double( N ) -> add( N, N ).

add( N, N ) -> N + N.


'Declares a integer variable and reserves memory to accommodate it
Dim As Integer baseAge = 10
'Define a variable that has static storage
Static As String person
person = "Amy"
'Declare variables that are both accessible inside and outside procedures
Dim Shared As String friend
friend = "Susan"
Dim Shared As Integer ageDiff = 3
Dim Shared As Integer extraYears = 5

Sub test()
    'Declares a integer variable and reserves memory to accommodate it
    Dim As Integer baseAge = 30
    'Define a variable that has static storage
    Static As String person
    person = "Bob"
    'Declare a local variable distinct from a variable with global scope having the same name
    Static As Integer extraYears = 2

    Print person; " and "; friend; " are"; baseAge; " and"; baseAge + ageDiff + extraYears; " years old."
End Sub

test()
Print person; " and "; friend; " are"; baseAge; " and"; baseAge + ageDiff + extraYears; " years old."
Sleep


global var1    # used outside of procedures

procedure one() # a global procedure (the only kind)
local  var2    # used inside of procedures
static var3    # also used inside of procedures
end


function global:Get-DependentService
{
    Get-Service | Where-Object {$_.DependentServices}
}


(define (foo x)
  (define (bar y) (+ x y))
  (bar 2))
(foo 1) ; => 3
(bar 1) ; => error


CALLER    # Contextual symbols in the immediate caller's lexical scope
OUTER     # Symbols in the next outer lexical scope
UNIT      # Symbols in the outermost lexical scope of compilation unit
SETTING   # Lexical symbols in the unit's DSL (usually CORE)
PARENT    # Symbols in this package's parent package (or lexical scope)


/*REXX program  demonstrates  the  use of    labels    and  also a   CALL   statement.  */
blarney = -0                                     /*just a blarney & balderdash statement*/
signal do_add                                    /*transfer program control to a  label.*/
ttt = sinD(30)                                   /*this REXX statement is never executed*/
                                                 /* [↓]   Note the case doesn't matter. */
DO_Add:                                          /*coming here from the SIGNAL statement*/

say 'calling the sub:  add.2.args'
call add.2.args 1, 7                             /*pass two arguments:   1   and a   7  */
say 'sum =' result                               /*display the result from the function.*/
exit                                             /*stick a fork in it,  we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
add.2.args: procedure;  parse arg x,y;   return x+y       /*first come, first served ···*/
add.2.args: say 'Whoa Nelly!! Has the universe run amok?' /*didactic, but never executed*/
add.2.args: return  arg(1) + arg(2)                       /*concise,   "    "       "   */


# Project : Scope/Function names and labels

see "What is your name?" + nl
give name
welcome(name)

func welcome(name)
        see "hello " + name + nl


def welcome(name)
   puts "hello #{name}"
end
puts "What is your name?"
$name = STDIN.gets
welcome($name)
return


   A=: 1
   B=: 2
   C=: 3
   F=: verb define
      A=:4
      B=.5
      D=.6
      A+B+C+D
   )
   F ''
18
   A
4
   B
2
   D
|value error


public //any class may access this member directly

protected //only this class, subclasses of this class,
//and classes in the same package may access this member directly

private //only this class may access this member directly

static //for use with other modifiers
//limits this member to one reference for the entire JVM

//adding no modifier (sometimes called "friendly") allows access to the member by classes in the same package

// Modifier    | Class | Package | Subclass | World
// ------------|-------|---------|----------|-------
// public      |  Y    |    Y    |    Y     |   Y
// protected   |  Y    |    Y    |    Y     |   N
// no modifier |  Y    |    Y    |    N     |   N
// private     |  Y    |    N    |    N     |   N

//method parameters are available inside the entire method

//Other declarations follow lexical scoping,
//being in the scope of the innermost set of braces ({}) to them.
//You may also create local scopes by surrounding blocks of code with braces.

public void function(int x){
   //can use x here
   int y;
   //can use x and y here
   {
      int z;
      //can use x, y, and z here
   }
   //can use x and y here, but NOT z
}


 julia> function foo(n)
             x = 0
             for i = 1:n
                 local x # introduce a loop-local x
                 x = i
             end
             x
         end
  foo (generic function with 1 method)

 julia> foo(10)
  0


// version 1.1.2

class SomeClass {
    val id: Int

    companion object {
        private var lastId = 0
        val objectsCreated get() = lastId
    }

    init {
        id = ++lastId
    }
}

fun main(args: Array<String>) {
    val sc1 = SomeClass()
    val sc2 = SomeClass()
    println(sc1.id)
    println(sc2.id)
    println(SomeClass.objectsCreated)
}


object ScopeFunction extends App {
  val c = new C()
  val d = new D()
  val n = 1

  def a() = println("calling a")

  trait E {
    def m() = println("calling m")
  }

  a() // OK as a is internal
  B.f() // OK as f is public

  class C {
    // class level function visible everywhere, by default
    def g() = println("calling g")

    // class level function only visible within C and its subclasses
    protected def i() {
      println("calling i")
      println("calling h") // OK as h within same class
      // nested function in scope until end of i
      def j() = println("calling j")

      j()
    }

    // class level function only visible within C
    private def h() = println("calling h")
  }

  c.g() // OK as g is public but can't call h or i via c

  class D extends C with E {
    // class level function visible anywhere within the same module
    def k() {
      println("calling k")
      i() // OK as C.i is protected
      m() // OK as E.m is public and has a body
    }
  }

  d.k() // OK as k is public

  object B {
    // object level function visible everywhere, by default
    def f() = println("calling f")
  }

  val l = (i:Int, j: Int) => println(i,j)

  println("Good-bye!") // will be executed

}


# Nested functions
func outer {
    func inner {};   # not visible outside
}

# Nested classes
class Outer {
    class Inner {};  # not visisble outside
}


doFoo 1 2 3;    # Will produce an error

proc doFoo {a b c} {
    puts [expr {$a + $b*$c}]
}
doFoo 1 2 3;    # Will now print 7 (and will continue to do so until doFoo is renamed or deleted


#!/bin/sh
multiply 3 4    # This will not work
echo $?    # A bogus value was returned because multiply definition has not yet been run.

multiply() {
  return `expr $1 \* $2`    # The backslash is required to suppress interpolation
}

multiply 3 4    # Ok. It works now.
echo $?         # This gives 12


//func.call() /* invalid, can't call func before its declared */

var func = Fn.new { System.print("func has been called.") }

func.call() // fine

//C.init() /* not OK, as C is null at this point */

class C {
    static init()   { method() } // fine even though 'method' not yet declared
    static method() { System.print("method has been called.") }
}

C.init() // fine


make "g 5    ; global

to proc :p
  make "h 4    ; also global
  local "l       ; local, no initial value
  localmake "m 3

  sub 7
end

to sub :s
  ; can see :g, :h, and :s
  ; if called from proc, can also see :l and :m
  localmake "h 5     ; hides global :h within this procedure and those it calls
end


:- public(foo/1).     % predicate can be called from anywhere

:- protected(bar/2).  % predicate can be called from the declaring entity and its descendants

:- private(baz/3).    % predicate can only be called from the declaring entity

:- object(object,     % predicates declared in the protocol become private for the object
    implements(private::protocol)).

:- category(object,   % predicates declared in the protocol become protected for the category
    implements(protected::protocol)).

:- protocol(extended, % no change to the scope of the predicates inherited from the extended protocol
    extends(public::minimal)).


foo = "global" -- global scope
print(foo)
local foo = "local module" -- local to the current block (which is the module)
print(foo) -- local obscures the global
print(_G.foo) -- but global still exists
do -- create a new block
  print(foo) -- outer module-level scope still visible
  local foo = "local block" -- local to the current block (which is this "do")
  print(foo) -- obscures outer module-level local
  for foo = 1,2 do -- create another more-inner scope
    print("local for "..foo) -- obscures prior block-level local
  end -- and close the scope
  print(foo) -- prior block-level local still exists
end -- close the block (and thus its scope)
print(foo) -- module-level local still exists
print(_G.foo) -- global still exists


Module Checkit {
      M=1000
      Function Global xz {
             =9999
      }
      Module TopModule {
            \\ clear vars and static vars
            Clear
            M=500
            Function Global xz {
                  =10000
            }
            Module Kappa {
                  Static N=1
                  Global M=1234
                  x=1
                  z=1
                  k=1
                  Group Alfa {
                  Private:
                        x=10, z=20, m=100
                        Function xz {
                              =.x*.z+M
                        }
                  Public:
                        k=50
                        Module AddOne {
                              .x++
                              .z++
                              .k++
                              Print .xz(), .m=100
                        }
                        Module ResetValues {
                              \\ use <= to change members, else using = we define local variables
                              .x<=10
                              .z<=20
                        }
                  }
                  ' print 1465
                  Alfa.AddOne
                  Print x=1, z=1, k=1, xz()=10000
                  Print N  ' 1 first time, 2 second time
                  N++
                  Push Alfa
            }
            Kappa
            Drop  ' drop one alfa
            Kappa
            Print M=500
            ' leave one alfa in stack of values
      }
      TopModule
      Read AlfaNew
      Try ok {
            AlfaNew.AddOne
      }
      \\ we get an error because M global not exist now
      \\ here M is Local.
      If Error or Not Ok Then Print Error$ ' Uknown M in .xz() in AlfaNew.AddOne
      Print M=1000, xz()=9999
      For AlfaNew {
            Global M=1234
            .ResetValues
            .AddOne  ' now works because M exist as global, for this block
      }
      Print M=1000, xz()=9999
      For This {
            Local M=50
            M++
            Print M=51
      }
      Print M=1000
}
Checkit
List  ' list of variables are empty
Modules ? ' list of modules show two: A and A.Checkit
Print Module$  ' print A


Module -> localize names of variables (lexical scoping)
Block  -> localize values of variables (dynamic scoping)
Module creates new symbols:
Module[{x}, Print[x];
 Module[{x}, Print[x]]
]
->x$119
->x$120
Block localizes values only; it does not create new symbols:
x = 7;
Block[{x=0}, Print[x]]
Print[x]
->0
->7


9000 REM The function is immediately visible and usable
9010 DEF FN s(x)=x*x

PRINT FN s(5): REM This will work immediately
GO TO 50: REM This will work immediately


OUTER
 SET OUT=1,IN=0
 WRITE "OUT = ",OUT,!
 WRITE "IN = ",IN,!
 DO INNER
 WRITE:$DATA(OUT)=0 "OUT was destroyed",!
 QUIT
INNER
 WRITE "OUT (inner scope) = ",OUT,!
 WRITE "IN (outer scope) = ",IN,!
 NEW IN
 SET IN=3.14
 WRITE "IN (inner scope) = ",IN,!
 KILL OUT
 QUIT


proc foo = echo "foo" # hidden
proc bar* = echo "bar" # acessible

type MyObject = object
  name*: string # accessible
  secretAge: int # hidden


procedure super;
var
	f: boolean;

	procedure nestedProcedure;
	var
		c: char;
	begin
		// here, `f`, `c`, `nestedProcedure` and `super` are available
	end;
	procedure commonTask;
	var
		f: boolean;
	begin
		// here, `super`, `commonTask` and _only_ the _local_ `f` is available
	end;
var
	c: char;

	procedure fooBar;
	begin
		// here, `super`, `fooBar`, `f` and `c` are available
	end;
var
	x: integer;
begin
	// here, `c`, `f`, and `x`, as well as,
	// `nestedProcedure`, `commonTask`, `fooBar` and `super` are available
end;


use strict;
$x = 1;                   # Compilation error.
our $y = 2;
print "$y\n";             # Legal; refers to $main::y.

package Foo;
our $z = 3;
package Bar;
print "$z\n";             # Refers to $Foo::z.


forward function localf()    -- not normally necesssary, but will not harm
forward global function globalf()   -- ""

function localf()
    return 1
end function

global function globalf()
    return 2
end function


$a = "foo"                        # global scope
function test {
    $a = "bar"                    # local scope
    Write-Host Local: $a          # "bar" - local variable
    Write-Host Global: $global:a  # "foo" - global variable
}


;define a local integer variable by simply using it
baseAge.i = 10
;explicitly define local strings
Define person.s = "Amy", friend.s = "Susan"
;define variables that are both accessible inside and outside procedures
Global ageDiff = 3
Global extraYears = 5

Procedure test()
  ;define a local integer variable by simply using it
  baseAge.i = 30
  ;explicitly define a local string
  Define person.s = "Bob"
  ;allow access to a local variable in the main body of code
  Shared friend
  ;create a local variable distinct from a variable with global scope having the same name
  Protected extraYears = 2

  PrintN(person + " and " + friend + " are " + Str(baseAge) + " and " + Str(baseAge + ageDiff + extraYears) + " years old.")
EndProcedure

If OpenConsole()
  test()

  PrintN(person + " and " + friend + " are " + Str(baseAge) + " and " + Str(baseAge + ageDiff + extraYears) + " years old.")

  Print(#CRLF$ + #CRLF$ + "Press ENTER to exit")
  Input()
  CloseConsole()
EndIf


>>> x="From global scope"
>>> def outerfunc():
    x = "From scope at outerfunc"

    def scoped_local():
        x = "scope local"
        return "scoped_local scope gives x = " + x
    print(scoped_local())

    def scoped_nonlocal():
        nonlocal x
        return "scoped_nonlocal scope gives x = " + x
    print(scoped_nonlocal())

    def scoped_global():
        global x
        return "scoped_global scope gives x = " + x
    print(scoped_global())

    def scoped_notdefinedlocally():
        return "scoped_notdefinedlocally scope gives x = " + x
    print(scoped_notdefinedlocally())

>>> outerfunc()
scoped_local scope gives x = scope local
scoped_nonlocal scope gives x = From scope at outerfunc
scoped_global scope gives x = From global scope
scoped_notdefinedlocally scope gives x = From global scope
>>>


X <- "global x"
f <- function() {
  x <- "local x"
  print(x) #"local x"
}
f()                          #prints "local x"
print(x)                     #prints "global x"


my $lexical-variable;
our $package-variable;
state $persistent-lexical;
has $.public-attribute;


/*REXX program to display scope modifiers  (for subroutines/functions). */
a=1/4
b=20
c=3
d=5
call SSN_571  d**4

       /* at this point,  A   is    defined and equal to      .25       */
       /* at this point,  B   is    defined and equal to    40          */
       /* at this point,  C   is    defined and equal to    27          */
       /* at this point,  D   is    defined and equal to     5          */
       /* at this point,  FF  isn't defined.                            */
       /* at this point, EWE  is    defined and equal to 'female sheep' */
       /* at this point,  G   is    defined and equal to   625          */
exit                                   /*stick a fork in it, we're done.*/
/*─────────────────────────────────────SSN_571 submarine, er, subroutine*/
SSN_571: procedure expose b c ewe g;  parse arg g
b   = b*2
c   = c**3
ff  = b+c
ewe = 'female sheep'
d   = 55555555
return                     /*compliments to Jules Verne's Captain Nemo? */


class Demo
  #public methods here

  protected
  #protect methods here

  private
  #private methods
end


set globalVar "This is a global variable"
namespace eval nsA {
    variable varInA "This is a variable in nsA"
}
namespace eval nsB {
    variable varInB "This is a variable in nsB"
    proc showOff {varname} {
        set localVar "This is a local variable"
        global globalVar
        variable varInB
        namespace upvar ::nsA varInA varInA
        puts "variable $varname holds \"[set $varname]\""
    }
}
nsB::showOff globalVar
nsB::showOff varInA
nsB::showOff varInB
nsB::showOff localVar


@(maybe)@# perhaps this subclause suceeds or not
@  (block foo)
@  (bind a "a")
@  (accept foo)
@(end)
@(bind b "b")


local_shop      = 0
hidden_variable = 3

#library+

this_public_constant = local_shop
a_visible_function   = +

#library-

for_local_people = 7


class MyClass {
    construct new(a) {
        _a = a // creates an instance field _a automatically
    }
    a { _a } // allow public access to the field
}

var mc = MyClass.new(3)
System.print(mc.a)  // fine
System.print(mc._a) // can't access _a directly as its private to the class


F monkey_coconuts(sailors = 5)
   V nuts = sailors
   L
      V n0 = nuts
      [(Int, Int, Int)] wakes
      L(sailor) 0..sailors
         V (portion, remainder) = divmod(n0, sailors)
         wakes.append((n0, portion, remainder))
         I portion <= 0 | remainder != (I sailor != sailors {1} E 0)
            nuts++
            L.break
         n0 = n0 - portion - remainder
      L.was_no_break
         R (nuts, wakes)

L(sailors) [5, 6]
   V (nuts, wake_stats) = monkey_coconuts(sailors)
   print("\nFor #. sailors the initial nut count is #.".format(sailors, nuts))
   print("On each waking, the nut count, portion taken, and monkeys share are:\n  "wake_stats.map(ws -> String(ws)).join(",\n  "))


loop, 2
{
	sailor := A_Index+4
	while !result := Coco(sailor, A_Index)
		continue
	; format output
	remain := result["Coconuts"]
	output := sailor  " Sailors, Number of coconuts = " result["Coconuts"] "`n"
	loop % sailor {
		x := result["Sailor_" A_Index]
		output .= "Monkey gets 1, Sailor# " A_Index " hides (" remain "-1)/" sailor " = " x ", remainder = " (remain -= x+1) "`n"
	}
	output .= "Remainder = " result["Remaining"] "/" sailor " = " floor(result["Remaining"] / sailor)
	MsgBox % output
}
return

Coco(sailor, coconut){
	result := [], result["Coconuts"] := coconut
	loop % sailor {
		if (Mod(coconut, sailor) <> 1)
			return
		result["Sailor_" A_Index] := Floor(coconut/sailor)
		coconut -= Floor(coconut/sailor) + 1
	}
	if Mod(coconut, sailor) || !coconut
		return
	result["Remaining"] := coconut
	return result
}


# syntax: GAWK -f SAILORS_COCONUTS_AND_A_MONKEY_PROBLEM.AWK
# converted from LUA
BEGIN {
    for (n=2; n<=9; n++) {
      x = 0
      while (!valid(n,x)) {
        x++
      }
      printf("%d %d\n",n,x)
    }
    exit(0)
}
function valid(n,nuts,  k) {
    k = n
    while (k != 0) {
      if ((nuts % n) != 1) {
        return(0)
      }
      k--
      nuts = nuts - 1 - int(nuts / n)
    }
    return((nuts != 0) && (nuts % n == 0))
}


define coconuts(sailors, monkeys) {
	print "coconuts(", sailors, ", ", monkeys, ") = "
	if (sailors < 2 || monkeys < 1 || sailors <= monkeys) {
		return 0
	}
	blue_cocos = sailors-1
	pow_bc = blue_cocos^sailors
	x_cocos = pow_bc
	while ((x_cocos-blue_cocos)%sailors || (x_cocos-blue_cocos)/sailors < 1) {
		x_cocos += pow_bc
	}
	return (x_cocos/pow_bc*(sailors^sailors)-blue_cocos)*monkeys
}
scale = 0
coconuts(1, 1)
coconuts(2, 1)
coconuts(3, 1)
coconuts(3, 2)
coconuts(4, 1)
coconuts(5, 1)
coconuts(5, 4)
coconuts(6, 1)
coconuts(101, 1)


( ( divmod
  =   a b
    . !arg:(?a.?b)&(div$(!a.!b).mod$(!a.!b))
  )
& ( overnight
  =   ns nn result s q r
    .   !arg:(?ns.?nn)
      & :?result
      & 0:?s
      &   whl
        ' ( !s+1:?s:~>!ns
          & divmod$(!nn.!ns):(?q.?r)
          & !r:1
          & !q*(!ns+-1):?nn
          & !result (!s.!q.!r.!nn):?result
          )
      & !s:>!ns
      & divmod$(!nn.!ns):(?q.0)
      & !result
  )
& ( minnuts
  =   nsailors nnuts result sailor takes gives leaves
    .   !arg:?nsailors
      & 0:?nnuts
      &   whl
        ' ( 1+!nnuts:?nnuts
          & ~(overnight$(!nsailors.!nnuts):?result)
          )
      & out$(!nsailors ": " !nnuts)
      &   whl
        ' ( !result:(?sailor.?takes.?gives.?leaves) ?result
          &   out
            $ ( str
              $ ( " Sailor #"
                  !sailor
                  " takes "
                  !takes
                  ", giving "
                  !gives
                  " to the monkey and leaves "
                  !leaves
                )
              )
          )
      &   out
        $ ( str
          $ ("In the morning, each sailor gets " !leaves*!nsailors^-1 " nuts")
          )
  )
& 4:?n
&   whl
  ' ( 1+!n:~>6:?n
    & out$("Solution with " !n " sailors:")
    & minnuts$!n
    )
)


#include <stdio.h>

int valid(int n, int nuts)
{
	int k;
	for (k = n; k; k--, nuts -= 1 + nuts/n)
		if (nuts%n != 1) return 0;
	return nuts && !(nuts%n);
}

int main(void)
{
	int n, x;
	for (n = 2; n < 10; n++) {
		for (x = 0; !valid(n, x); x++);
		printf("%d: %d\n", n, x);
	}
	return 0;
}


class Test
{
    static bool valid(int n, int nuts)
    {
        for (int k = n; k != 0; k--, nuts -= 1 + nuts / n)
        {
            if (nuts % n != 1)
            {
                return false;
            }
        }

        return nuts != 0 && (nuts % n == 0);
    }

    static void Main(string[] args)
    {
        int x = 0;
        for (int n = 2; n < 10; n++)
        {
            while (!valid(n, x))
                x++;
            System.Console.WriteLine(n + ": " + x);
        }
    }
}


#include <iostream>

bool valid(int n, int nuts) {
    for (int k = n; k != 0; k--, nuts -= 1 + nuts / n) {
        if (nuts % n != 1) {
            return false;
        }
    }

    return nuts != 0 && (nuts % n == 0);
}

int main() {
    int x = 0;
    for (int n = 2; n < 10; n++) {
        while (!valid(n, x)) {
            x++;
        }
        std::cout << n << ": " << x << std::endl;
    }

    return 0;
}


(defn solves-for? [sailors initial-coconut-count]
  (with-local-vars [coconuts initial-coconut-count, hidings 0]
    (while (and (> @coconuts sailors) (= (mod @coconuts sailors) 1)
      (var-set coconuts (/ (* (dec @coconuts) (dec sailors)) sailors))
      (var-set hidings (inc @hidings)))
    (and (zero? (mod @coconuts sailors)) (= @hidings sailors))))

(doseq [sailors (range 5 7)]
  (let [start (first (filter (partial solves-for? sailors) (range)))]
    (println (str sailors " sailors start with " start " coconuts:"))
    (with-local-vars [coconuts start]
      (doseq [sailor (range sailors)]
        (let [hidden (/ (dec @coconuts) sailors)]
          (var-set coconuts (/ (* (dec @coconuts) (dec sailors)) sailors))
          (println (str "\tSailor " (inc sailor) " hides " hidden " coconuts and gives 1 to the monkey, leaving " @coconuts "."))))
      (println
        (str "\tIn the morning, each sailor gets another " (/ @coconuts sailors) " coconuts."))
      (println "\tThe monkey gets no more.\n"))))


import std.stdio;

void main() {
    auto coconuts = 11;

    outer:
    foreach (ns; 2..10) {
        int[] hidden = new int[ns];
        coconuts = (coconuts / ns) * ns + 1;
        while (true) {
            auto nc = coconuts;
            foreach (s; 1..ns+1) {
                if (nc % ns == 1) {
                    hidden[s-1] = nc/ns;
                    nc -= hidden[s-1] + 1;
                    if (s==ns && nc%ns==0) {
                        writeln(ns, " sailors require a minimum of ", coconuts, " coconuts");
                        foreach (t; 1..ns+1) {
                            writeln("\tSailor ", t, " hides ", hidden[t - 1]);
                        }
                        writeln("\tThe monkey gets ", ns);
                        writeln("\tFinally, each sailor takes ", nc / ns);
                        continue outer;
                    }
                } else {
                    break;
                }
            }
            coconuts += ns;
        }
    }
}


defmodule RC do
  def valid?(sailor, nuts), do: valid?(sailor, nuts, sailor)

  def valid?(sailor, nuts, 0), do: nuts > 0 and rem(nuts,sailor) == 0
  def valid?(sailor, nuts, _) when rem(nuts,sailor)!=1, do: false
  def valid?(sailor, nuts, i) do
    valid?(sailor, nuts - div(nuts,sailor) - 1, i-1)
  end
end

Enum.each([5,6], fn sailor ->
  nuts = Enum.find(Stream.iterate(sailor, &(&1+1)), fn n -> RC.valid?(sailor, n) end)
  IO.puts "\n#{sailor} sailors => #{nuts} coconuts"
  Enum.reduce(0..sailor, nuts, fn _,n ->
    {d, r} = {div(n,sailor), rem(n,sailor)}
    IO.puts "  #{inspect [n, d, r]}"
    n - 1 - d
  end)
end)


: total
  over * over 1- rot 0 ?do
    over over mod if dup xor swap leave else over over / 1+ rot + swap then
  loop drop
;

: sailors
  1+ 2 ?do
    1 begin i over total dup 0= while drop 1+ repeat cr i 0 .r ." : " . .
  loop
;

9 sailors


Dim As Integer cocos = 11

For ns As Integer = 2 To 9
    Dim As Integer oculta(ns)
    cocos = Int(cocos / ns) * ns + 1
    Do
        Dim As Integer nc = cocos
        For s As Integer = 1 To ns+1
            If nc Mod ns = 1 Then
                oculta(s-1) = Int(nc / ns)
                nc = nc - (oculta(s-1) + 1)
                If s = ns And Not (nc Mod ns) Then
                    Print ns; " marineros requieren un m¡nimo de"; cocos; " cocos"
                    For t As Integer = 1 To ns
                        Print !"\tEl marinero"; t; " se esconde"; oculta(t - 1)
                    Next t
                    Print !"\tEl mono obtiene"; ns
                    Print !"\tFinalmente, cada marinero se lleva"; Int(nc / ns); !"\n"
                    Exit Do
                End If
            Else
                Exit For
            End If
        Next s
        cocos += ns
    Loop
Next ns
Sleep


package main

import "fmt"

func main() {
    coconuts := 11
outer:
    for ns := 2; ns < 10; ns++ {
        hidden := make([]int, ns)
        coconuts = (coconuts/ns)*ns + 1
        for {
            nc := coconuts
            for s := 1; s <= ns; s++ {
                if nc%ns == 1 {
                    hidden[s-1] = nc / ns
                    nc -= hidden[s-1] + 1
                    if s == ns && nc%ns == 0 {
                        fmt.Println(ns, "sailors require a minimum of", coconuts, "coconuts")
                        for t := 1; t <= ns; t++ {
                            fmt.Println("\tSailor", t, "hides", hidden[t-1])
                        }
                        fmt.Println("\tThe monkey gets", ns)
                        fmt.Println("\tFinally, each sailor takes", nc/ns, "\b\n")
                        continue outer
                    }
                } else {
                    break
                }
            }
            coconuts += ns
        }
    }
}


import Control.Monad ((>=>))
import Data.Maybe (mapMaybe)
import System.Environment (getArgs)

-- Takes the number of sailors and the final number of coconuts. Returns
-- Just the associated initial number of coconuts and Nothing otherwise.
tryFor :: Int -> Int -> Maybe Int
tryFor s = foldr (>=>) pure $ replicate s step
  where
    step n
      | n `mod` (s - 1) == 0 = Just $ n * s `div` (s - 1) + 1
      | otherwise = Nothing

-- Gets the number of sailors from the first command-line argument and
-- assumes 5 as a default if none is given. Then uses tryFor to find the
-- smallest solution.
main :: IO ()
main = do
  args <- getArgs
  let n =
        case args of
          [] -> 5
          s:_ -> read s
      a = head . mapMaybe (tryFor n) $ [n,2 * n ..]
  print a


public class Test {

    static boolean valid(int n, int nuts) {
        for (int k = n; k != 0; k--, nuts -= 1 + nuts / n)
            if (nuts % n != 1)
                return false;
        return nuts != 0 && (nuts % n == 0);
    }

    public static void main(String[] args) {
        int x = 0;
        for (int n = 2; n < 10; n++) {
            while (!valid(n, x))
                x++;
            System.out.printf("%d: %d%n", n, x);
        }
    }
}


(function () {

    // wakeSplit :: Int -> Int -> Int -> Int
    function wakeSplit(intNuts, intSailors, intDepth) {
        var nDepth = intDepth !== undefined ? intDepth : intSailors,
            portion = Math.floor(intNuts / intSailors),
            remain = intNuts % intSailors;

        return 0 >= portion || remain !== (nDepth ? 1 : 0) ?
            null : nDepth ? wakeSplit(
                intNuts - portion - remain, intSailors, nDepth - 1
            ) : intNuts;
    }

    // TEST for 5, 6, and 7 intSailors
    return [5, 6, 7].map(function (intSailors) {
        var intNuts = intSailors;

        while (!wakeSplit(intNuts, intSailors)) intNuts += 1;

        return intNuts;
    });
})();


def until(cond; next): def _until: if cond then . else (next|_until) end; _until;


function validnutsforsailors(sailors, finalpile)
    for i in sailors:-1:1
        if finalpile % sailors != 1
            return false
        end
        finalpile -= Int(floor(finalpile/sailors) + 1)
    end
    (finalpile != 0) && (finalpile % sailors == 0)
end

function runsim()
    println("Sailors     Starting Pile")
    for sailors in 2:9
        finalcount = 0
        while validnutsforsailors(sailors, finalcount) == false
            finalcount += 1
        end
        println("$sailors           $finalcount")
    end
end

runsim()


// version 1.1.2

fun main(args: Array<String>) {
    var coconuts = 11
    outer@ for (ns in 2..9) {
        val hidden = IntArray(ns)
        coconuts = (coconuts / ns) * ns + 1
        while (true) {
            var nc = coconuts
            for (s in 1..ns) {
                if (nc % ns == 1) {
                    hidden[s - 1] = nc / ns
                    nc -= hidden[s - 1] + 1
                    if (s == ns && nc % ns == 0) {
                        println("$ns sailors require a minimum of $coconuts coconuts")
                        for (t in 1..ns) println("\tSailor $t hides ${hidden[t - 1]}")
                        println("\tThe monkey gets $ns")
                        println("\tFinally, each sailor takes ${nc / ns}\n")
                        continue@outer
                    }
                }
                else break
            }
            coconuts += ns
        }
    }
}


function valid(n,nuts)
    local k = n
    local i = 0
    while k ~= 0 do
        if (nuts % n) ~= 1 then
            return false
        end
        k = k - 1
        nuts = nuts - 1 - math.floor(nuts / n)
    end
    return nuts ~= 0 and (nuts % n == 0)
end

for n=2, 9 do
    local x = 0
    while not valid(n, x) do
        x = x + 1
    end
    print(n..": "..x)
end


ClearAll[SequenceOk]
SequenceOk[n_, k_] := Module[{m = n, q, r, valid = True},
  Do[
   {q, r} = QuotientRemainder[m, k];
   If[r != 1,
    valid = False;
    Break[];
    ];
   m -= q + 1
   ,
   {k}
   ];
  If[Mod[m, k] != 0,
   valid = False
   ];
  valid
  ]
i = 1;
While[! SequenceOk[i, 5], i++]
i

i = 1;
While[! SequenceOk[i, 6], i++]
i


MODULE Coconuts;
FROM FormatString IMPORT FormatString;
FROM Terminal IMPORT WriteString,WriteLn,ReadChar;

CONST MAX_SAILORS = 9;

PROCEDURE Scenario(coconuts,ns : INTEGER);
VAR
    buf : ARRAY[0..63] OF CHAR;
    hidden : ARRAY[0..MAX_SAILORS-1] OF INTEGER;
    nc,s,t : INTEGER;
BEGIN
    IF ns>MAX_SAILORS THEN RETURN END;

    coconuts := (coconuts DIV ns) * ns + 1;
    LOOP
        nc := coconuts;
        FOR s:=1 TO ns DO
            IF nc MOD ns = 1 THEN
                hidden[s-1] := nc DIV ns;
                nc := nc - hidden[s-1] - 1;
                IF (s=ns) AND (nc MOD ns = 0) THEN
                    FormatString("%i sailors require a minimum of %i coconuts\n", buf, ns, coconuts);
                    WriteString(buf);

                    FOR t:=1 TO ns DO
                        FormatString("\tSailor %i hides %i\n", buf, t, hidden[t-1]);
                        WriteString(buf)
                    END;

                    FormatString("\tThe monkey gets %i\n", buf, ns);
                    WriteString(buf);
                    FormatString("\tFinally, each sailor takes %i\n", buf, nc DIV ns);
                    WriteString(buf);
                    RETURN
                END
            ELSE
                BREAK
            END
        END;
        INC(coconuts,ns)
    END
END Scenario;

VAR
    ns : INTEGER;
BEGIN
    FOR ns:=2 TO MAX_SAILORS DO
        Scenario(11,ns);
    END;

    ReadChar
END Coconuts.


import strformat

var coconuts = 11

for ns in 2..9:
  var hidden = newSeq[int](ns)
  coconuts = (coconuts div ns) * ns + 1
  block Search:
    while true:
      var nc = coconuts
      for sailor in 1..ns:
        if nc mod ns == 1:
          hidden[sailor-1] = nc div ns
          dec nc, hidden[sailor-1] + 1
          if sailor == ns and nc mod ns == 0:
            echo &"{ns} sailors require a minimum of {coconuts} coconuts."
            for t in 1..ns:
              echo &"\tSailor {t} hides {hidden[t-1]}."
            echo &"\tThe monkey gets {ns}."
            echo &"\tFinally, each sailor takes {nc div ns}.\n"
            break Search # Done. Continue with more sailors or exit.
        else:
          break   # Failed. Continue search with more coconuts.
      inc coconuts, ns


class Program {
  function : Total(n : Int, nuts : Int) ~ Int {
    k := 0;
    for(nuts *= n; k < n; k++;) {
      if(nuts % (n-1) <> 0) { return 0; };
      nuts += nuts / (n-1) + 1;
    };

    return nuts;
  }

  function : Main(args : String[]) ~ Nil {
    for(n := 2; n < 10; n++;) {
      x := 0;  t := 0;
      do {
        x++;
        t := Total(n, x);
      }
      while(t = 0);
      "{$n}: {$t}, {$x}"->PrintLine();
    };
  }
}


use bigint;

for $sailors (1..15) { check( $sailors, coconuts( 0+$sailors ) ) }

sub is_valid {
    my($sailors, $nuts) = @_;
    return 0, 0 if $sailors == 1 and $nuts == 1;
    my @shares;
    for (1..$sailors) {
        return () unless ($nuts % $sailors) == 1;
        push @shares, int ($nuts-1)/$sailors;
        $nuts -= (1 + int $nuts/$sailors);
    }
    push @shares, int $nuts/$sailors;
    return @shares if !($nuts % $sailors);
}

sub check {
    my($sailors, $coconuts) = @_;
    my @suffix = ('th', 'st', 'nd', 'rd', ('th') x 6, ('th') x 10);
    my @piles = is_valid($sailors, $coconuts);
    if (@piles) {
        print "\nSailors $sailors: Coconuts $coconuts:\n";
        for my $k (0..-1 + $#piles) {
             print $k+1 . $suffix[$k+1] . " takes " . $piles[$k] . ", gives 1 to the monkey.\n"
        }
        print "The next morning, each sailor takes " . $piles[-1] . "\nwith none left over for the monkey.\n";
        return 1
    }
    return 0
}

sub coconuts {
    my($sailors) = @_;
    if ($sailors % 2 == 0 ) { ($sailors ** $sailors - 1) * ($sailors - 1) }
    else                    {  $sailors ** $sailors      -  $sailors + 1  }
}


procedure solve(integer sailors)
integer m, sm1 = sailors-1
    if sm1=0 then   -- edge condition for solve(1) [ avoid /0 ]
        m = sailors
    else
        for n=sailors to 1_000_000_000 by sailors do    -- morning pile divisible by #sailors
            m = n
            for j=1 to sailors do               -- see if all of the sailors could..
                if remainder(m,sm1)!=0 then     -- ..have pushed together sm1 piles
                    m = 0                       --  (no: try a higher n)
                    exit
                end if
                m = sailors*m/sm1+1     -- add sailor j's stash and one for the monkey
            end for
            if m!=0 then exit end if
        end for
    end if
    printf(1,"Solution with %d sailors: %d\n",{sailors,m})
    for i=1 to sailors do
        m -= 1                                  -- one for the monkey
        m /= sailors
        printf(1,"Sailor #%d takes %d, giving 1 to the monkey and leaving %d\n",{i,m,m*sm1})
        m *= (sm1)
    end for
    printf(1,"In the morning each sailor gets %d nuts\n",m/sailors)
end procedure

solve(5)
solve(6)


main ?=>
    between(2,9,N),           % N: number of sailors
    once s(N),
    fail.
main => true.

s(N) =>
    next_candidate(N+1,N,C),   % C: original number of coconuts
    divide(N,N,C,Cr),          % Cr: remainder
    printf("%d: original = %d, remainder = %d, final share = %d\n",N,C,Cr,Cr div N).

next_candidate(From,_Step,X) ?=> X = From.
next_candidate(From,Step,X) => next_candidate(From+Step,Step,X).

divide(N,0,C,Cr) => C > 0, C mod N == 0, Cr = C.
divide(N,I,C,Cr) =>
    (C-1) mod N == 0,
    Q = (C-1) div N,
    C1 = Q*(N-1),
    divide(N,I-1,C1,Cr).


def monkey_coconuts(sailors=5):
    "Parameterised the number of sailors using an inner loop including the last mornings case"
    nuts = sailors
    while True:
        n0, wakes = nuts, []
        for sailor in range(sailors + 1):
            portion, remainder = divmod(n0, sailors)
            wakes.append((n0, portion, remainder))
            if portion <= 0 or remainder != (1 if sailor != sailors else 0):
                nuts += 1
                break
            n0 = n0 - portion - remainder
        else:
            break
    return nuts, wakes

if __name__ == "__main__":
    for sailors in [5, 6]:
        nuts, wake_stats = monkey_coconuts(sailors)
        print("\nFor %i sailors the initial nut count is %i" % (sailors, nuts))
        print("On each waking, the nut count, portion taken, and monkeys share are:\n ",
              ',\n  '.join(repr(ws) for ws in wake_stats))


coconutsProblem <- function(sailorCount)
{
  stopifnot(sailorCount > 1) #Problem makes no sense otherwise
  initalCoconutCount <- sailorCount
  repeat
  {
    initalCoconutCount <- initalCoconutCount + 1
    coconutCount <- initalCoconutCount
    for(i in seq_len(sailorCount))
    {
      if(coconutCount %% sailorCount != 1) break
      coconutCount <- (coconutCount - 1) * (sailorCount - 1)/sailorCount
      if(i == sailorCount && coconutCount > 0 && coconutCount %% sailorCount == 0) return(initalCoconutCount)
    }
  }
}
print(data.frame("Sailors" = 2:8, "Coconuts" = sapply(2:8, coconutsProblem)))


#lang racket

(define (wake-and-split nuts sailors depth wakes)
  (define-values (portion remainder) (quotient/remainder nuts sailors))
  (define monkey (if (zero? depth) 0 1))
  (define new-wakes (cons (list nuts portion remainder) wakes))
  (and (positive? portion)
       (= remainder monkey)
       (if (zero? depth)
           new-wakes
           (wake-and-split (- nuts portion remainder) sailors (sub1 depth) new-wakes))))

(define (sleep-and-split nuts sailors)
  (wake-and-split nuts sailors sailors '()))

(define (monkey_coconuts (sailors 5))
    (let loop ([nuts sailors])
      (or (sleep-and-split nuts sailors)
          (loop (add1 nuts)))))

(for ([sailors (in-range 5 7)])
  (define wakes (monkey_coconuts sailors))
  (printf "For ~a sailors the initial nut count is ~a\n" sailors (first (last wakes)))
  (map displayln (reverse wakes))
  (newline))


my @ones = flat 'th', 'st', 'nd', 'rd', 'th' xx 6;
my @teens = 'th' xx 10;
my @suffix = lazy flat (@ones, @teens, @ones xx 8) xx *;

# brute force the first six
for 1 .. 6 -> $sailors { for $sailors .. * -> $coconuts { last if check( $sailors, $coconuts ) } }

# finesse 7 through 15
for 7 .. 15 -> $sailors { next if check( $sailors, coconuts( $sailors ) ) }

sub is_valid ( $sailors is copy, $nuts is copy ) {
    return 0, 0 if $sailors == $nuts == 1;
    my @shares;
    for ^$sailors {
        return () unless $nuts % $sailors == 1;
        push @shares, ($nuts - 1) div $sailors;
        $nuts -= (1 + $nuts div $sailors);
    }
    push @shares, $nuts div $sailors;
    return @shares if !?($nuts % $sailors);
}

sub check ($sailors, $coconuts) {
    if my @piles = is_valid($sailors, $coconuts) {
        say "\nSailors $sailors: Coconuts $coconuts:";
        for ^(@piles - 1) -> $k {
             say "{$k+1}@suffix[$k+1] takes @piles[$k], gives 1 to the monkey."
        }
        say "The next morning, each sailor takes @piles[*-1]\nwith none left over for the monkey.";
        return True;
    }
    False;
}

multi sub coconuts ( $sailors where { $sailors % 2 == 0 } ) { ($sailors - 1) * ($sailors ** $sailors - 1) }
multi sub coconuts ( $sailors where { $sailors % 2 == 1 } ) { $sailors ** $sailors - $sailors + 1 }


/*REXX program  solves  a  riddle  of 5 sailors, a pile of coconuts, and a monkey.      */
parse arg L H .;        if L==''  then L= 5      /*L  not specified?   Then use default.*/
                        if H==''  then H= 6      /*H   "      "          "   "  default.*/
                                                 /*{Tars is an old name for sailors.}   */
       do n=L  to H                              /*traipse through a number of sailors. */
                      do $=0  while \valid(n, $) /*perform while not valid coconuts.    */
                      end   /*$*/
       say 'sailors='n           "  coconuts="$  /*display number of sailors & coconuts.*/
       end  /*n*/
exit 0                                           /*stick a fork in it,  we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
valid: procedure;  parse arg n,nuts              /*obtain the number sailors & coconuts.*/
                 do k=n  by -1  for n            /*step through the possibilities.      */
                 if nuts//n \== 1  then return 0 /*Not one coconut left?   No solution. */
                 nuts=nuts  -  (1  +  nuts % n)  /*subtract number of coconuts from pile*/
                 end   /*k*/
       return (nuts \== 0)  &  \(nuts//n \== 0)  /*see if number coconuts>0 & remainder.*/


# Project : Sailors, coconuts and a monkey problem

scm(5)
scm(6)

func scm(sailors)
        sm1 = sailors-1
        if sm1 = 0
           m = sailors
        else
           for n=sailors to 1000000000 step sailors
                m = n
                for j=1 to sailors
                     if m % sm1 != 0
                        m = 0
                        exit
                     ok
                     m = sailors*m/sm1+1
                next
                if m != 0
                   exit
                ok
           next
        ok
        see "Solution with " + sailors + " sailors: " + m + nl
        for i=1 to sailors
             m = m - 1
             m = m / sailors
             see "Sailor " + i + " takes " + m + " giving 1 to the monkey and leaving " + m*sm1 + nl
             m = m * sm1
        next
        see "In the morning each sailor gets " + m/sailors + " nuts" + nl + nl


def valid?(sailor, nuts)
  sailor.times do
    return false if (nuts % sailor) != 1
    nuts -= 1 + nuts / sailor
  end
  nuts > 0 and nuts % sailor == 0
end

[5,6].each do |sailor|
  n = sailor
  n += 1 until valid?(sailor, n)
  puts "\n#{sailor} sailors => #{n} coconuts"
  (sailor+1).times do
    div, mod = n.divmod(sailor)
    puts "  #{[n, div, mod]}"
    n -= 1 + div
  end
end


object Sailors extends App {
  var x = 0

  private def valid(n: Int, _nuts: Int): Boolean = {
    var nuts = _nuts
    for (k <- n until 0 by -1) {
      if (nuts % n != 1) return false
      nuts -= 1 + nuts / n
    }
    nuts != 0 && (nuts % n == 0)
  }

  for (nSailors <- 2 until 10) {
    while (!valid(nSailors, x)) x += 1
    println(f"$nSailors%d: $x%d")
  }

}


func coconuts(sailors, monkeys=1) {
    if ((sailors < 2) || (monkeys < 1) || (sailors <= monkeys)) {
        return 0
    }
    var blue_cocos = sailors-1
    var pow_bc = blue_cocos**sailors
    var x_cocos = pow_bc
    while ((x_cocos-blue_cocos)%sailors || ((x_cocos-blue_cocos)/sailors < 1)) {
        x_cocos += pow_bc
    }
    return monkeys*(x_cocos / pow_bc * sailors**sailors - blue_cocos)
}

2.to(9).each { |sailor|
    say "#{sailor}: #{coconuts(sailor)}";
}


proc assert {expr {msg ""}} {    ;# for "static" assertions that throw nice errors
    if {![uplevel 1 [list expr $expr]]} {
        if {$msg eq ""} {
            catch {set msg "{[uplevel 1 [list subst -noc $expr]]}"}
        }
        throw {ASSERT ERROR} "{$expr} $msg"
    }
}

proc divmod {a b} {
    list [expr {$a / $b}] [expr {$a % $b}]
}

proc overnight {ns nn} {
    set result {}
    for {set s 0} {$s < $ns} {incr s} {
        lassign [divmod $nn $ns] q r
        assert {$r eq 1} "Incorrect remainder in round $s (expected 1, got $r)"
        set nn [expr {$q*($ns-1)}]
        lappend result $s $q $r $nn
    }
    lassign [divmod $nn $ns] q r
    assert {$r eq 0} "Incorrect remainder at end (expected 0, got $r)"
    return $result
}

proc minnuts {nsailors} {
    while 1 {
        incr nnuts
        try {
            set result [overnight $nsailors $nnuts]
        } on error {} {
            # continue
        } on ok {} {
            break
        }
    }
    puts "$nsailors: $nnuts"
    foreach {sailor takes gives leaves} $result {
        puts " Sailor #$sailor takes $takes, giving $gives to the monkey and leaves $leaves"
    }
    puts "In the morning, each sailor gets [expr {$leaves/$nsailors}] nuts"
}

foreach n {5 6} {
    puts "Solution with $n sailors:"
    minnuts $n
}


For n = 2 To 7
  t = 0
  For x = 1 Step 1 While t = 0
    t = FUNC(_Total(n,x))
  Next
  Print n;": ";t;Tab(12); x - 1
Next

End

_Total Param(2)
  Local(1)

  [email protected] = [email protected] * [email protected]
  [email protected] = [email protected] - 1

  For [email protected] = 0 To [email protected]

    If [email protected] % [email protected] Then
       [email protected] = 0
       Break
    EndIf

    [email protected] = [email protected] + 1 + [email protected] / [email protected]
  Next
Return ([email protected])


Option Explicit
Public Sub coconuts()
    Dim sailors As Integer
    Dim share As Long
    Dim finalshare As Integer
    Dim minimum As Long, pile As Long
    Dim i As Long, j As Integer
    Debug.Print "Sailors", "Pile", "Final share"
    For sailors = 2 To 6
        i = 1
        Do While True
            pile = i
            For j = 1 To sailors
                If (pile - 1) Mod sailors <> 0 Then Exit For
                share = (pile - 1) / sailors
                pile = pile - share - 1
            Next j
            If j > sailors Then
                If share Mod sailors = 0 And share > 0 Then
                    minimum = i
                    finalshare = pile / sailors
                    Exit Do
                End If
            End If
            i = i + 1
        Loop
        Debug.Print sailors, minimum, finalshare
    Next sailors
End Sub


var coconuts = 11
for (ns in 2..9) {
    var hidden = List.filled(ns, 0)
    coconuts = (coconuts/ns).floor * ns + 1
    while (true) {
        var nc = coconuts
        var outer = false
        for (s in 1..ns) {
            if (nc%ns == 1) {
                hidden[s-1] = (nc/ns).floor
                nc = nc - hidden[s-1] - 1
                if (s == ns && nc%ns == 0) {
                    System.print("%(ns) sailors require a minimum of %(coconuts) coconuts")
                    for (t in 1..ns) System.print("\tSailor %(t) hides %(hidden[t-1])")
                    System.print("\tThe monkey gets %(ns)")
                    System.print("\tFinally, each sailor takes %((nc/ns).floor)\n")
                    outer = true
                    break
                }
            } else {
                break
            }
        }
        if (outer) break
        coconuts = coconuts + ns
    }
}


coconuts = 11

for ns = 2 to 9
    dim hidden(ns)
    coconuts = int(coconuts / ns) * ns + 1
    do
        nc = coconuts
        for s = 1 to ns+1
            if mod(nc, ns) = 1 then
                hidden(s-1) = int(nc / ns)
                nc = nc - (hidden(s-1) + 1)
                if s = ns and not mod(nc, ns) then
                    print ns, " sailors require a minimum of ", coconuts, " coconuts"
                    for t = 1 to ns
                        print "\tSailor ", t, " hides ", hidden(t - 1)
                    next
                    print "\tThe monkey gets ", ns
                    print "\tFinally, each sailor takes ", int(nc / ns), "\n"
                    break 2
                end if
            else
                break
            end if
        next
        coconuts = coconuts + ns
    loop
next


fcn monkey_coconuts(sailors=5){
   nuts,wakes:=sailors,List();
   while(True){
      n0:=nuts; wakes.clear();
      foreach sailor in (sailors + 1){
         portion, remainder := n0.divr(sailors);
	 wakes.append(T(n0, portion, remainder));
	 if(portion <= 0 or remainder != (sailor != sailors).toInt()){
	    nuts += 1;
	    break;
	 }
	 n0 = n0 - portion - remainder;
      }
      fallthrough{ break }
   }

   return(nuts, wakes)
}
foreach sailors in ([5..6]){
   nuts, wake_stats := monkey_coconuts(sailors);
   println("For %d sailors the initial nut count is %,d".fmt(sailors, nuts));
   println("On each waking, the nut count, portion taken, and monkeys share are:\n   ",
      wake_stats.concat("\n   "));
}


generic
   type Data is private;
package Bin_Trees is

   type Tree_Type is private;

   function Empty(Tree: Tree_Type) return Boolean;
   function Left (Tree: Tree_Type) return Tree_Type;
   function Right(Tree: Tree_Type) return Tree_Type;
   function Item (Tree: Tree_Type) return Data;
   function Empty return Tree_Type;

   procedure Destroy_Tree(N: in out Tree_Type);
   function Tree(Value: Data) return Tree_Type;
   function Tree(Value: Data; Left, Right : Tree_Type) return Tree_Type;

private

   type Node;
   type Tree_Type is access Node;
   type Node is record
      Left, Right: Tree_Type := null;
      Item: Data;
   end record;

end Bin_Trees;


( ( T
  =
    .   ( next
        =   node stack rhs
          .   !arg:%?node ?stack
            &   whl
              ' ( !node:(?node.?rhs)
                & !rhs !stack:?stack
                )
            & (!node.!stack)
        )
      & !arg:(?stackA,?stackB)
      &   whl
        ' ( !stackA:~
          & !stackB:~
          & next$!stackA:(?leafA.?stackA)
          & next$!stackB:(?leafB.?stackB)
          & !leafA:!leafB
          )
      & out$!arg
      & (   !stackA:!stackB:
          & !leafA:!leafB
          & out$equal
        | out$"not equal"
        )
  )
& T$(x,x)
& T$((x.y),(x.y))
& T$(((x.y).z),(x.y.z))
& T$((x.y.z),(x.y.q))
& T$((x.y),(x.y.q))
& T$((x.y.z),(x.y))
& T$(((x.y).z),(x.z.y))
&   T
  $ ( (a.b.c.(x.y).z)
    , (((a.b).c).x.y.z)
    )
);


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

typedef struct {
	ucontext_t caller, callee;
	char stack[8192];
	void *in, *out;
} co_t;

co_t * co_new(void(*f)(), void *data)
{
	co_t * c = malloc(sizeof(*c));
	getcontext(&c->callee);
	c->in = data;

	c->callee.uc_stack.ss_sp = c->stack;
	c->callee.uc_stack.ss_size = sizeof(c->stack);
	c->callee.uc_link = &c->caller;
	makecontext(&c->callee, f, 1, (int)c);

	return c;
}

void co_del(co_t *c)
{
	free(c);
}

inline void
co_yield(co_t *c, void *data)
{
	c->out = data;
	swapcontext(&c->callee, &c->caller);
}

inline void *
co_collect(co_t *c)
{
	c->out = 0;
	swapcontext(&c->caller, &c->callee);
	return c->out;
}

// end of coroutine stuff

typedef struct node node;
struct node {
	int v;
	node *left, *right;
};

node *newnode(int v)
{
	node *n = malloc(sizeof(node));
	n->left = n->right = 0;
	n->v = v;
	return n;
}

void tree_insert(node **root, node *n)
{
	while (*root) root = ((*root)->v > n->v)
				? &(*root)->left
				: &(*root)->right;
	*root = n;
}

void tree_trav(int x)
{
	co_t *c = (co_t *) x;

	void trav(node *root) {
		if (!root) return;
		trav(root->left);
		co_yield(c, root);
		trav(root->right);
	}

	trav(c->in);
}

int tree_eq(node *t1, node *t2)
{
	co_t *c1 = co_new(tree_trav, t1);
	co_t *c2 = co_new(tree_trav, t2);

	node *p = 0, *q = 0;
	do {
		p = co_collect(c1);
		q = co_collect(c2);
	} while (p && q && (p->v == q->v));

	co_del(c1);
	co_del(c2);
	return !p && !q;
}

int main()
{
	int x[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1 };
	int y[] = { 2, 5, 7, 1, 9, 0, 6, 4, 8, 3, -1 };
	int z[] = { 0, 1, 2, 3, 4, 5, 6, 8, 9, -1 };

	node *t1 = 0, *t2 = 0, *t3 = 0;

	void mktree(int *buf, node **root) {
		int i;
		for (i = 0; buf[i] >= 0; i++)
			tree_insert(root, newnode(buf[i]));
	}

	mktree(x, &t1); // ordered binary tree, result of traversing
	mktree(y, &t2); // should be independent of insertion, so t1 == t2
	mktree(z, &t3);

	printf("t1 == t2: %s\n", tree_eq(t1, t2) ? "yes" : "no");
	printf("t1 == t3: %s\n", tree_eq(t1, t3) ? "yes" : "no");

	return 0;
}


using System;
using System.Collections.Generic;
using System.Linq;

namespace Same_Fringe
{
	class Program
	{
		static void Main()
		{
			var rnd = new Random(110456);
			var randList = Enumerable.Range(0, 20).Select(i => rnd.Next(1000)).ToList();
			var bt1 = new BinTree<int>(randList);
			// Shuffling will create a tree with the same values but different topology
			Shuffle(randList, 428);
			var bt2 = new BinTree<int>(randList);
			Console.WriteLine(bt1.CompareTo(bt2) ? "True compare worked" : "True compare failed");
			// Insert a 0 in the first tree which should cause a failure
			bt1.Insert(0);
			Console.WriteLine(bt1.CompareTo(bt2) ? "False compare failed" : "False compare worked");
		}

		static void Shuffle<T>(List<T> values, int seed)
		{
			var rnd = new Random(seed);

			for (var i = 0; i < values.Count - 2; i++)
			{
				var iSwap = rnd.Next(values.Count - i) + i;
				var tmp = values[iSwap];
				values[iSwap] = values[i];
				values[i] = tmp;
			}
		}
	}

	// Define other methods and classes here
	class BinTree<T> where T:IComparable
	{
		private BinTree<T> _left;
		private BinTree<T> _right;
		private T _value;

		private BinTree<T> Left
		{
			get { return _left; }
		}

		private BinTree<T> Right
		{
			get { return _right; }
		}

		// On interior nodes, any value greater than or equal to Value goes in the
		// right subtree, everything else in the left.
		private T Value
		{
			get { return _value; }
		}

		public bool IsLeaf { get { return Left == null; } }

		private BinTree(BinTree<T> left, BinTree<T> right, T value)
		{
			_left = left;
			_right = right;
			_value = value;
		}

		public BinTree(T value) : this(null, null, value) { }

		public BinTree(IEnumerable<T> values)
		{
			// ReSharper disable PossibleMultipleEnumeration
			_value = values.First();
			foreach (var value in values.Skip(1))
			{
				Insert(value);
			}
			// ReSharper restore PossibleMultipleEnumeration
		}

		public void Insert(T value)
		{
			if (IsLeaf)
			{
				if (value.CompareTo(Value) < 0)
				{
					_left = new BinTree<T>(value);
					_right = new BinTree<T>(Value);
				}
				else
				{
					_left = new BinTree<T>(Value);
					_right = new BinTree<T>(value);
					_value = value;
				}
			}
			else
			{
				if (value.CompareTo(Value) < 0)
				{
					Left.Insert(value);
				}
				else
				{
					Right.Insert(value);
				}
			}
		}

		public IEnumerable<T> GetLeaves()
		{
			if (IsLeaf)
			{
				yield return Value;
				yield break;
			}
			foreach (var val in Left.GetLeaves())
			{
				yield return val;
			}
			foreach (var val in Right.GetLeaves())
			{
				yield return val;
			}
		}

		internal bool CompareTo(BinTree<T> other)
		{
			return other.GetLeaves().Zip(GetLeaves(), (t1, t2) => t1.CompareTo(t2) == 0).All(f => f);
		}
	}
}


#include <algorithm>
#include <coroutine>
#include <iostream>
#include <memory>
#include <tuple>
#include <variant>

using namespace std;

class BinaryTree
{
  // C++ does not have a built in tree type.  The binary tree is a recursive
  // data type that is represented by an empty tree or a node the has a value
  // and a left and right sub-tree.  A tuple represents the node and unique_ptr
  // represents an empty vs. non-empty tree.
  using Node = tuple<BinaryTree, int, BinaryTree>;
  unique_ptr<Node> m_tree;

public:
  // Provide ways to make trees
  BinaryTree() = default; // Make an empty tree
  BinaryTree(BinaryTree&& leftChild, int value, BinaryTree&& rightChild)
  : m_tree {make_unique<Node>(move(leftChild), value, move(rightChild))} {}
  BinaryTree(int value) : BinaryTree(BinaryTree{}, value, BinaryTree{}){}
  BinaryTree(BinaryTree&& leftChild, int value)
  : BinaryTree(move(leftChild), value, BinaryTree{}){}
  BinaryTree(int value, BinaryTree&& rightChild)
  : BinaryTree(BinaryTree{}, value, move(rightChild)){}

  // Test if the tree is empty
  explicit operator bool() const
  {
    return (bool)m_tree;
  }

  // Get the value of the root node of the tree
  int Value() const
  {
    return get<1>(*m_tree);
  }

  // Get the left child tree
  const BinaryTree& LeftChild() const
  {
    return get<0>(*m_tree);
  }

  // Get the right child tree
  const BinaryTree& RightChild() const
  {
    return get<2>(*m_tree);
  }
};

// Define a promise type to be used for coroutines
struct TreeWalker {
  struct promise_type {
    int val;

    suspend_never initial_suspend() noexcept {return {};}
    suspend_never return_void() noexcept {return {};}
    suspend_always final_suspend() noexcept {return {};}
    void unhandled_exception() noexcept { }

    TreeWalker get_return_object()
    {
      return TreeWalker{coroutine_handle<promise_type>::from_promise(*this)};
    }

    suspend_always yield_value(int x) noexcept
    {
      val=x;
      return {};
    }
  };

  coroutine_handle<promise_type> coro;

  TreeWalker(coroutine_handle<promise_type> h): coro(h) {}

  ~TreeWalker()
  {
    if(coro) coro.destroy();
  }

  // Define an iterator type to work with the coroutine
  class Iterator
  {
    const coroutine_handle<promise_type>* m_h = nullptr;

  public:
    Iterator() = default;
    constexpr Iterator(const coroutine_handle<promise_type>* h) : m_h(h){}

    Iterator& operator++()
    {
      m_h->resume();
      return *this;
    }

    Iterator operator++(int)
    {
      auto old(*this);
      m_h->resume();
      return old;
    }

    int operator*() const
    {
      return m_h->promise().val;
    }

    bool operator!=(monostate) const noexcept
    {
      return !m_h->done();
      return m_h && !m_h->done();
    }

    bool operator==(monostate) const noexcept
    {
      return !operator!=(monostate{});
    }
  };

  constexpr Iterator begin() const noexcept
  {
    return Iterator(&coro);
  }

  constexpr monostate end() const noexcept
  {
    return monostate{};
  }
};

// Allow the iterator to be used like a standard library iterator
namespace std {
    template<>
    class iterator_traits<TreeWalker::Iterator>
    {
    public:
        using difference_type = std::ptrdiff_t;
        using size_type = std::size_t;
        using value_type = int;
        using pointer = int*;
        using reference = int&;
        using iterator_category = std::input_iterator_tag;
    };
}

// A coroutine that iterates though all of the fringe nodes
TreeWalker WalkFringe(const BinaryTree& tree)
{
  if(tree)
  {
    auto& left = tree.LeftChild();
    auto& right = tree.RightChild();
    if(!left && !right)
    {
      // a fringe node because it has no children
      co_yield tree.Value();
    }

    for(auto v : WalkFringe(left))
    {
      co_yield v;
    }

    for(auto v : WalkFringe(right))
    {
      co_yield v;
    }
  }
  co_return;
}

// Print a tree
void PrintTree(const BinaryTree& tree)
{
  if(tree)
  {
    cout << "(";
    PrintTree(tree.LeftChild());
    cout << tree.Value();
    PrintTree(tree.RightChild());
    cout <<")";
  }
}

// Compare two trees
void Compare(const BinaryTree& tree1, const BinaryTree& tree2)
{
  // Create a lazy range for both trees
  auto walker1 = WalkFringe(tree1);
  auto walker2 = WalkFringe(tree2);

  // Compare the ranges.
  bool sameFringe = ranges::equal(walker1.begin(), walker1.end(),
               walker2.begin(), walker2.end());

  // Print the results
  PrintTree(tree1);
  cout << (sameFringe ? " has same fringe as " : " has different fringe than ");
  PrintTree(tree2);
  cout << "\n";
}

int main()
{
  // Create two trees that that are different but have the same fringe nodes
  BinaryTree tree1(BinaryTree{6}, 77, BinaryTree{BinaryTree{3}, 77,
    BinaryTree{77, BinaryTree{9}}});
  BinaryTree tree2(BinaryTree{BinaryTree{BinaryTree{6}, 77}, 77, BinaryTree{
    BinaryTree{3}, 77, BinaryTree{9}}});
  // Create a tree with a different fringe
  BinaryTree tree3(BinaryTree{BinaryTree{BinaryTree{6}, 77}, 77, BinaryTree{77, BinaryTree{9}}});

  // Compare the trees
  Compare(tree1, tree2);
  Compare(tree1, tree3);
}


(defn fringe-seq [branch? children content tree]
  (letfn [(walk [node]
            (lazy-seq
              (if (branch? node)
                (if (empty? (children node))
                  (list (content node))
                  (mapcat walk (children node)))
                (list node))))]
    (walk tree)))


struct Node(T) {
    T data;
    Node* L, R;
}

bool sameFringe(T)(Node!T* t1, Node!T* t2) {
    T[] scan(Node!T* t) {
        if (!t) return [];
        return (!t.L && !t.R) ? [t.data] : scan(t.L) ~ scan(t.R);
    }
    return scan(t1) == scan(t2);
}

void main() {
    import std.stdio;
    alias N = Node!int;
    auto t1 = new N(10, new N(20, new N(30, new N(40), new N(50))));
    auto t2 = new N(1, new N(2, new N(3, new N(40), new N(50))));
    writeln(sameFringe(t1, t2));
    auto t3 = new N(1, new N(2, new N(3, new N(40), new N(51))));
    writeln(sameFringe(t1, t3));
}


package main

import "fmt"

type node struct {
    int
    left, right *node
}

// function returns a channel that yields the leaves of the tree.
// the channel is closed after all leaves are received.
func leaves(t *node) chan int {
    ch := make(chan int)
    // recursive function to walk tree.
    var f func(*node)
    f = func(n *node) {
        if n == nil {
            return
        }
        // leaves are identified by having no children.
        if n.left == nil && n.right == nil {
            ch <- n.int
        } else {
            f(n.left)
            f(n.right)
        }
    }
    // goroutine runs concurrently with others.
    // it walks the tree then closes the channel.
    go func() {
        f(t)
        close(ch)
    }()
    return ch
}

func sameFringe(t1, t2 *node) bool {
    f1 := leaves(t1)
    f2 := leaves(t2)
    for l1 := range f1 {
        // both trees must yield a leaf, and the leaves must be equal.
        if l2, ok := <-f2; !ok || l1 != l2 {
            return false
        }
    }
    // there must be nothing left in f2 after consuming all of f1.
    _, ok := <-f2
    return !ok
}

func main() {
    // the different shapes of the trees is shown with indention.
    // the leaves are easy to spot by the int: key.
    t1 := &node{3,
        &node{1,
            &node{int: 1},
            &node{int: 2}},
        &node{8,
            &node{int: 5},
            &node{int: 13}}}
    // t2 with negative values for internal nodes that can't possibly match
    // positive values in t1, just to show that only leaves are being compared.
    t2 := &node{-8,
        &node{-3,
            &node{-1,
                &node{int: 1},
                &node{int: 2}},
            &node{int: 5}},
        &node{int: 13}}
    fmt.Println(sameFringe(t1, t2)) // prints true.
}


data Tree a
  = Leaf a
  | Node (Tree a)
         (Tree a)
  deriving (Show, Eq)

fringe :: Tree a -> [a]
fringe (Leaf x) = [x]
fringe (Node n1 n2) = fringe n1 ++ fringe n2

sameFringe
  :: (Eq a)
  => Tree a -> Tree a -> Bool
sameFringe t1 t2 = fringe t1 == fringe t2

main :: IO ()
main = do
  let a = Node (Leaf 1) (Node (Leaf 2) (Node (Leaf 3) (Node (Leaf 4) (Leaf 5))))
      b = Node (Leaf 1) (Node (Node (Leaf 2) (Leaf 3)) (Node (Leaf 4) (Leaf 5)))
      c = Node (Node (Node (Node (Leaf 1) (Leaf 2)) (Leaf 3)) (Leaf 4)) (Leaf 5)
      x =
        Node
          (Leaf 1)
          (Node
             (Leaf 2)
             (Node (Leaf 3) (Node (Leaf 4) (Node (Leaf 5) (Leaf 6)))))
      y = Node (Leaf 0) (Node (Node (Leaf 2) (Leaf 3)) (Node (Leaf 4) (Leaf 5)))
      z = Node (Leaf 1) (Node (Leaf 2) (Node (Node (Leaf 4) (Leaf 3)) (Leaf 5)))
  mapM_ print $ sameFringe a <$> [a, b, c, x, y, z]


procedure main()
    aTree := [1, [2, [4, [7]], [5]], [3, [6, [8], [9]]]]
    bTree := [1, [2, [4, [7]], [5]], [3, [6, [8], [9]]]]
    write("aTree and bTree ",(sameFringe(aTree,bTree),"have")|"don't have",
          " the same leaves.")
    cTree := [1, [2, [4, [7]], [5]], [3, [6, [8]]]]
    dTree := [1, [2, [4, [7]], [5]], [3, [6, [8], [9]]]]
    write("cTree and dTree ",(sameFringe(cTree,dTree),"have")|"don't have",
          " the same leaves.")
end

procedure sameFringe(a,b)
    return same{genLeaves(a),genLeaves(b)}
end

procedure same(L)
   while n1 := @L[1] do {
      n2 := @L[2] | fail
      if n1 ~== n2 then fail
      }
   return not @L[2]
end

procedure genLeaves(t)
    suspend (*(node := preorder(t)) == 1, node[1])
end

procedure preorder(L)
    if \L then suspend L | preorder(L[2|3])
end


import java.util.*;

class SameFringe
{
  public interface Node<T extends Comparable<? super T>>
  {
    Node<T> getLeft();
    Node<T> getRight();
    boolean isLeaf();
    T getData();
  }

  public static class SimpleNode<T extends Comparable<? super T>> implements Node<T>
  {
    private final T data;
    public SimpleNode<T> left;
    public SimpleNode<T> right;

    public SimpleNode(T data)
    {  this(data, null, null);  }

    public SimpleNode(T data, SimpleNode<T> left, SimpleNode<T> right)
    {
      this.data = data;
      this.left = left;
      this.right = right;
    }

    public Node<T> getLeft()
    {  return left;  }

    public Node<T> getRight()
    {  return right;  }

    public boolean isLeaf()
    {  return ((left == null) && (right == null));  }

    public T getData()
    {  return data;  }

    public SimpleNode<T> addToTree(T data)
    {
      int cmp = data.compareTo(this.data);
      if (cmp == 0)
        throw new IllegalArgumentException("Same data!");
      if (cmp < 0)
      {
        if (left == null)
          return (left = new SimpleNode<T>(data));
        return left.addToTree(data);
      }
      if (right == null)
        return (right = new SimpleNode<T>(data));
      return right.addToTree(data);
    }
  }

  public static <T extends Comparable<? super T>> boolean areLeavesSame(Node<T> node1, Node<T> node2)
  {
    Stack<Node<T>> stack1 = new Stack<Node<T>>();
    Stack<Node<T>> stack2 = new Stack<Node<T>>();
    stack1.push(node1);
    stack2.push(node2);
    // NOT using short-circuit operator
    while (((node1 = advanceToLeaf(stack1)) != null) & ((node2 = advanceToLeaf(stack2)) != null))
      if (!node1.getData().equals(node2.getData()))
        return false;
    // Return true if finished at same time
    return (node1 == null) && (node2 == null);
  }

  private static <T extends Comparable<? super T>> Node<T> advanceToLeaf(Stack<Node<T>> stack)
  {
    while (!stack.isEmpty())
    {
      Node<T> node = stack.pop();
      if (node.isLeaf())
        return node;
      Node<T> rightNode = node.getRight();
      if (rightNode != null)
        stack.push(rightNode);
      Node<T> leftNode = node.getLeft();
      if (leftNode != null)
        stack.push(leftNode);
    }
    return null;
  }

  public static void main(String[] args)
  {
    SimpleNode<Integer> headNode1 = new SimpleNode<Integer>(35, new SimpleNode<Integer>(25, new SimpleNode<Integer>(15, new SimpleNode<Integer>(10), new SimpleNode<Integer>(20)), new SimpleNode<Integer>(30)), new SimpleNode<Integer>(45, new SimpleNode<Integer>(40), new SimpleNode<Integer>(50)));
    SimpleNode<Integer> headNode2 = new SimpleNode<Integer>(24, new SimpleNode<Integer>(14, new SimpleNode<Integer>(10), new SimpleNode<Integer>(16, null, new SimpleNode<Integer>(20))), new SimpleNode<Integer>(34, new SimpleNode<Integer>(30), new SimpleNode<Integer>(42, new SimpleNode<Integer>(40), new SimpleNode<Integer>(56, new SimpleNode<Integer>(50), null))));
    SimpleNode<Integer> headNode3 = new SimpleNode<Integer>(24, new SimpleNode<Integer>(14, new SimpleNode<Integer>(10), new SimpleNode<Integer>(16, null, new SimpleNode<Integer>(20))), new SimpleNode<Integer>(34, new SimpleNode<Integer>(30), new SimpleNode<Integer>(42, new SimpleNode<Integer>(40), new SimpleNode<Integer>(50, null, new SimpleNode<Integer>(56)))));
    System.out.print("Leaves for set 1: ");
    simpleWalk(headNode1);
    System.out.println();
    System.out.print("Leaves for set 2: ");
    simpleWalk(headNode2);
    System.out.println();
    System.out.print("Leaves for set 3: ");
    simpleWalk(headNode3);
    System.out.println();
    System.out.println("areLeavesSame(1, 2)? " + areLeavesSame(headNode1, headNode2));
    System.out.println("areLeavesSame(2, 3)? " + areLeavesSame(headNode2, headNode3));
  }

  public static void simpleWalk(Node<Integer> node)
  {
    if (node.isLeaf())
      System.out.print(node.getData() + " ");
    else
    {
      Node<Integer> left = node.getLeft();
      if (left != null)
        simpleWalk(left);
      Node<Integer> right = node.getRight();
      if (right != null)
        simpleWalk(right);
    }
  }
}


using Lazy

"""
    Input a tree for display as a fringed structure.
"""
function fringe(tree)
    fringey(node::Pair) = [fringey(i) for i in node]
    fringey(leaf::Int) = leaf
    fringey(tree)
end

"""
    equalsfringe() uses a reduction to a lazy 1D list via
    getleaflist() for its "equality" of fringes
"""
getleaflist(tree::Int) = [tree]
getleaflist(tree::Pair) = vcat(getleaflist(seq(tree[1])), getleaflist(seq(tree[2])))
getleaflist(tree::Lazy.LazyList) = vcat(getleaflist(tree[1]), getleaflist(tree[2]))
getleaflist(tree::Void) = []
equalsfringe(t1, t2) = (getleaflist(t1) == getleaflist(t2))

a = 1 => 2 => 3 => 4 => 5 => 6 => 7 => 8
b = 1 => (( 2 => 3 ) => (4 => (5 => ((6 => 7) => 8))))
c = (((1 => 2) => 3) => 4) => 5 => 6 => 7 => 8

x = 1 => 2 => 3 => 4 => 5 => 6 => 7 => 8 => 9
y = 0 => 2 => 3 => 4 => 5 => 6 => 7 => 8
z = 1 => 2 => (4 => 3) => 5 => 6 => 7 => 8

prettyprint(s) = println(replace("$s", r"\{Any,1\}|Any|Array\{T,1\}\swhere\sT|Array|", ""))
prettyprint(fringe(a))
prettyprint(fringe(b))
prettyprint(fringe(c))
prettyprint(fringe(x))
prettyprint(fringe(y))
prettyprint(fringe(z))

prettyprint(getleaflist(a))
prettyprint(getleaflist(b))
prettyprint(getleaflist(c))

println(equalsfringe(a, a))
println(equalsfringe(a, b))
println(equalsfringe(a, c))
println(equalsfringe(b, c))
println(equalsfringe(a, x) == false)
println(equalsfringe(a, y) == false)
println(equalsfringe(a, z) == false)


local type, insert, remove = type, table.insert, table.remove

None = {} -- a unique object for a truncated branch (i.e. empty subtree)
function isbranch(node) return type(node) == 'table' and #node == 2 end
function left(node) return node[1] end
function right(node) return node[2] end

function fringeiter(tree)
    local agenda = {tree}
    local function push(item) insert(agenda, item) end
    local function pop() return remove(agenda) end
    return function()
        while #agenda > 0 do
            node = pop()
            if isbranch(node) then
                push(right(node))
                push(left(node))
            elseif node == None then
                -- continue
            else
                return node
            end
        end
    end
end

function same_fringe(atree, btree)
    local anext = fringeiter(atree or None)
    local bnext = fringeiter(btree or None)
    local pos = 0
    repeat
        local aitem, bitem = anext(), bnext()
        pos = pos + 1
        if aitem ~= bitem then
            return false, string.format("at position %d, %s ~= %s", pos, aitem, bitem)
        end
    until not aitem
    return true
end

t1 = {1, {2, {3, {4, {5, None}}}}}
t2 = {{1,2}, {{3, 4}, 5}}
t3 = {{{1,2}, 3}, 4}

function compare_fringe(label, ta, tb)
    local equal, nonmatch = same_fringe(ta, tb)
    io.write(label .. ": ")
    if equal then
        print("same fringe")
    else
        print(nonmatch)
    end
end

compare_fringe("(t1, t2)", t1, t2)
compare_fringe("(t1, t3)", t1, t3)