#!/usr/bin/env rune
pragma.syntax("0.9")

def pi := (-1.0).acos()
def makeEPainter := <unsafe:com.zooko.tray.makeEPainter>
def colors := <awt:makeColor>

# --------------------------------------------------------------
# --- Definitions

/** Execute 'task' repeatedly as long 'indicator' is unresolved. */
def doWhileUnresolved(indicator, task) {
  def loop() {
    if (!Ref.isResolved(indicator)) {
      task()
      loop <- ()
    }
  }
  loop <- ()
}

/** The data structure specified for the task. */
def makeBuckets(size) {
    def values := ([100] * size).diverge() # storage
    def buckets {
        to size() :int { return size }
        /** get current quantity in bucket 'i' */
        to get(i :int) { return values[i] }
        /** transfer 'amount' units, as much as possible, from bucket 'i' to bucket 'j'
            or vice versa if 'amount' is negative */
        to transfer(i :int, j :int, amount :int) {
            def amountLim := amount.min(values[i]).max(-(values[j]))
            values[i] -= amountLim
            values[j] += amountLim
        }
    }
    return buckets
}

/** A view of the current state of the buckets. */
def makeDisplayComponent(buckets) {
  def c := makeEPainter(def paintCallback {
    to paintComponent(g) {
      def pixelsW := c.getWidth()
      def pixelsH := c.getHeight()
      def bucketsW := buckets.size()

      g.setColor(colors.getWhite())
      g.fillRect(0, 0, pixelsW, pixelsH)

      g.setColor(colors.getDarkGray())
      var sum := 0
      for i in 0..!bucketsW {
        sum += def value := buckets[i]
        def x0 := (i       * pixelsW / bucketsW).floor()
        def x1 := ((i + 1) * pixelsW / bucketsW).floor()
        g.fillRect(x0 + 1, pixelsH - value,
                   x1 - x0 - 1, value)
      }

      g.setColor(colors.getBlack())
      g."drawString(String, int, int)"(`Total: $sum`, 2, 20)
    }
  })
  c.setPreferredSize(<awt:makeDimension>(500, 300))
  return c
}

# --------------------------------------------------------------
# --- Application setup

def buckets := makeBuckets(100)
def done # Promise indicating when the window is closed

# Create the window
def frame := <unsafe:javax.swing.makeJFrame>("Atomic transfers")
frame.setContentPane(def display := makeDisplayComponent(buckets))
frame.addWindowListener(def mainWindowListener {
  to windowClosing(event) :void {
    bind done := null
  }
  match _ {}
})
frame.setLocation(50, 50)
frame.pack()

# --------------------------------------------------------------
# --- Tasks

# Neatens up buckets
var ni := 0
doWhileUnresolved(done, fn {
  def i := ni
  def j := (ni + 1) %% buckets.size()
  buckets.transfer(i, j, (buckets[i] - buckets[j]) // 4)
  ni := j
})

# Messes up buckets
var mi := 0
doWhileUnresolved(done, fn {
    def i := (mi + entropy.nextInt(3)) %% buckets.size()
    def j := (i + entropy.nextInt(3)) %% buckets.size() #entropy.nextInt(buckets.size())
    buckets.transfer(i, j, (buckets[i] / pi).floor())
    mi := j
})

# Updates display at fixed 10 Hz
# (Note: tries to catch up; on slow systems slow this down or it will starve the other tasks)
def clock := timer.every(100, def _(_) {
  if (Ref.isResolved(done)) {
    clock.stop()
  } else {
    display.repaint()
  }
})
clock.start()

# --------------------------------------------------------------
# --- All ready, go visible and wait

frame.show()
interp.waitAtTop(done)


Loop, 100
  Door%A_Index% := "closed"

Loop, 100 {
  x := A_Index, y := A_Index
  While (x <= 100)
  {
    CurrentDoor := Door%x%
    If CurrentDoor contains closed
    {
      Door%x% := "open"
      x += y
    }
    else if CurrentDoor contains open
    {
      Door%x% := "closed"
      x += y
    }
  }
}

Loop, 100 {
   CurrentDoor := Door%A_Index%
   If CurrentDoor contains open
      Res .= "Door " A_Index " is open`n"
}
MsgBox % Res


#lang racket
(require math/number-theory)
(define attractive? (compose1 prime? prime-omega))
(filter attractive? (range 1 121))


use Lingua::EN::Numbers;
use ntheory:from<Perl5> <factor is_prime>;

sub display ($n,$m) { ($n..$m).grep: (~*).&factor.elems.&is_prime }

sub count ($n,$m) { +($n..$m).grep: (~*).&factor.elems.&is_prime }

# The Task
put "Attractive numbers from 1 to 120:\n" ~
display(1, 120)».fmt("%3d").rotor(20, :partial).join: "\n";

# Robusto!
for 1, 1000,  1, 10000, 1, 100000, 2**73 + 1, 2**73 + 100 -> $a, $b {
    put "\nCount of attractive numbers from {comma $a} to {comma $b}:\n" ~
    comma count $a, $b
}


/*REXX program finds and shows lists (or counts) attractive numbers up to a specified N.*/
parse arg N .                                    /*get optional argument from the C.L.  */
if N=='' | N==","  then N= 120                   /*Not specified?  Then use the default.*/
cnt= N<0                                         /*semaphore used to control the output.*/
N= abs(N)                                        /*ensure that  N  is a positive number.*/
call genP 100                                    /*gen 100 primes (high= 541); overkill.*/
sw= linesize()  -  1                             /*SW:    is the usable screen width.   */
if \cnt  then say 'attractive numbers up to and including '      commas(N)        " are:"
#= 0                                             /*number of attractive #'s  (so far).  */
$=                                               /*a list of attractive numbers (so far)*/
    do j=1  for N;   if @.j  then iterate        /*Is it a low prime?  Then skip number.*/
          a= cFact(j)                            /*call cFact to count the factors in J.*/
    if \@.a  then iterate                        /*if # of factors not prime, then skip.*/
    #= # + 1                                     /*bump number of attractive #'s found. */
    if cnt   then iterate                        /*if not displaying numbers, skip list.*/
    cj= commas(j);             _= $ cj           /*append a commatized number to $ list.*/
    if length(_)>sw  then do;  say strip($);  $= cj;  end   /*display a line of numbers.*/
                     else                     $= _          /*append the latest number. */
    end   /*j*/

if $\==''  &  \cnt   then say strip($)           /*display any residual numbers in list.*/
say;     say commas(#)     ' attractive numbers found up to and including '      commas(N)
exit                                             /*stick a fork in it,  we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
cFact: procedure;  parse arg z 1 oz;  if z<2  then return z  /*if Z too small, return Z.*/
       #= 0                                      /*#:  is the number of factors (so far)*/
             do  while z//2==0;  #= #+1;  z= z%2;  end  /*maybe add the factor of two.  */
             do  while z//3==0;  #= #+1;  z= z%3;  end  /*  "    "   "     "    " three.*/
             do  while z//5==0;  #= #+1;  z= z%5;  end  /*  "    "   "     "    " five. */
             do  while z//7==0;  #= #+1;  z= z%7;  end  /*  "    "   "     "    " seven.*/
                                                 /* [↑]  reduce  Z  by some low primes. */
          do k=11  by 6  while k<=z              /*insure that  K  isn't divisible by 3.*/
          parse var k  ''  -1  _                 /*obtain the last decimal digit of  K. */
          if _\==5  then do  while z//k==0;  #= #+1;   z= z%k;   end   /*maybe reduce Z.*/
          if _ ==3  then iterate                 /*Next number ÷ by 5?  Skip.   ____    */
          if k*k>oz then leave                   /*are we  greater  than the   √ OZ  ?  */
          y= k + 2                               /*get next divisor,  hopefully a prime.*/
                         do while  z//y==0;  #= #+1;   z= z%y;   end   /*maybe reduce Z.*/
          end   /*k*/
       if z\==1  then return # + 1               /*if residual isn't unity, then add one*/
                      return #                   /*return the number of factors in  OZ. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
commas: parse arg ?;  do jc=length(?)-3  to 1  by -3; ?=insert(',', ?, jc); end;  return ?
/*──────────────────────────────────────────────────────────────────────────────────────*/
genP: procedure expose @.; parse arg n;           @.=0;         @.2= 1;     @.3= 1;   p= 2
        do j=3  by 2  until p==n;   do k=3  by 2  until k*k>j;  if j//k==0  then iterate j
                                    end  /*k*/;             @.j = 1;        p= p + 1
        end   /*j*/;          return             /* [↑]  generate  N  primes.           */


function move(sequence s, integer amount, integer src, integer dest)
    if src < 1 or src > length(s) or dest < 1 or dest > length(s) or amount < 0 then
        return -1
    else
        if src != dest and amount then
            if amount > s[src] then
                amount = s[src]
            end if
            s[src] -= amount
            s[dest] += amount
        end if
        return s
    end if
end function

sequence buckets
buckets = repeat(100,10)

procedure equalize()
    integer i, j, diff
    while 1 do
        i = rand(length(buckets))
        j = rand(length(buckets))
        diff = buckets[i] - buckets[j]
        if  diff >= 2 then
            buckets = move(buckets, floor(diff / 2), i, j)
        elsif diff <= -2 then
            buckets = move(buckets, -floor(diff / 2), j, i)
        end if
        task_yield()
    end while
end procedure

procedure redistribute()
    integer i, j
    while 1 do
        i = rand(length(buckets))
        j = rand(length(buckets))
        if buckets[i] then
            buckets = move(buckets, rand(buckets[i]), i, j)
        end if
        task_yield()
    end while
end procedure

function sum(sequence s)
    integer sum
    sum = 0
    for i = 1 to length(s) do
        sum += s[i]
    end for
    return sum
end function

atom task

task = task_create(routine_id("equalize"), {})
task_schedule(task, 1)

task = task_create(routine_id("redistribute"), {})
task_schedule(task, 1)

task_schedule(0, {0.5, 0.5})

for i = 1 to 24 do
    print(1,buckets)
    printf(1," sum: %d\n", {sum(buckets)})
    task_yield()
end for


#include <array.au3>
$doors = 100

;door array, 0 = closed, 1 = open
Local $door[$doors +1]

For $ii = 1 To $doors
	For $i = $ii To $doors Step $ii
		$door[$i] = Not $door[$i]
	next
Next

;display to screen
For $i = 1 To $doors
	ConsoleWrite (Number($door[$i])& " ")
	If Mod($i,10) = 0 Then ConsoleWrite(@CRLF)
Next


# Project: Attractive Numbers

decomp = []
nump = 0
see "Attractive Numbers up to 120:" + nl
while nump < 120
decomp = []
nump = nump + 1
for i = 1 to nump
    if isPrime(i) and nump%i = 0
       add(decomp,i)
       dec = nump/i
       while dec%i = 0
             add(decomp,i)
             dec = dec/i
       end
    ok
next
if isPrime(len(decomp))
   see string(nump) + " = ["
for n = 1 to len(decomp)
    if n < len(decomp)
       see string(decomp[n]) + "*"
    else
       see string(decomp[n]) + "] - " + len(decomp) + " is prime" + nl
    ok
next
ok
end

func isPrime(num)
     if (num <= 1) return 0 ok
     if (num % 2 = 0) and num != 2 return 0 ok
     for i = 3 to floor(num / 2) -1 step 2
         if (num % i = 0) return 0 ok
     next
     return 1


require "prime"

p (1..120).select{|n| n.prime_division.sum(&:last).prime? }


use primal::Primes;

const MAX: u64 = 120;

/// Returns an Option with a tuple => Ok((smaller prime factor, num divided by that prime factor))
/// If num is a prime number itself, returns None
fn extract_prime_factor(num: u64) -> Option<(u64, u64)> {
    let mut i = 0;
    if primal::is_prime(num) {
        None
    } else {
        loop {
            let prime = Primes::all().nth(i).unwrap() as u64;
            if num % prime == 0 {
                return Some((prime, num / prime));
            } else {
                i += 1;
            }
        }
    }
}

/// Returns a vector containing all the prime factors of num
fn factorize(num: u64) -> Vec<u64> {
    let mut factorized = Vec::new();
    let mut rest = num;
    while let Some((prime, factorizable_rest)) = extract_prime_factor(rest) {
        factorized.push(prime);
        rest = factorizable_rest;
    }
    factorized.push(rest);
    factorized
}

fn main() {
    let mut output: Vec<u64> = Vec::new();
    for num in 4 ..= MAX {
        if primal::is_prime(factorize(num).len() as u64) {
            output.push(num);
        }
    }
    println!("The attractive numbers up to and including 120 are\n{:?}", output);
}


object AttractiveNumbers extends App {
  private val max = 120
  private var count = 0

  private def nFactors(n: Int): Int = {
    @scala.annotation.tailrec
    def factors(x: Int, f: Int, acc: Int): Int =
      if (f * f > x) acc + 1
      else
        x % f match {
          case 0 => factors(x / f, f, acc + 1)
          case _ => factors(x, f + 1, acc)
        }

    factors(n, 2, 0)
  }

  private def ls: Seq[String] =
    for (i <- 4 to max;
         n = nFactors(i)
         if n >= 2 && nFactors(n) == 1 // isPrime(n)
         ) yield f"$i%4d($n)"

  println(f"The attractive numbers up to and including $max%d are: [number(factors)]\n")
  ls.zipWithIndex
    .groupBy { case (_, index) => index / 20 }
    .foreach { case (_, row) => println(row.map(_._1).mkString) }
}


open System.Threading

type Buckets(n) =
  let rand = System.Random()
  let mutex = Array.init n (fun _ -> new Mutex())
  let bucket = Array.init n (fun _ -> 100)

  member this.Count = n

  member this.Item n = bucket.[n]

  member private this.Lock is k =
    let is = Seq.sort is
    for i in is do
      mutex.[i].WaitOne() |> ignore
    try k() finally
    for i in is do
      mutex.[i].ReleaseMutex()

  member this.Transfer i j d =
    if i <> j && d <> 0 then
      let i, j, d = if d > 0 then i, j, d else j, i, -d
      this.Lock [i; j] (fun () ->
        let d = min d bucket.[i]
        bucket.[i] <- bucket.[i] - d
        bucket.[j] <- bucket.[j] + d)

  member this.Read =
    this.Lock [0..n-1] (fun () -> Array.copy bucket)

  member this.Print() =
    let xs = this.Read
    printf "%A = %d\n" xs (Seq.sum xs)

  interface System.IDisposable with
    member this.Dispose() =
      for m in mutex do
        (m :> System.IDisposable).Dispose()

let transfers = ref 0
let max_transfers = 1000000

let rand_pair (rand: System.Random) n =
  let i, j = rand.Next n, rand.Next(n-1)
  i, if j<i then j else j+1

let equalizer (bucket: Buckets) () =
  let rand = System.Random()
  while System.Threading.Interlocked.Increment transfers < max_transfers do
    let i, j = rand_pair rand bucket.Count
    let d = (bucket.[i] - bucket.[j]) / 2
    if d > 0 then
      bucket.Transfer i j d
    else
      bucket.Transfer j i -d

let randomizer (bucket: Buckets) () =
  let rand = System.Random()
  while System.Threading.Interlocked.Increment transfers < max_transfers do
    let i, j = rand_pair rand bucket.Count
    let d = 1 + rand.Next bucket.[i]
    bucket.Transfer i j d

do
  use bucket = new Buckets(10)
  let equalizer = Thread(equalizer bucket)
  let randomizer = Thread(randomizer bucket)
  bucket.Print()
  equalizer.Start()
  randomizer.Start()
  while !transfers < max_transfers do
    Thread.Sleep 100
    bucket.Print()


func is_attractive(n) {
    n.bigomega.is_prime
}

1..120 -> grep(is_attractive).say


import Foundation

extension BinaryInteger {
  @inlinable
  public var isAttractive: Bool {
    return primeDecomposition().count.isPrime
  }

  @inlinable
  public var isPrime: Bool {
    if self == 0 || self == 1 {
      return false
    } else if self == 2 {
      return true
    }

    let max = Self(ceil((Double(self).squareRoot())))

    for i in stride(from: 2, through: max, by: 1) {
      if self % i == 0 {
        return false
      }
    }

    return true
  }

  @inlinable
  public func primeDecomposition() -> [Self] {
    guard self > 1 else { return [] }

    func step(_ x: Self) -> Self {
      return 1 + (x << 2) - ((x >> 1) << 1)
    }

    let maxQ = Self(Double(self).squareRoot())
    var d: Self = 1
    var q: Self = self & 1 == 0 ? 2 : 3

    while q <= maxQ && self % q != 0 {
      q = step(d)
      d += 1
    }

    return q <= maxQ ? [q] + (self / q).primeDecomposition() : [self]
  }
}

let attractive = Array((1...).lazy.filter({ $0.isAttractive }).prefix(while: { $0 <= 120 }))

print("Attractive numbers up to and including 120: \(attractive)")


proc isPrime {n} {
    if {$n < 2} {
        return 0
    }
    if {$n > 3} {
        if {0 == ($n % 2)} {
            return 0
        }
        for {set d 3} {($d * $d) <= $n} {incr d 2} {
            if {0 == ($n % $d)} {
                return 0
            }
        }
    }
    return 1                    ;# no divisor found
}

proc cntPF {n} {
    set cnt 0
    while {0 == ($n % 2)} {
        set n [expr {$n / 2}]
        incr cnt
    }
    for {set d 3} {($d * $d) <= $n} {incr d 2} {
        while {0 == ($n % $d)} {
            set n [expr {$n / $d}]
            incr cnt
        }
    }
    if {$n > 1} {
        incr cnt
    }
    return $cnt
}

proc showRange {lo hi} {
    puts "Attractive numbers in range $lo..$hi are:"
    set k 0
    for {set n $lo} {$n <= $hi} {incr n} {
        if {[isPrime [cntPF $n]]} {
            puts -nonewline " [format %3s $n]"
            incr k
        }
        if {$k >= 20} {
            puts ""
            set k 0
        }
    }
    if {$k > 0} {
        puts ""
    }
}
showRange 1 120


Randomize Timer
Dim Shared As Uinteger cubo(1 To 10), a, i
For i As Uinteger = 1 To 10
    cubo(i) = Int(Rnd * 90)
Next i

Function Display(cadena As String) As Uinteger
    Dim As Uinteger valor
    Print cadena; Spc(2);
    For i As Uinteger = 1 To 10
        valor += cubo(i)
        Print Using "###"; cubo(i);
    Next i
    Print " Total:"; valor
    Return valor
End Function

Sub Flatten(f As Uinteger)
    Dim As Uinteger f1 = Int((f / 10) + .5), f2
    For i As Uinteger = 1 To 10
        cubo(i) = f1
        f2 += f1
    Next i
    cubo(10) += f - f2
End Sub

Sub Transfer(a1 As Uinteger, a2 As Uinteger)
    Dim As Uinteger temp = Int(Rnd * cubo(a1))
    cubo(a1) -= temp
    cubo(a2) += temp
End Sub

a = Display("        Display:")   ' show original array
Flatten(a)                        ' flatten the array
a = Display("        Flatten:")   ' show flattened array
Transfer(3, 5)                    ' transfer some amount from 3 to 5
Display(" 19 from 3 to 5:")       ' show transfer array
Sleep


package main

import (
    "fmt"
    "math/rand"
    "sync"
    "time"
)

const nBuckets = 10

type bucketList struct {
    b [nBuckets]int // bucket data specified by task

    // transfer counts for each updater, not strictly required by task but
    // useful to show that the two updaters get fair chances to run.
    tc [2]int

    sync.Mutex // synchronization
}

// Updater ids, to track number of transfers by updater.
// these can index bucketlist.tc for example.
const (
    idOrder = iota
    idChaos
)

const initialSum = 1000 // sum of all bucket values

// Constructor.
func newBucketList() *bucketList {
    var bl bucketList
    // Distribute initialSum across buckets.
    for i, dist := nBuckets, initialSum; i > 0; {
        v := dist / i
        i--
        bl.b[i] = v
        dist -= v
    }
    return &bl
}

// method 1 required by task, get current value of a bucket
func (bl *bucketList) bucketValue(b int) int {
    bl.Lock() // lock before accessing data
    r := bl.b[b]
    bl.Unlock()
    return r
}

// method 2 required by task
func (bl *bucketList) transfer(b1, b2, a int, ux int) {
    // Get access.
    bl.Lock()
    // Clamping maintains invariant that bucket values remain nonnegative.
    if a > bl.b[b1] {
        a = bl.b[b1]
    }
    // Transfer.
    bl.b[b1] -= a
    bl.b[b2] += a
    bl.tc[ux]++ // increment transfer count
    bl.Unlock()
}

// additional useful method
func (bl *bucketList) snapshot(s *[nBuckets]int, tc *[2]int) {
    bl.Lock()
    *s = bl.b
    *tc = bl.tc
    bl.tc = [2]int{} // clear transfer counts
    bl.Unlock()
}

var bl = newBucketList()

func main() {
    // Three concurrent tasks.
    go order() // make values closer to equal
    go chaos() // arbitrarily redistribute values
    buddha()   // display total value and individual values of each bucket
}

// The concurrent tasks exercise the data operations by calling bucketList
// methods.  The bucketList methods are "threadsafe", by which we really mean
// goroutine-safe.  The conconcurrent tasks then do no explicit synchronization
// and are not responsible for maintaining invariants.

// Exercise 1 required by task: make values more equal.
func order() {
    r := rand.New(rand.NewSource(time.Now().UnixNano()))
    for {
        b1 := r.Intn(nBuckets)
        b2 := r.Intn(nBuckets - 1)
        if b2 >= b1 {
            b2++
        }
        v1 := bl.bucketValue(b1)
        v2 := bl.bucketValue(b2)
        if v1 > v2 {
            bl.transfer(b1, b2, (v1-v2)/2, idOrder)
        } else {
            bl.transfer(b2, b1, (v2-v1)/2, idOrder)
        }
    }
}

// Exercise 2 required by task: redistribute values.
func chaos() {
    r := rand.New(rand.NewSource(time.Now().Unix()))
    for {
        b1 := r.Intn(nBuckets)
        b2 := r.Intn(nBuckets - 1)
        if b2 >= b1 {
            b2++
        }
        bl.transfer(b1, b2, r.Intn(bl.bucketValue(b1)+1), idChaos)
    }
}

// Exercise 3 requred by task: display total.
func buddha() {
    var s [nBuckets]int
    var tc [2]int
    var total, nTicks int

    fmt.Println("sum  ---updates---    mean  buckets")
    tr := time.Tick(time.Second / 10)
    for {
        <-tr
        bl.snapshot(&s, &tc)
        var sum int
        for _, l := range s {
            if l < 0 {
                panic("sob") // invariant not preserved
            }
            sum += l
        }
        // Output number of updates per tick and cummulative mean
        // updates per tick to demonstrate "as often as possible"
        // of task exercises 1 and 2.
        total += tc[0] + tc[1]
        nTicks++
        fmt.Printf("%d %6d %6d %7d  %3d\n", sum, tc[0], tc[1], total/nTicks, s)
        if sum != initialSum {
            panic("weep") // invariant not preserved
        }
    }
}


(open,closed,change,open?) := (true,false,not,test);
doors := bits(100,closed);
for i in 1..#doors repeat
  for j in i..#doors by i repeat
    doors.j := change doors.j
[i for i in 1..#doors | open? doors.i]


bool is_prime(int n) {
  var d = 5;
  if (n < 2) return false;
  if (n % 2 == 0) return n == 2;
  if (n % 3 == 0) return n == 3;
  while (d * d <= n) {
    if (n % d == 0) return false;
    d += 2;
    if (n % d == 0) return false;
    d += 4;
  }
  return true;
}

int count_prime_factors(int n) {
  var count = 0;
  var f = 2;
  if (n == 1) return 0;
  if (is_prime(n)) return 1;
  while (true) {
    if (n % f == 0) {
      count++;
      n /= f;
      if (n == 1) return count;
      if (is_prime(n)) f = n;
    } else if (f >= 3) {
      f += 2;
    } else {
      f = 3;
    }
  }
}

void main() {
  const int MAX = 120;
  var n = 0;
  var count = 0;
  stdout.printf(@"The attractive numbers up to and including $MAX are:\n");
  for (int i = 1; i <= MAX; i++) {
    n = count_prime_factors(i);
    if (is_prime(n)) {
      stdout.printf("%4d", i);
      count++;
      if (count % 20 == 0)
        stdout.printf("\n");
    }
  }
  stdout.printf("\n");
}


Option Explicit

Public Sub AttractiveNumbers()
Dim max As Integer, i As Integer, n As Integer

max = 120

For i = 1 To max
    n = CountPrimeFactors(i)
    If IsPrime(n) Then Debug.Print i
Next i

End Sub

Public Function IsPrime(ByVal n As Integer) As Boolean
Dim d As Integer

IsPrime = True
d = 5

If n < 2 Then
    IsPrime = False
    GoTo Finish
End If

If n Mod 2 = 0 Then
    IsPrime = (n = 2)
    GoTo Finish
End If

If n Mod 3 = 0 Then
    IsPrime = (n = 3)
    GoTo Finish
End If

While (d * d <= n)
    If (n Mod d = 0) Then IsPrime = False
    d = d + 2
    If (n Mod d = 0) Then IsPrime = False
    d = d + 4
Wend
Finish:
End Function

Public Function CountPrimeFactors(ByVal n As Integer) As Integer

Dim count As Integer, f As Integer

If n = 1 Then
    CountPrimeFactors = 0
    GoTo Finish2
End If

If (IsPrime(n)) Then
    CountPrimeFactors = 1
    GoTo Finish2
End If

count = 0
f = 2

Do While (True)
    If n Mod f = 0 Then
        count = count + 1
        n = n / f
        If n = 1 Then
            CountPrimeFactors = count
            Exit Do
        End If
        If IsPrime(n) Then f = n
    ElseIf f >= 3 Then
        f = f + 2
    Else
        f = 3
    End If
Loop

Finish2:
End Function


class Buckets {

    def cells = []
    final n

    Buckets(n, limit=1000, random=new Random()) {
        this.n = n
        (0..<n).each {
            cells << random.nextInt(limit)
        }
    }

    synchronized getAt(i) {
        cells[i]
    }

    synchronized transfer(from, to, amount) {
        assert from in (0..<n) && to in (0..<n)
        def cappedAmt = [cells[from], amount].min()
        cells[from] -= cappedAmt
        cells[to] += cappedAmt
    }

    synchronized String toString() { cells.toString() }
}

def random = new Random()

def buckets = new Buckets(5)

def makeCloser = { i, j ->
    synchronized(buckets) {
        def targetDiff = (buckets[i]-buckets[j]).intdiv(2)
        if (targetDiff < 0) {
            buckets.transfer(j, i, -targetDiff)
        } else {
            buckets.transfer(i, j, targetDiff)
        }
    }
}

def randomize = { i, j ->
    synchronized(buckets) {
        def targetLimit = buckets[i] + buckets[j]
        def targetI = random.nextInt(targetLimit + 1)
        if (targetI < buckets[i]) {
            buckets.transfer(i, j, buckets[i] - targetI)
        } else {
            buckets.transfer(j, i, targetI - buckets[i])
        }
    }
}

Thread.start {
    def start = System.currentTimeMillis()
    while (start + 10000 > System.currentTimeMillis()) {
        def i = random.nextInt(buckets.n)
        def j = random.nextInt(buckets.n)
        makeCloser(i, j)
    }
}

Thread.start {
    def start = System.currentTimeMillis()
    while (start + 10000 > System.currentTimeMillis()) {
        def i = random.nextInt(buckets.n)
        def j = random.nextInt(buckets.n)
        randomize(i, j)
    }
}

def start = System.currentTimeMillis()
while (start + 10000 > System.currentTimeMillis()) {
    synchronized(buckets) {
        def sum = buckets.cells.sum()
        println "${new Date()}: checksum: ${sum} buckets: ${buckets}"
    }
    Thread.sleep(500)
}


main()
{
  auto doors[100]; /* != 0 means open */
  auto pass, door;

  door = 0;
  while( door<100 ) doors[door++] = 0;

  pass = 0;
  while( pass<100 )
  {
    door = pass;
    while( door<100 )
    {
      doors[door] = !doors[door];
      door =+ pass+1;
    }
    ++pass;
  }

  door = 0;
  while( door<100 )
  {
    printf("door #%d is %s.*n", door+1, doors[door] ? "open" : "closed");
    ++door;
  }

  return(0);
}


Module Module1
    Const MAX = 120

    Function IsPrime(n As Integer) As Boolean
        If n < 2 Then Return False
        If n Mod 2 = 0 Then Return n = 2
        If n Mod 3 = 0 Then Return n = 3
        Dim d = 5
        While d * d <= n
            If n Mod d = 0 Then Return False
            d += 2
            If n Mod d = 0 Then Return False
            d += 4
        End While
        Return True
    End Function

    Function PrimefactorCount(n As Integer) As Integer
        If n = 1 Then Return 0
        If IsPrime(n) Then Return 1
        Dim count = 0
        Dim f = 2
        While True
            If n Mod f = 0 Then
                count += 1
                n /= f
                If n = 1 Then Return count
                If IsPrime(n) Then f = n
            ElseIf f >= 3 Then
                f += 2
            Else
                f = 3
            End If
        End While
        Throw New Exception("Unexpected")
    End Function

    Sub Main()
        Console.WriteLine("The attractive numbers up to and including {0} are:", MAX)
        Dim i = 1
        Dim count = 0
        While i <= MAX
            Dim n = PrimefactorCount(i)
            If IsPrime(n) Then
                Console.Write("{0,4}", i)
                count += 1
                If count Mod 20 = 0 Then
                    Console.WriteLine()
                End If
            End If
                i += 1
        End While
        Console.WriteLine()
    End Sub

End Module


fn is_prime(n int) bool {
    if n < 2 {
        return false
    }
    else if n%2 == 0 {
        return n == 2
    }
    else if n%3 == 0 {
        return n == 3
    }
    else {
        mut d := 5
        for  d*d <= n {
            if n%d == 0 {
                return false
            }
            d += 2
            if n%d == 0 {
                return false
            }
            d += 4
        }
        return true
    }
}

fn count_prime_factors(n int) int {
    mut nn := n
    if n == 1 {
        return 0
    }
    else if is_prime(nn) {
        return 1
    }
    else {
        mut count, mut f := 0, 2
        for {
            if nn%f == 0 {
                count++
                nn /= f
                if nn == 1{
                    return count
                }
                if is_prime(nn) {
                    f = nn
                }
            } else if f >= 3{
                f += 2
            } else {
                f = 3
            }
        }
        return count
    }
}

fn main() {
    max := 120
    println('The attractive numbers up to and including $max are:')
    mut count := 0
    for i in 1 .. max+1 {
        n := count_prime_factors(i)
        if is_prime(n) {
            print('${i:4}')
            count++
            if count%20 == 0 {
                println('')
            }
        }
    }
}


module AtomicUpdates (main) where

import Control.Concurrent (forkIO, threadDelay)
import Control.Concurrent.MVar (MVar, newMVar, readMVar, modifyMVar_)
import Control.Monad (forever, forM_)
import Data.IntMap (IntMap, (!), toAscList, fromList, adjust)
import System.Random (randomRIO)
import Text.Printf (printf)

-------------------------------------------------------------------------------

type Index = Int
type Value = Integer
data Buckets = Buckets Index (MVar (IntMap Value))

makeBuckets   :: Int -> IO Buckets
size          :: Buckets -> Index
currentValue  :: Buckets -> Index -> IO Value
currentValues :: Buckets          -> IO (IntMap Value)
transfer      :: Buckets -> Index -> Index -> Value -> IO ()

-------------------------------------------------------------------------------

makeBuckets n = do v <- newMVar (fromList [(i, 100) | i <- [1..n]])
                   return (Buckets n v)

size (Buckets n _) = n

currentValue (Buckets _ v) i = fmap (! i) (readMVar v)
currentValues (Buckets _ v) = readMVar v

transfer b@(Buckets n v) i j amt | amt < 0        = transfer b j i (-amt)
                                 | otherwise      = do
  modifyMVar_ v $ \map -> let amt' = min amt (map ! i)
                            in return $ adjust (subtract amt') i
                                      $ adjust (+        amt') j
                                      $ map

-------------------------------------------------------------------------------

roughen, smooth, display :: Buckets -> IO ()

pick buckets = randomRIO (1, size buckets)

roughen buckets = forever loop where
  loop = do i <- pick buckets
            j <- pick buckets
            iv <- currentValue buckets i
            transfer buckets i j (iv `div` 3)

smooth buckets = forever loop where
  loop = do i <- pick buckets
            j <- pick buckets
            iv <- currentValue buckets i
            jv <- currentValue buckets j
            transfer buckets i j ((iv - jv) `div` 4)

display buckets = forever loop where
  loop = do threadDelay 1000000
            bmap <- currentValues buckets
            putStrLn (report $ map snd $ toAscList bmap)
  report list = "\nTotal: " ++ show (sum list) ++ "\n" ++ bars
    where bars = concatMap row $ map (*40) $ reverse [1..5]
          row lim = printf "%3d " lim ++ [if x >= lim then '*' else ' ' | x <- list] ++ "\n"

main = do buckets <- makeBuckets 100
          forkIO (roughen buckets)
          forkIO (smooth buckets)
          display buckets


global mtx

procedure main(A)
    nBuckets := integer(A[1]) | 10
    nShows := integer(A[2]) | 4
    showBuckets := A[3]
    mtx := mutex()
    every !(buckets := list(nBuckets)) := ?100

    thread repeat {
        every (b1|b2) := ?nBuckets   # OK if same!
        critical mtx: xfer((buckets[b1] - buckets[b2])/2, b1, b2)
        }
    thread repeat {
        every (b1|b2) := ?nBuckets   # OK if same!
        critical mtx: xfer(integer(?buckets[b1]), b1, b2)
        }
    wait(thread repeat {
        delay(500)
        critical mtx: {
            every (sum := 0) +:= !buckets
            writes("Sum: ",sum)
            if \showBuckets then every writes(" -> "|right(!buckets, 4))
            }
        write()
        if (nShows -:= 1) <= 0 then break
        })
end

procedure xfer(x,b1,b2)
    buckets[b1] -:= x
    buckets[b2] +:= x
end


OPTION BASE 1

DECLARE doors[100]

FOR size = 1 TO 100
    FOR pass = 0 TO 100 STEP size
	doors[pass] = NOT(doors[pass])
    NEXT
NEXT

FOR which = 1 TO 100
    IF doors[which] THEN PRINT which
NEXT


import "/fmt" for Fmt
import "/math" for Int

var max = 120
System.print("The attractive numbers up to and including %(max) are:")
var count = 0
for (i in 1..max) {
    var n = Int.primeFactors(i).count
    if (Int.isPrime(n)) {
        System.write(Fmt.d(4, i))
        count = count + 1
        if (count%20 == 0) System.print()
    }
}
System.print()


func IsPrime(N);        \Return 'true' if N is prime
int  N, I;
[if N <= 2 then return N = 2;
if (N&1) = 0 then \even >2\ return false;
for I:= 3 to sqrt(N) do
    [if rem(N/I) = 0 then return false;
    I:= I+1;
    ];
return true;
];

func Factors(N);        \Return number of factors for N
int  N, Cnt, F;
[Cnt:= 0;
F:= 2;
repeat  if rem(N/F) = 0 then
                [Cnt:= Cnt+1;
                N:= N/F;
                ]
        else    F:= F+1;
until   F > N;
return Cnt;
];

int C, N;
[C:= 0;
for N:= 4 to 120 do
    if IsPrime(Factors(N)) then
        [IntOut(0, N);
        C:= C+1;
        if rem(C/10) then ChOut(0, 9\tab\) else CrLf(0);
        ];
]


var [const] BI=Import("zklBigNum");  // libGMP
fcn attractiveNumber(n){ BI(primeFactors(n).len()).probablyPrime() }

println("The attractive numbers up to and including 120 are:");
[1..120].filter(attractiveNumber)
   .apply("%4d".fmt).pump(Void,T(Void.Read,19,False),"println");


import java.util.Arrays;
import java.util.concurrent.ThreadLocalRandom;

public class AtomicUpdates {

    private static final int NUM_BUCKETS = 10;

    public static class Buckets {
        private final int[] data;

        public Buckets(int[] data) {
            this.data = data.clone();
        }

        public int getBucket(int index) {
            synchronized (data) {
                return data[index];
            }
        }

        public int transfer(int srcIndex, int dstIndex, int amount) {
            if (amount < 0)
                throw new IllegalArgumentException("negative amount: " + amount);
            if (amount == 0)
                return 0;

            synchronized (data) {
                if (data[srcIndex] - amount < 0)
                    amount = data[srcIndex];
                if (data[dstIndex] + amount < 0)
                    amount = Integer.MAX_VALUE - data[dstIndex];
                if (amount < 0)
                    throw new IllegalStateException();
                data[srcIndex] -= amount;
                data[dstIndex] += amount;
                return amount;
            }
        }

        public int[] getBuckets() {
            synchronized (data) {
                return data.clone();
            }
        }
    }

    private static long getTotal(int[] values) {
        long total = 0;
        for (int value : values) {
            total += value;
        }
        return total;
    }

    public static void main(String[] args) {
        ThreadLocalRandom rnd = ThreadLocalRandom.current();

        int[] values = new int[NUM_BUCKETS];
        for (int i = 0; i < values.length; i++)
            values[i] = rnd.nextInt() & Integer.MAX_VALUE;
        System.out.println("Initial Array: " + getTotal(values) + " " + Arrays.toString(values));

        Buckets buckets = new Buckets(values);
        new Thread(() -> equalize(buckets), "equalizer").start();
        new Thread(() -> transferRandomAmount(buckets), "transferrer").start();
        new Thread(() -> print(buckets), "printer").start();
    }

    private static void transferRandomAmount(Buckets buckets) {
        ThreadLocalRandom rnd = ThreadLocalRandom.current();
        while (true) {
            int srcIndex = rnd.nextInt(NUM_BUCKETS);
            int dstIndex = rnd.nextInt(NUM_BUCKETS);
            int amount = rnd.nextInt() & Integer.MAX_VALUE;
            buckets.transfer(srcIndex, dstIndex, amount);
        }
    }

    private static void equalize(Buckets buckets) {
        ThreadLocalRandom rnd = ThreadLocalRandom.current();
        while (true) {
            int srcIndex = rnd.nextInt(NUM_BUCKETS);
            int dstIndex = rnd.nextInt(NUM_BUCKETS);
            int amount = (buckets.getBucket(srcIndex) - buckets.getBucket(dstIndex)) / 2;
            if (amount >= 0)
                buckets.transfer(srcIndex, dstIndex, amount);
        }
    }

    private static void print(Buckets buckets) {
        while (true) {
            long nextPrintTime = System.currentTimeMillis() + 3000;
            long now;
            while ((now = System.currentTimeMillis()) < nextPrintTime) {
                try {
                    Thread.sleep(nextPrintTime - now);
                } catch (InterruptedException e) {
                    return;
                }
            }

            int[] bucketValues = buckets.getBuckets();
            System.out.println("Current values: " + getTotal(bucketValues) + " " + Arrays.toString(bucketValues));
        }
    }
}


 100 :
 110  REM  100 DOORS PROBLEM
 120 :
 130  DIM D(100)
 140  FOR P = 1 TO 100
 150  FOR T = P TO 100 STEP P
 160  D(T) =  NOT D(T): NEXT T
 170  NEXT P
 180  FOR I = 1 TO 100
 190  IF D(I) THEN  PRINT I;" ";
 200  NEXT I


using StatsBase

function runall()
    nbuckets = 16
    unfinish = true
    spinner = ReentrantLock()
    buckets = rand(1:99, nbuckets)
    totaltrans = 0

    bucketsum() = sum(buckets)
    smallpause() = sleep(rand() / 2000)
    picktwo() = (samplepair(nbuckets)...)
    function equalizer()
        while unfinish
            smallpause()
            if trylock(spinner)
                i, j = picktwo()
                sm = buckets[i] + buckets[j]
                m = fld(sm + 1, 2)
                buckets[i], buckets[j] = m, sm - m
                totaltrans += 1
                unlock(spinner)
            end
        end
    end
    function redistributor()
        while unfinish
            smallpause()
            if trylock(spinner)
                i, j = picktwo()
                sm = buckets[i] + buckets[j]
                buckets[i] = rand(0:sm)
                buckets[j] = sm - buckets[i]
                totaltrans += 1
                unlock(spinner)
            end
        end
    end
    function accountant()
        count = 0
        while count < 16
            smallpause()
            if trylock(spinner)
                println("Current state of buckets: $buckets. Total in buckets: $(bucketsum())")
                unlock(spinner)
                count += 1
                sleep(1)
            end
        end
        unfinish = false
    end
    t = time()
    @async equalizer()
    @async redistributor()
    @async accountant()
    while unfinish sleep(0.25) end
    println("Total transactions: $totaltrans ($(round(Int, totaltrans / (time() - t))) unlocks per second).")
end

runall()


// version 1.2.0

import java.util.concurrent.ThreadLocalRandom
import kotlin.concurrent.thread

const val NUM_BUCKETS = 10

class Buckets(data: IntArray) {
    private val data = data.copyOf()

    operator fun get(index: Int) = synchronized(data) { data[index] }

    fun transfer(srcIndex: Int, dstIndex: Int, amount: Int): Int {
        if (amount < 0) {
            throw IllegalArgumentException("Negative amount: $amount")
        }
        if (amount == 0) return 0
        synchronized(data) {
            var a = amount
            if (data[srcIndex] - a < 0) a = data[srcIndex]
            if (data[dstIndex] + a < 0) a = Int.MAX_VALUE - data[dstIndex]
            if (a < 0) throw IllegalStateException()
            data[srcIndex] -= a
            data[dstIndex] += a
            return a
        }
    }

    val buckets get() = synchronized(data) { data.copyOf() }

    fun transferRandomAmount() {
        val rnd = ThreadLocalRandom.current()
        while (true) {
            val srcIndex = rnd.nextInt(NUM_BUCKETS)
            val dstIndex = rnd.nextInt(NUM_BUCKETS)
            val amount = rnd.nextInt() and Int.MAX_VALUE
            transfer(srcIndex, dstIndex, amount)
        }
    }

    fun equalize() {
        val rnd = ThreadLocalRandom.current()
        while (true) {
            val srcIndex = rnd.nextInt(NUM_BUCKETS)
            val dstIndex = rnd.nextInt(NUM_BUCKETS)
            val amount = (this[srcIndex] - this[dstIndex]) / 2
            if (amount >= 0) transfer(srcIndex, dstIndex, amount)
        }
    }

    fun print() {
        while (true) {
            val nextPrintTime = System.currentTimeMillis() + 3000
            while (true) {
                val now = System.currentTimeMillis()
                if (now >= nextPrintTime) break
                try {
                    Thread.sleep(nextPrintTime - now)
                }
                catch (e: InterruptedException) {
                    return
                }
            }
            val bucketValues = buckets
            println("Current values: ${bucketValues.total} ${bucketValues.asList()}")
        }
    }
}

val IntArray.total: Long get() {
    var sum = 0L
    for (d in this) sum += d
    return sum
}

fun main(args: Array<String>) {
    val rnd = ThreadLocalRandom.current()
    val values = IntArray(NUM_BUCKETS) { rnd.nextInt() and Int.MAX_VALUE }
    println("Initial array:  ${values.total} ${values.asList()}")
    val buckets = Buckets(values)
    thread(name = "equalizer")   { buckets.equalize() }
    thread(name = "transferrer") { buckets.transferRandomAmount() }
    thread(name = "printer")     { buckets.print() }
}


@echo off
setlocal enableDelayedExpansion
:: 0 = closed
:: 1 = open
:: SET /A treats undefined variable as 0
:: Negation operator ! must be escaped because delayed expansion is enabled
for /l %%p in (1 1 100) do for /l %%d in (%%p %%p 100) do set /a "door%%d=^!door%%d"
for /l %%d in (1 1 100) do if !door%%d!==1 (
  echo door %%d is open
) else echo door %%d is closed


define atomic => thread {
    data
        private buckets = staticarray_join(10, void),
        private lock = 0

    public onCreate => {
        loop(.buckets->size) => {
            .`buckets`->get(loop_count) = math_random(0, 1000)
        }
    }

    public buckets => .`buckets`

    public bucket(index::integer) => .`buckets`->get(#index)

    public transfer(source::integer, dest::integer, amount::integer) => {
        #source == #dest
            ? return

        #amount = math_min(#amount, .`buckets`->get(#source))
        .`buckets`->get(#source) -= #amount
        .`buckets`->get(#dest)   += #amount
    }

    public numBuckets => .`buckets`->size

    public lock => {
        .`lock` == 1
            ? return false

        .`lock` = 1
        return true
    }
    public unlock => {
        .`lock` = 0
    }
}

local(initial_total) = (with b in atomic->buckets sum #b)
local(total) = #initial_total

// Make 2 buckets close to equal
local(_) = split_thread => {
    local(bucket1) = math_random(1, atomic->numBuckets)
    local(bucket2) = math_random(1, atomic->numBuckets)
    local(value1)  = atomic->bucket(#bucket1)
    local(value2)  = atomic->bucket(#bucket2)

    if(#value1 >= #value2) => {
        atomic->transfer(#bucket1, #bucket2, (#value1 - #value2) / 2)
    else
        atomic->transfer(#bucket2, #bucket1, (#value2 - #value1) / 2)
    }

    currentCapture->restart
}

// Randomly distribute 2 buckets
local(_) = split_thread => {
    local(bucket1) = math_random(1, atomic->numBuckets)
    local(bucket2) = math_random(1, atomic->numBuckets)
    local(value1)  = atomic->bucket(#bucket1)

    atomic->transfer(#bucket1, #bucket2, math_random(1, #value1))

    currentCapture->restart
}

local(buckets)
while(#initial_total == #total) => {
    sleep(2000)
    #buckets = atomic->buckets
    #total   = with b in #buckets sum #b
    stdoutnl(#buckets->asString + " -- total: " + #total)
}
stdoutnl(`ERROR: totals no longer match: ` + #initial_total + ', ' + #total)


:- object(buckets).

    :- threaded.

    :- public([start/0, start/4]).

    % bucket representation
    :- private(bucket_/2).
    :- dynamic(bucket_/2).

    % use the same mutex for all the predicates that access the buckets
    :- private([bucket/2, buckets/1, transfer/3]).
    :- synchronized([bucket/2, buckets/1, transfer/3]).

    start :-
        % by default, create ten buckets with initial random integer values
        % in the interval [0, 10[ and print their contents ten times
        start(10, 0, 10, 10).

    start(N, Min, Max, Samples) :-
        % create the buckets with random values in the
        % interval [Min, Max[ and return their sum
        create_buckets(N, Min, Max, Sum),
        write('Sum of all bucket values: '), write(Sum), nl, nl,
        % use competitive or-parallelism for the three loops such that
        % the computations terminate when the display loop terminates
        threaded((
                display_loop(Samples)
            ;   match_loop(N)
            ;   redistribute_loop(N)
        )).

    create_buckets(N, Min, Max, Sum) :-
        % remove all exisiting buckets
        retractall(bucket_(_,_)),
        % create the new buckets
        create_buckets(N, Min, Max, 0, Sum).

    create_buckets(0, _, _, Sum, Sum) :-
        !.
    create_buckets(N, Min, Max, Sum0, Sum) :-
        random::random(Min, Max, Value),
        asserta(bucket_(N,Value)),
        M is N - 1,
        Sum1 is Sum0 + Value,
        create_buckets(M, Min, Max, Sum1, Sum).

    bucket(Bucket, Value) :-
        bucket_(Bucket, Value).

    buckets(Values) :-
        findall(Value, bucket_(_, Value), Values).

    transfer(Origin, _, Origin) :-
        !.
    transfer(Origin, Delta, Destin) :-
        retract(bucket_(Origin, OriginValue)),
        retract(bucket_(Destin, DestinValue)),
        % the buckets may have changed between the access to its
        % values and the calling of this transfer predicate; thus,
        % we must ensure that we're transfering a legal amount
        Amount is min(Delta, OriginValue),
        NewOriginValue is OriginValue - Amount,
        NewDestinValue is DestinValue + Amount,
        assertz(bucket_(Origin, NewOriginValue)),
        assertz(bucket_(Destin, NewDestinValue)).

    match_loop(N) :-
        % randomly select two buckets
        M is N + 1,
        random::random(1, M, Bucket1),
        random::random(1, M, Bucket2),
        % access their contents
        bucket(Bucket1, Value1),
        bucket(Bucket2, Value2),
        % make their new values approximately equal
        Delta is truncate(abs(Value1 - Value2)/2),
        (   Value1 > Value2 ->
            transfer(Bucket1, Delta, Bucket2)
        ;   Value1 < Value2 ->
            transfer(Bucket2, Delta, Bucket1)
        ;   true
        ),
        match_loop(N).

    redistribute_loop(N) :-
        % randomly select two buckets
        M is N + 1,
        random::random(1, M, FromBucket),
        random::random(1, M, ToBucket),
        % access bucket from where we transfer
        bucket(FromBucket, Current),
        Limit is Current + 1,
        random::random(0, Limit, Delta),
        transfer(FromBucket, Delta, ToBucket),
        redistribute_loop(N).

    display_loop(0) :-
        !.
    display_loop(N) :-
        buckets(Values),
        write(Values), nl,
        thread_sleep(2),
        M is N - 1,
        display_loop(M).

:- end_object.


DIM doors%(100)
FOR pass% = 1 TO 100
    FOR door% = pass% TO 100 STEP pass%
        doors%(door%) = NOT doors%(door%)
    NEXT door%
NEXT pass%
FOR door% = 1 TO 100
    IF doors%(door%) PRINT "Door " ; door% " is open"
NEXT door%


transfer[bucks_, src_, dest_, n_] :=
  ReplacePart[
   bucks, {src -> Max[bucks[[src]] - n, 0],
    dest -> bucks[[dest]] + Min[bucks[[src]], n]}];
DistributeDefinitions[transfer];
SetSharedVariable[bucks, comp];
bucks = RandomInteger[10, 20];
comp = True;
Print["Original sum: " <> IntegerString[Plus @@ bucks]];
Print[Dynamic["Current sum: " <> IntegerString[Plus @@ bucks]]];
WaitAll[{ParallelSubmit[
    While[True, While[! comp, Null]; comp = False;
     Module[{a = RandomInteger[{1, 20}], b = RandomInteger[{1, 20}]},
      bucks = transfer[bucks, Max[a, b], Min[a, b],
        Floor[Abs[bucks[[a]] - bucks[[b]]]/2]]]; comp = True]],
   ParallelSubmit[
    While[True, While[! comp, Null]; comp = False;
     Module[{src = RandomInteger[{1, 20}],
       dest = RandomInteger[{1, 20}]},
      bucks = transfer[bucks, src, dest,
        RandomInteger[{1, bucks[[src]]}]]]; comp = True]]}];


import locks
import math
import os
import random

const N = 10          # Number of buckets.
const MaxInit = 99    # Maximum initial value for buckets.

var buckets: array[1..N, Natural]       # Array of buckets.
var bucketLocks: array[1..N, Lock]      # Array of bucket locks.
var randomLock: Lock                    # Lock to protect the random number generator.
var terminate: array[3, Channel[bool]]  # Used to ask threads to terminate.

#---------------------------------------------------------------------------------------------------

proc getTwoIndexes(): tuple[a, b: int] =
  ## Get two indexes from the random number generator.

  result.a = rand(1..N)
  result.b = rand(2..N)
  if result.b == result.a: result.b = 1

#---------------------------------------------------------------------------------------------------

proc equalize(num: int) {.thread.} =
  ## Try to equalize two buckets.

  var b1, b2: int         # Bucket indexes.

  while true:

    # Select the two buckets to "equalize".
    withLock randomLock:
     (b1, b2) = getTwoIndexes()
    if b1 > b2: swap b1, b2       # We want "b1 < b2" to avoid deadlocks.

    # Perform equalization.
    withLock bucketLocks[b1]:
      withLock bucketLocks[b2]:
        let target = (buckets[b1] + buckets[b2]) div 2
        let delta = target - buckets[b1]
        inc buckets[b1], delta
        dec buckets[b2], delta

    # Check termination.
    let (available, stop) = tryRecv terminate[num]
    if available and stop: break

#---------------------------------------------------------------------------------------------------

proc distribute(num: int) {.thread.} =
  ## Redistribute contents of two buckets.

  var b1, b2: int         # Bucket indexes.
  var factor: float       # Ratio used to compute the new value for "b1".

  while true:

    # Select the two buckets for redistribution and the redistribution factor.
    withLock randomLock:
      (b1, b2) = getTwoIndexes()
      factor = rand(0.0..1.0)
    if b1 > b2: swap b1, b2       # We want "b1 < b2" to avoid deadlocks..

    # Perform redistribution.
    withLock bucketLocks[b1]:
      withLock bucketLocks[b2]:
        let sum = buckets[b1] + buckets[b2]
        let value = (sum.toFloat * factor).toInt
        buckets[b1] = value
        buckets[b2] = sum - value

    # Check termination.
    let (available, stop) = tryRecv terminate[num]
    if available and stop: break

#---------------------------------------------------------------------------------------------------

proc display(num: int) {.thread.} =
  ## Display the content of buckets and the sum (which should be constant).

  while true:
    for i in 1..N: acquire bucketLocks[i]
    echo buckets, "   Total = ", sum(buckets)
    for i in countdown(N, 1): release bucketLocks[i]
    os.sleep(1000)

    # Check termination.
    let (available, stop) = tryRecv terminate[num]
    if available and stop: break

#———————————————————————————————————————————————————————————————————————————————————————————————————

randomize()

# Initialize the buckets with a random value.
for bucket in buckets.mitems:
  bucket = rand(1..MaxInit)

# Initialize the locks.
randomLock.initLock()
for lock in bucketLocks.mitems:
  lock.initLock()

# Open the channels.
for c in terminate.mitems:
  c.open()

# Create and launch the threads.
var tequal, tdist, tdisp: Thread[int]
tequal.createThread(equalize, 0)
tdist.createThread(distribute, 1)
tdisp.createThread(display, 2)

sleep(10000)

# Ask the threads to stop.
for c in terminate.mitems:
  c.send(true)

joinThreads([tequal, tdist, tdisp])

# Free resources.
randomLock.deinitLock()
for lock in bucketLocks.mitems:
  lock.deinitLock()
for c in terminate.mitems:
  c.close()


declare
  %%
  %% INIT
  %%
  NBuckets = 100
  StartVal = 50
  ExpectedSum = NBuckets * StartVal

  %% Makes a tuple and calls Fun for every field
  fun {Make Label N Fun}
     R = {Tuple.make Label N}
  in
     for I in 1..N do R.I = {Fun} end
     R
  end

  Buckets = {Make buckets NBuckets fun {$} {Cell.new StartVal} end}
  Locks = {Make locks NBuckets Lock.new}
  LockList = {Record.toList Locks}

  %%
  %% DISPLAY
  %%
  proc {Display}
     Snapshot = {WithLocks LockList
                 fun {$}
                    {Record.map Buckets Cell.access}
                 end
                }
     Sum = {Record.foldL Snapshot Number.'+' 0}
  in
     {Print Snapshot}
     {System.showInfo "  sum: "#Sum}
     Sum = ExpectedSum %% assert
  end

  %% Calls Fun with multiple locks locked and returns the result of Fun.
  fun {WithLocks Ls Fun}
     case Ls of L|Lr then
        lock L then
           {WithLocks Lr Fun}
        end
     [] nil then {Fun}
     end
  end

  %%
  %% MANIPULATE
  %%
  proc {Smooth I J}
     Diff = @(Buckets.I) - @(Buckets.J) %% reading without lock: by design
     Amount = Diff div 4
  in
     {Transfer I J Amount}
  end

  proc {Roughen I J}
     Amount = @(Buckets.I) div 3 %% reading without lock: by design
  in
     {Transfer I J Amount}
  end

  %% Atomically transfer an amount from From to To.
  %% Negative amounts are allowed;
  %% will never make a bucket negative.
  proc {Transfer From To Amount}
     if From \= To then
        %% lock in order (to avoid deadlocks)
        Smaller = {Min From To}
        Bigger = {Max From To}
     in
        lock Locks.Smaller then
           lock Locks.Bigger then
              FromBucket = Buckets.From
              ToBucket = Buckets.To
              NewFromValue = @FromBucket - Amount
              NewToValue = @ToBucket + Amount
           in
              if NewFromValue >= 0 andthen NewToValue >= 0 then
                 FromBucket := NewFromValue
                 ToBucket := NewToValue
              end
           end
        end
     end
   end

  %% Returns a random bucket index.
  fun {Pick}
     {OS.rand} mod NBuckets + 1
  end
in
  %%
  %% START
  %%
  thread for do {Smooth {Pick} {Pick}} end end
  thread for do {Roughen {Pick} {Pick}} end end
  for do {Display} {Time.delay 50} end


/* 0 means door is closed, 1 means door is open */
for (i = 0; i < 100; i++) {
    for (j = i; j < 100; j += (i + 1)) {
        d[j] = 1 - d[j]     /* Toggle door */
    }
}

"Open doors:
"
for (i = 0; i < 100; i++) {
    if (d[i] == 1) (i + 1)
}


use strict;
use 5.10.0;

use threads 'yield';
use threads::shared;

my @a :shared = (100) x 10;
my $stop :shared = 0;

sub pick2 {
	my $i = int(rand(10));
	my $j;
	$j = int(rand(10)) until $j != $i;
	($i, $j)
}

sub even {
	lock @a;
	my ($i, $j) = pick2;
	my $sum = $a[$i] + $a[$j];
	$a[$i] = int($sum / 2);
	$a[$j] = $sum - $a[$i];
}

sub rand_move {
	lock @a;
	my ($i, $j) = pick2;

	my $x = int(rand $a[$i]);
	$a[$i] -= $x;
	$a[$j] += $x;
}

sub show {
	lock @a;
	my $sum = 0;
	$sum += $_ for (@a);
	printf "%4d", $_ for @a;
	print " total $sum\n";
}

my $t1 = async { even		until $stop }
my $t2 = async { rand_move	until $stop }
my $t3 = async {
	for (1 .. 10) {
		show;
		sleep(1);
	}
	$stop = 1;
};

$t1->join; $t2->join; $t3->join;


get "libhdr"

let start() be
$(  let doors = vec 100

    // close all doors
    for n = 1 to 100 do doors!n := 0

    // make 100 passes
    for pass = 1 to 100 do
    $(  let n = pass
        while n <= 100 do
        $(  doors!n := ~doors!n
            n := n + pass
        $)
    $)

    // report which doors are open
    for n = 1 to 100 do
        if doors!n then
            writef("Door %N is open.*N", n)
$)


without js    -- (no threads or critical sections in JavaScript)
constant nBuckets = 20
sequence buckets = tagset(nBuckets)     -- {1,2,3,..,20}
constant bucket_cs = init_cs()          -- critical section
atom equals = 0, rands = 0              -- operation counts
integer terminate = 0                   -- control flag

procedure mythreads(integer eq)
-- if eq then equalise else randomise
integer b1,b2,amt
    while not terminate do
        b1 = rand(nBuckets)
        b2 = rand(nBuckets)
        if b1!=b2 then                  -- (test not actually needed)
            enter_cs(bucket_cs)
            if eq then
                amt = floor((buckets[b1]-buckets[b2])/2)
                equals += 1
            else
                amt = rand(buckets[b1]+1)-1
                rands += 1
            end if
            buckets[b1] -= amt
            buckets[b2] += amt
            leave_cs(bucket_cs)
        end if
    end while
    exit_thread(0)
end procedure

procedure display()
    enter_cs(bucket_cs)
    ?{sum(buckets),equals,rands,buckets}
    leave_cs(bucket_cs)
end procedure

display()

constant threads = {create_thread(routine_id("mythreads"),{1}), -- equalise
                    create_thread(routine_id("mythreads"),{0})} -- randomise

constant ESC = #1B
while not find(get_key(),{ESC,'q','Q'}) do
    sleep(1)
    display()
end while
terminate = 1
wait_thread(threads)
delete_cs(bucket_cs)


(seed (in "/dev/urandom" (rd 8)))

(de *Buckets . 15)   # Number of buckets

# E/R model
(class +Bucket +Entity)
(rel key (+Key +Number))   # Key  1 .. *Buckets
(rel val (+Number))        # Value 1 .. 999

# Create new DB file
(pool (tmp "buckets.db"))

# Create *Buckets buckets with values between 1 and 999
(for K *Buckets
   (new T '(+Bucket)  'key K  'val (rand 1 999)) )
(commit)

# Pick a random bucket
(de pickBucket ()
   (db 'key '+Bucket (rand 1 *Buckets)) )

# First process
(unless (fork)
   (seed *Pid)                                  # Ensure local random sequence
   (loop
      (let (B1 (pickBucket)  B2 (pickBucket))   # Pick two buckets 'B1' and 'B2'
         (dbSync)                               # Atomic DB operation
         (let (V1 (; B1 val)  V2 (; B2 val))    # Get current values
            (cond
               ((> V1 V2)
                  (dec> B1 'val)                # Make them closer to equal
                  (inc> B2 'val) )
               ((> V2 V1)
                  (dec> B2 'val)
                  (inc> B1 'val) ) ) )
         (commit 'upd)                          # Close transaction
         (wait 1) ) ) )

# Second process
(unless (fork)
   (seed *Pid)                                  # Ensure local random sequence
   (loop
      (let (B1 (pickBucket)  B2 (pickBucket))   # Pick two buckets 'B1' and 'B2'
         (unless (== B1 B2)                     # Found two different ones?
            (dbSync)                            # Atomic DB operation
            (let (V1 (; B1 val)  V2 (; B2 val)) # Get current values
               (cond
                  ((> V1 V2 0)
                     (inc> B1 'val)             # Redistribute them
                     (dec> B2 'val) )
                  ((> V2 V1 0)
                     (inc> B2 'val)
                     (dec> B1 'val) ) ) )
            (commit 'upd)                       # Close transaction
            (wait 1) ) ) ) )

# Third process
(unless (fork)
   (loop
      (let Lst (collect 'key '+Bucket)          # Get all buckets
         (for This Lst                          # Print current values
            (printsp (: val)) )
         (prinl                                 # and total sum
            "-- Total: "
            (sum '((This) (: val)) Lst) ) )
      (wait 2000) ) )                           # Sleep two seconds

(wait)


#Buckets=9
#TotalAmount=200
Global Dim Buckets(#Buckets)
Global BMutex=CreateMutex()
Global Quit=#False

Procedure max(x,y)
  If x>=y:  ProcedureReturn x
  Else:     ProcedureReturn y
  EndIf
EndProcedure

Procedure Move(WantedAmount, From, Dest)
  Protected RealAmount
  If from<>Dest
    LockMutex(BMutex)
    RealAmount=max(0, Buckets(from)-WantedAmount)
    Buckets(From)-RealAmount
    Buckets(Dest)+RealAmount
    UnlockMutex(BMutex)
  EndIf
  ProcedureReturn RealAmount
EndProcedure

Procedure Level(A,B)
  Protected i, j, t
  If A<>B
    LockMutex(BMutex)
    t=Buckets(A)+Buckets(B)
    i=t/2: j=t-i
    Buckets(A)=i
    Buckets(B)=j
    UnlockMutex(BMutex)
  EndIf
EndProcedure

Procedure DoInvent(Array A(1))
  Protected i, sum
  LockMutex(BMutex)
  For i=0 To ArraySize(Buckets())
    A(i)=Buckets(i)
    sum+A(i)
  Next i
  UnlockMutex(BMutex)
  ProcedureReturn sum
EndProcedure

Procedure MixingThread(arg)
  Repeat
    Move(Random(#TotalAmount),Random(#Buckets),Random(#Buckets))
  Until Quit
EndProcedure

Procedure LevelingThread(arg)
  Repeat
    Level(Random(#Buckets),Random(#Buckets))
  Until Quit
EndProcedure

If OpenWindow(0,0,0,100,150,"Atomic updates",#PB_Window_SystemMenu)
  Define Thread1=CreateThread(@MixingThread(),0)
  Define Thread2=CreateThread(@MixingThread(),0)
  Define i, Event
  Dim Inventory(#Buckets)
  ; Set up a small GUI
  For i=0 To 9
    TextGadget(i, 0,i*15,50, 15,"Bucket #"+Str(i))
  Next i
  TextGadget(10,55,135,40,15,"=")
  AddWindowTimer(0,0,500)
  Buckets(0)=#TotalAmount
  Repeat
    Event=WaitWindowEvent()
    If Event=#PB_Event_Timer
      i=DoInvent(Inventory())
      SetGadgetText(10,"="+Str(i))
      For i=0 To #Buckets
        SetGadgetText(i, Str(Inventory(i)))
      Next i
    EndIf
  Until Event=#PB_Event_CloseWindow
  Quit=#True  ; Tell threads to shut down
  WaitThread(Thread1): WaitThread(Thread2)
EndIf


var doors = [false] * 100
for i in 0..100 {
  iter var j = i; j < 100; j += i + 1 {
    doors[j] = !doors[j]
  }
  var state = doors[i] ? 'open' : 'closed'
  echo 'Door ${i + 1} is ${state}'
}


from __future__ import with_statement # required for Python 2.5
import threading
import random
import time

terminate = threading.Event()

class Buckets:
    def __init__(self, nbuckets):
        self.nbuckets = nbuckets
        self.values = [random.randrange(10) for i in range(nbuckets)]
        self.lock = threading.Lock()

    def __getitem__(self, i):
        return self.values[i]

    def transfer(self, src, dst, amount):
        with self.lock:
            amount = min(amount, self.values[src])
            self.values[src] -= amount
            self.values[dst] += amount

    def snapshot(self):
        # copy of the current state (synchronized)
        with self.lock:
            return self.values[:]

def randomize(buckets):
    nbuckets = buckets.nbuckets
    while not terminate.isSet():
        src = random.randrange(nbuckets)
        dst = random.randrange(nbuckets)
        if dst!=src:
            amount = random.randrange(20)
            buckets.transfer(src, dst, amount)

def equalize(buckets):
    nbuckets = buckets.nbuckets
    while not terminate.isSet():
        src = random.randrange(nbuckets)
        dst = random.randrange(nbuckets)
        if dst!=src:
            amount = (buckets[src] - buckets[dst]) // 2
            if amount>=0: buckets.transfer(src, dst, amount)
            else: buckets.transfer(dst, src, -amount)

def print_state(buckets):
    snapshot = buckets.snapshot()
    for value in snapshot:
        print '%2d' % value,
    print '=', sum(snapshot)

# create 15 buckets
buckets = Buckets(15)

# the randomize thread
t1 = threading.Thread(target=randomize, args=[buckets])
t1.start()

# the equalize thread
t2 = threading.Thread(target=equalize, args=[buckets])
t2.start()

# main thread, display
try:
    while True:
        print_state(buckets)
        time.sleep(1)
except KeyboardInterrupt: # ^C to finish
    terminate.set()

# wait until all worker threads finish
t1.join()
t2.join()


Graphics 640,480
i=1
While ((i*i)<=100)
	a$=i*i
	DrawText a$,10,20*i
	Print i*i
	i=i+1
Wend
Flip
WaitKey


#lang racket

(struct bucket (value [lock #:auto])
  #:auto-value #f
  #:mutable
  #:transparent)

(define *buckets* (build-vector 10 (λ (i) (bucket 100))))

(define (show-buckets)
  (let* ([values (for/list ([b *buckets*]) (bucket-value b))]
         [total (apply + values)])
    (append values (list '- total))))

(define *equalizations* 0)
(define *randomizations* 0)
(define *blocks* 0)

(define (show-stats)
  (let ([n (length *log*)]
        [log (reverse *log*)])
    (printf "Equalizations ~a, Randomizations ~a, Transfers: ~a, Blocks ~a\n"
              *equalizations* *randomizations* n *blocks*)
    (for ([i (in-range 10)])
      (define j (min (floor (* i (/ n 9))) (sub1 n)))
      (printf "~a (~a). " (add1 i) (add1 j))
      (displayln (list-ref log j)))))

(define *log* (list (show-buckets)))

(define-syntax-rule (inc! x) (set! x (add1 x)))

(define (get-bucket i) (vector-ref *buckets* i))

(define (get-value i) (bucket-value (get-bucket i)))
(define (set-value! i v) (set-bucket-value! (get-bucket i) v))

(define (locked? i) (bucket-lock (vector-ref *buckets* i)))
(define (lock! i v) (set-bucket-lock! (get-bucket i) v))
(define (unlock! i) (lock! i #f))

(define *clamp-lock* #f)

(define (clamp i j)
  (cond [*clamp-lock* (inc! *blocks*)
                      #f]
        [else (set! *clamp-lock* #t)
              (let ([result #f]
                    [g (gensym)])
                (unless (locked? i)
                  (lock! i g)
                  (cond [(locked? j) (unlock! i)]
                        [else (lock! j g)
                              (set! result #t)]))
                (unless result (inc! *blocks*))
                (set! *clamp-lock* #f)
                result)]))

(define (unclamp i j)
  (unlock! i)
  (unlock! j))

(define (transfer i j amount)
  (let* ([lock1 (locked? i)]
         [lock2 (locked? j)]
         [a (get-value i)]
         [b (get-value j)]
         [c (- a amount)]
         [d (+ b amount)])
    (cond [(< c 0) (error 'transfer "Removing too much.")]
          [(< d 0) (error 'transfer "Stealing too much.")]
          [(and lock1 (equal? lock1 lock2)) (set-value! i c)
                                            (set-value! j d)
                                            (set! *log*
                                                  (cons (show-buckets) *log*))]
          [else (error 'transfer "Lock problem")])))

(define (equalize i j)
  (when (clamp i j)
    (let ([a (get-value i)]
          [b (get-value j)])
      (unless (= a b)
        (transfer i j (if (> a b)
                          (floor (/ (- a b) 2))
                          (- (floor (/ (- b a) 2)))))
        (inc! *equalizations*)))
        (unclamp i j)))

(define (randomize i j)
  (when (clamp i j)
    (let* ([a (get-value i)]
           [b (get-value j)]
           [t (+ a b)]
           [r (if (= t 0) 0 (random t))])
      (unless (= r 0)
        (transfer i j (- a r))
        (inc! *randomizations*)))
    (unclamp i j)))

(thread (λ () (for ([_ (in-range 500000)]) (equalize (random 10) (random 10)))))
(thread (λ () (for ([_ (in-range 500000)]) (randomize (random 10) (random 10)))))


#| A collection of non-negative integers, with atomic operations.
class BucketStore {

  has $.elems is required;
  has @!buckets = ^1024 .pick xx $!elems;
  has $lock     = Lock.new;

  #| Returns an array with the contents of all buckets.
  method buckets {
    $lock.protect: { [@!buckets] }
  }

  #| Transfers $amount from bucket at index $from, to bucket at index $to.
  method transfer ($amount, :$from!, :$to!) {
    return if $from == $to;

    $lock.protect: {
      my $clamped = $amount min @!buckets[$from];

      @!buckets[$from] -= $clamped;
      @!buckets[$to]   += $clamped;
    }
  }
}

# Create bucket store
my $bucket-store = BucketStore.new: elems => 8;
my $initial-sum = $bucket-store.buckets.sum;

# Start a thread to equalize buckets
Thread.start: {
  loop {
    my @buckets = $bucket-store.buckets;

    # Pick 2 buckets, so that $to has not more than $from
    my ($to, $from) = @buckets.keys.pick(2).sort({ @buckets[$_] });

    # Transfer half of the difference, rounded down
    $bucket-store.transfer: ([-] @buckets[$from, $to]) div 2, :$from, :$to;
  }
}

# Start a thread to distribute values among buckets
Thread.start: {
  loop {
    my @buckets = $bucket-store.buckets;

    # Pick 2 buckets
    my ($to, $from) = @buckets.keys.pick(2);

    # Transfer a random portion
    $bucket-store.transfer: ^@buckets[$from] .pick, :$from, :$to;
  }
}

# Loop to display buckets
loop {
  sleep 1;

  my @buckets = $bucket-store.buckets;
  my $sum = @buckets.sum;

  say "{@buckets.fmt: '%4d'}, total $sum";

  if $sum != $initial-sum {
    note "ERROR: Total changed from $initial-sum to $sum";
    exit 1;
  }
}


DEFINE PROCEDURE ''DIVIDE'' [A,B]:
BLOCK 0: BEGIN
  IF A < B, THEN:
    QUIT BLOCK 0;
  CELL(0) <= 1;
  OUTPUT <= 1;
  LOOP AT MOST A TIMES:
  BLOCK 2: BEGIN
    IF OUTPUT * B = A, THEN:
    QUIT BLOCK 0;
    OUTPUT <= OUTPUT + 1;
    IF OUTPUT * B > A, THEN:
    BLOCK 3: BEGIN
      OUTPUT <= CELL(0);
      QUIT BLOCK 0;
    BLOCK 3: END;
    CELL(0) <= OUTPUT;
  BLOCK 2: END;
BLOCK 0: END.

DEFINE PROCEDURE ''MINUS'' [A,B]:
BLOCK 0: BEGIN
  IF A < B, THEN:
    QUIT BLOCK 0;
  LOOP AT MOST A TIMES:
  BLOCK 1: BEGIN
    IF OUTPUT + B = A, THEN:
      QUIT BLOCK 0;
    OUTPUT <= OUTPUT + 1;
  BLOCK 1: END;
BLOCK 0: END.

DEFINE PROCEDURE ''MODULUS'' [A,B]:
BLOCK 0: BEGIN
  CELL(0) <= DIVIDE[A,B];
  OUTPUT <= MINUS[A,CELL(0) * B];
BLOCK 0: END.

DEFINE PROCEDURE ''TOGGLE'' [DOOR]:
BLOCK 0: BEGIN
  IF DOOR = 1, THEN:
    QUIT BLOCK 0;
  OUTPUT <= 1;
BLOCK 0: END.

DEFINE PROCEDURE ''NUMBERS'' [DOOR, COUNT]:
BLOCK 0: BEGIN
  CELL(0) <= 1; /*each number*/
  OUTPUT <= 0; /*current door state*/

  LOOP COUNT TIMES:
  BLOCK 1: BEGIN

    IF MODULUS[DOOR, CELL(0)] = 0, THEN:
      OUTPUT <= TOGGLE[OUTPUT];

    CELL(0) <= CELL(0) + 1;

  BLOCK 1: END;

BLOCK 0: END.

DEFINE PROCEDURE ''DOORS'' [COUNT]:
BLOCK 0: BEGIN

  CELL(0) <= 1; /*each door*/
  LOOP COUNT TIMES:
  BLOCK 1: BEGIN

    CELL(1) <= NUMBERS[CELL(0), COUNT];  /*iterate over the states of this door to get its final state*/
    IF CELL(1) = 1, THEN: /*door state = open*/
      PRINT[CELL(0), '   '];

    CELL(0) <= CELL(0) + 1;

  BLOCK 1: END;
BLOCK 0: END.

DOORS[100];


# Project : Atomic updates

bucket = list(10)
f2 = 0
for i = 1 to 10
     bucket[i] = floor(random(9)*10)
next

a = display("display:")
see nl
a = flatten(a)
see "" + a + nl
a = display("flatten:")
see nl
a = transfer(3,5)
see a + nl
see "19 from 3 to 5: "
a = display(a)
see nl

func display(a)
        display = 0
        see "" + a + " " + char(9)
        for i = 1 to 10
             display = display + bucket[i]
             see "" + bucket[i] + " "
        next
       see " total:" + display
       return display

func flatten(f)
        f1 = floor((f / 10) + 0.5)
        for i = 1 to 10
             bucket[i] = f1
             f2	 = f2 + f1
        next
        bucket[10] = bucket[10] + f - f2

func transfer(a1,a2)
        transfer = floor(random(9)/10 * bucket[a1])
        bucket[a1] = bucket[a1] - transfer
        bucket[a2] = bucket[a2] + transfer


require 'thread'

# A collection of buckets, filled with random non-negative integers.
# There are atomic operations to look at the bucket contents, and
# to move amounts between buckets.
class BucketStore

  # Creates a BucketStore with +nbuckets+ buckets. Fills each bucket
  # with a random non-negative integer.
  def initialize nbuckets
    # Create an array for the buckets
    @buckets = (0...nbuckets).map { rand(1024) }

    # Mutex used to make operations atomic
    @mutex = Mutex.new
  end

  # Returns an array with the contents of all buckets.
  def buckets
    @mutex.synchronize { Array.new(@buckets) }
  end

  # Transfers _amount_ to bucket at array index _destination_,
  # from bucket at array index _source_.
  def transfer destination, source, amount
    # Do nothing if both buckets are same
    return nil if destination == source

    @mutex.synchronize do
      # Clamp amount to prevent negative value in bucket
      amount = [amount, @buckets[source]].min

      @buckets[source] -= amount
      @buckets[destination] += amount
    end
    nil
  end
end

# Create bucket store
bucket_store = BucketStore.new 8

# Get total amount in the store
TOTAL = bucket_store.buckets.inject { |a, b| a += b }

# Start a thread to equalize buckets
Thread.new do
  loop do
    # Pick 2 buckets
    buckets = bucket_store.buckets
    first = rand buckets.length
    second = rand buckets.length

    # Swap buckets so that _first_ has not more than _second_
    first, second = second, first if buckets[first] > buckets[second]

    # Transfer half of the difference, rounded down
    bucket_store.transfer first, second, (buckets[second] - buckets[first]) / 2
  end
end

# Start a thread to distribute values among buckets
Thread.new do
  loop do
    # Pick 2 buckets
    buckets = bucket_store.buckets
    first = rand buckets.length
    second = rand buckets.length

    # Transfer random amount to _first_ from _second_
    bucket_store.transfer first, second, rand(buckets[second])
  end
end

# Loop to display buckets
loop do
  sleep 1

  buckets = bucket_store.buckets

  # Compute the total value in all buckets.
  # We calculate this outside BucketStore so BucketStore can't cheat by
  # always reporting the same value.
  n = buckets.inject { |a, b| a += b }

  # Display buckets and total
  printf "%s, total %d\n", (buckets.map { |v| sprintf "%4d", v }.join " "), n

  if n != TOTAL
    # This should never happen
    $stderr.puts "ERROR: Total changed from #{TOTAL} to #{n}"
    exit 1
  end
end


DIM bucket(10)
FOR i = 1 TO 10 : bucket(i) = int(RND(0)*100) : NEXT

a = display("       Display:")	' show original array
a = flatten(a)			' flatten the array
a = display("       Flatten:")	' show flattened array
a = transfer(3,5)		' transfer some amount from 3 to 5
a = display(a;" from 3 to 5:")	' Show transfer array
end

FUNCTION display(a$)
  print a$;" ";chr$(9);
    for i = 1 to 10
      display = display + bucket(i)
      print bucket(i);chr$(9);
    next i
  print " Total:";display
END FUNCTION

FUNCTION flatten(f)
   f1 = int((f / 10) + .5)
   for i = 1 to 10
    bucket(i)	= f1
    f2		= f2 + f1
   next i
   bucket(10)	= bucket(10) + f - f2
END FUNCTION

FUNCTION transfer(a1,a2)
transfer	= int(rnd(0) * bucket(a1))
bucket(a1)	= bucket(a1) - transfer
bucket(a2)	= bucket(a2) + transfer
END FUNCTION


( 100doors-tbl
=   door step
  .   tbl$(doors.101) { Create an array. Indexing is 0-based. Add one extra for addressing element nr. 100 }
    & 0:?step
    &   whl
      ' ( 1+!step:~>100:?step   { ~> means 'not greater than', i.e. 'less than or equal' }
        & 0:?door
        &   whl
          ' ( !step+!door:~>100:?door
            & 1+-1*!(!door$doors):?doors  { <number>$<variable> sets the current index, which stays the same until explicitly changed. }
            )
        )
    & 0:?door
    &   whl
      ' ( 1+!door:~>100:?door
        &   out
          $ ( door
              !door
              is
              ( !(!door$doors):1&open
              | closed
              )
            )
        )
    & tbl$(doors.0)  { clean up the array }
)


extern crate rand;

use std::sync::{Arc, Mutex};
use std::thread;
use std::cmp;
use std::time::Duration;

use rand::Rng;
use rand::distributions::{IndependentSample, Range};

trait Buckets {
    fn equalize<R:Rng>(&mut self, rng: &mut R);
    fn randomize<R:Rng>(&mut self, rng: &mut R);
    fn print_state(&self);
}

impl Buckets for [i32] {
    fn equalize<R:Rng>(&mut self, rng: &mut R) {
        let range = Range::new(0,self.len()-1);
        let src = range.ind_sample(rng);
        let dst = range.ind_sample(rng);
        if dst != src {
            let amount = cmp::min(((dst + src) / 2) as i32, self[src]);
            let multiplier = if amount >= 0 { -1 } else { 1 };
            self[src] += amount * multiplier;
            self[dst] -= amount * multiplier;
        }
    }
    fn randomize<R:Rng>(&mut self, rng: &mut R) {
        let ind_range = Range::new(0,self.len()-1);
        let src = ind_range.ind_sample(rng);
        let dst = ind_range.ind_sample(rng);
        if dst != src {
            let amount = cmp::min(Range::new(0,20).ind_sample(rng), self[src]);
            self[src] -= amount;
            self[dst] += amount;

        }
    }
    fn print_state(&self) {
        println!("{:?} = {}", self, self.iter().sum::<i32>());
    }
}

fn main() {
    let e_buckets = Arc::new(Mutex::new([10; 10]));
    let r_buckets = e_buckets.clone();
    let p_buckets = e_buckets.clone();

    thread::spawn(move || {
        let mut rng = rand::thread_rng();
        loop {
            let mut buckets = e_buckets.lock().unwrap();
            buckets.equalize(&mut rng);
        }
    });
    thread::spawn(move || {
        let mut rng = rand::thread_rng();
        loop {
            let mut buckets = r_buckets.lock().unwrap();
            buckets.randomize(&mut rng);
        }
    });

    let sleep_time = Duration::new(1,0);
    loop {
        {
            let buckets = p_buckets.lock().unwrap();
            buckets.print_state();
        }
        thread::sleep(sleep_time);
    }
}


object AtomicUpdates {

  class Buckets(ns: Int*) {

    import scala.actors.Actor._

    val buckets = ns.toArray

    case class Get(index: Int)
    case class Transfer(fromIndex: Int, toIndex: Int, amount: Int)
    case object GetAll

    val handler = actor {
      loop {
        react {
          case Get(index) => reply(buckets(index))
          case Transfer(fromIndex, toIndex, amount) =>
            assert(amount >= 0)
            val actualAmount = Math.min(amount, buckets(fromIndex))
            buckets(fromIndex) -= actualAmount
            buckets(toIndex) += actualAmount
          case GetAll => reply(buckets.toList)
        }
      }
    }

    def get(index: Int): Int = (handler !? Get(index)).asInstanceOf[Int]
    def transfer(fromIndex: Int, toIndex: Int, amount: Int) = handler ! Transfer(fromIndex, toIndex, amount)
    def getAll: List[Int] = (handler !? GetAll).asInstanceOf[List[Int]]
  }

  def randomPair(n: Int): (Int, Int) = {
    import scala.util.Random._
    val pair = (nextInt(n), nextInt(n))
    if (pair._1 == pair._2) randomPair(n) else pair
  }

  def main(args: Array[String]) {
    import scala.actors.Scheduler._
    val buckets = new Buckets(List.range(1, 11): _*)
    val stop = new java.util.concurrent.atomic.AtomicBoolean(false)
    val latch = new java.util.concurrent.CountDownLatch(3)
    execute {
      while (!stop.get) {
        val (i1, i2) = randomPair(10)
        val (n1, n2) = (buckets.get(i1), buckets.get(i2))
        val m = (n1 + n2) / 2
        if (n1 < n2)
          buckets.transfer(i2, i1, n2 - m)
        else
          buckets.transfer(i1, i2, n1 - m)
      }
      latch.countDown
    }
    execute {
      while (!stop.get) {
        val (i1, i2) = randomPair(10)
        val n = buckets.get(i1)
        buckets.transfer(i1, i2, if (n == 0) 0 else scala.util.Random.nextInt(n))
      }
      latch.countDown
    }
    execute {
      for (i <- 1 to 20) {
        val all = buckets.getAll
        println(all.sum + ":" + all)
        Thread.sleep(500)
      }
      stop.set(true)
      latch.countDown
    }
    latch.await
    shutdown
  }
}


NUM_BUCKETS := 10.
"create and preset with random data"
buckets := (1 to:NUM_BUCKETS)
             collect:[:i | Random nextIntegerBetween:0 and:10000]
             as:Array.
count_randomizations := 0.
count_equalizations := 0.

printSum :=
    [
        "the sum must be computed and printed while noone fiddles around"
        |snapshot|
        snapshot := buckets synchronized:[ buckets copy ].
        Transcript showCR: e' {snapshot} sum={snapshot sum}'.
    ].

pickTwo :=
    [:action |
        "pick two pockets and eval action on it"
        |p1 p2|
        p1 := Random nextIntegerBetween:1 and:NUM_BUCKETS.
        p2 := Random nextIntegerBetween:1 and:NUM_BUCKETS.
        buckets synchronized:[ action value:p1 value:p2 ].
    ].

randomize :=
    [
        pickTwo value:[:p1 :p2 |
            "take a random value from p1 and add to p2"
            |howMuch|
            howMuch := Random nextIntegerBetween:0 and:(buckets at:p1).
            buckets at:p1 put:(buckets at:p1)-howMuch.
            buckets at:p2 put:(buckets at:p2)+howMuch.
        ].
        count_randomizations := count_randomizations + 1.
    ].

equalize :=
    [
        pickTwo value:[:p1 :p2 |
            "average them"
            |diff|
            diff := ((buckets at:p1) - (buckets at:p2)) // 2.
            buckets at:p1 put:(buckets at:p1)-diff.
            buckets at:p2 put:(buckets at:p2)+diff.
        ].
        count_equalizations := count_equalizations + 1.
    ].

"start the show"
randomizer := [ randomize loop ] fork.
equalizer  := [ equalize loop ] fork.

"every 2 seconds, print the sum"
monitor    := [
                [
                    printSum value.
                    Delay waitFor:2 seconds.
                ] loop.
              ] fork.

"let it run for 10 seconds, then kill them all"
Delay waitFor:20 seconds.
randomizer terminate.
equalizer terminate.
monitor terminate.

Stdout printCR: e'performed {count_equalizations} equalizations and {count_randomizations} randomizations'.


import Foundation

final class AtomicBuckets: CustomStringConvertible {
  var count: Int {
    return buckets.count
  }

  var description: String {
    return withBucketsLocked { "\(buckets)" }
  }

  var total: Int {
    return withBucketsLocked { buckets.reduce(0, +) }
  }

  private let lock = DispatchSemaphore(value: 1)

  private var buckets: [Int]

  subscript(n: Int) -> Int {
    return withBucketsLocked { buckets[n] }
  }

  init(with buckets: [Int]) {
    self.buckets = buckets
  }

  func transfer(amount: Int, from: Int, to: Int) {
    withBucketsLocked {
      let transferAmount = buckets[from] >= amount ? amount : buckets[from]

      buckets[from] -= transferAmount
      buckets[to] += transferAmount
    }
  }

  private func withBucketsLocked<T>(do: () -> T) -> T {
    let ret: T

    lock.wait()
    ret = `do`()
    lock.signal()

    return ret
  }
}

let bucks = AtomicBuckets(with: [21, 39, 40, 20])
let order = DispatchSource.makeTimerSource()
let chaos = DispatchSource.makeTimerSource()
let printer = DispatchSource.makeTimerSource()

printer.setEventHandler {
  print("\(bucks) = \(bucks.total)")
}

printer.schedule(deadline: .now(), repeating: .seconds(1))
printer.activate()

order.setEventHandler {
  let (b1, b2) = (Int.random(in: 0..<bucks.count), Int.random(in: 0..<bucks.count))
  let (v1, v2) = (bucks[b1], bucks[b2])

  guard v1 != v2 else {
    return
  }

  if v1 > v2 {
    bucks.transfer(amount: (v1 - v2) / 2, from: b1, to: b2)
  } else {
    bucks.transfer(amount: (v2 - v1) / 2, from: b2, to: b1)
  }
}

order.schedule(deadline: .now(), repeating: .milliseconds(5))
order.activate()

chaos.setEventHandler {
  let (b1, b2) = (Int.random(in: 0..<bucks.count), Int.random(in: 0..<bucks.count))

  bucks.transfer(amount: Int.random(in: 0..<(bucks[b1] + 1)), from: b1, to: b2)
}

chaos.schedule(deadline: .now(), repeating: .milliseconds(5))
chaos.activate()

dispatchMain()


swch ← ≠´{100⥊1«𝕩⥊0}¨1+↕100
¯1↓∾{𝕩∾@+10}¨•Fmt¨⟨swch,/swch⟩


package require Thread
package require Tk

# Make the shared state
canvas .c		;# So we can allocate the display lines in one loop
set m [thread::mutex create]
for {set i 0} {$i<100} {incr i} {
    set bucket b$i	;# A handle for every bucket...
    tsv::set buckets $bucket 50
    lappend buckets $bucket
    lappend lines [.c create line 0 0 0 0]
}
tsv::set still going 1

# Make the "make more equal" task
lappend tasks [thread::create {
    # Perform an atomic update of two cells
    proc transfer {b1 b2 val} {
	variable m
	thread::mutex lock $m
	set v [tsv::get buckets $b1]
	if {$val > $v} {
	    set val $v
	}
	tsv::incr buckets $b1 [expr {-$val}]
	tsv::incr buckets $b2 $val
	thread::mutex unlock $m
    }

    # The task itself; we loop this round frequently
    proc task {mutex buckets} {
	variable m $mutex b $buckets i 0
	while {[tsv::get still going]} {
	    set b1 [lindex $b $i]
	    if {[incr i] == [llength $b]} {set i 0}
	    set b2 [lindex $b $i]

	    if {[tsv::get buckets $b1] > [tsv::get buckets $b2]} {
		transfer $b1 $b2 1
	    } else {
		transfer $b1 $b2 -1
	    }
	}
    }
    thread::wait
}]

# Make the "mess things up" task
lappend tasks [thread::create {
    # Utility to pick a random item from a list
    proc pick list {
	lindex $list [expr {int(rand() * [llength $list])}]
    }
    proc transfer {b1 b2 val} {
	variable m
	thread::mutex lock $m
	set v [tsv::get buckets $b1]
	if {$val > $v} {
	    set val $v
	}
	tsv::incr buckets $b1 [expr {-$val}]
	tsv::incr buckets $b2 $val
	thread::mutex unlock $m
    }

    # The task to move a large amount between two random buckets
    proc task {mutex buckets} {
	variable m $mutex b $buckets
	while {[tsv::get still going]} {
	    set b1 [pick $b]
	    set b2 [pick $b]
	    transfer $b1 $b2 [expr {[tsv::get buckets $b1] / 3}]
	}
    }
    thread::wait
}]

# The "main" task; we keep GUI operations in the main thread
proc redisplay {} {
    global m buckets lines
    thread::mutex lock $m
    set i 1
    foreach b $buckets l $lines {
	.c coords $l $i 0 $i [tsv::get buckets $b]
	incr i 2
    }
    thread::mutex unlock $m
    after 100 redisplay
}

# Start tasks and display
.c configure -width 201 -height 120
pack .c
redisplay
foreach t $tasks {
    thread::send -async $t [list task $m $buckets]
}

# Wait for user to close window, then tidy up
tkwait window .
tsv::set still going 0
thread::broadcast thread::exit


#include <stdio.h>

int main()
{
  char is_open[100] = { 0 };
  int pass, door;

  /* do the 100 passes */
  for (pass = 0; pass < 100; ++pass)
    for (door = pass; door < 100; door += pass+1)
      is_open[door] = !is_open[door];

  /* output the result */
  for (door = 0; door < 100; ++door)
    printf("door #%d is %s.\n", door+1, (is_open[door]? "open" : "closed"));

  return 0;
}


import "random" for Random
import "scheduler" for Scheduler
import "timer" for Timer
import "/math" for Nums

var Rnd = Random.new()

var NUM_BUCKETS = 10
var MAX_VALUE   = 9999

class Buckets {
    construct new(data) {
        _data = data.toList
        _running = true
    }

    [index] { _data[index] }

    transfer(srcIndex, dstIndex, amount) {
        if (amount < 0) Fiber.abort("Negative amount: %(amount)")
        if (amount == 0) return 0
        var a = amount
        if (_data[srcIndex] - a < 0) a = _data[srcIndex]
        if (_data[dstIndex] + a < 0) a = MAX_VALUE - _data[dstIndex]
        if (a < 0) Fiber.abort("Negative amount: %(a)")
        _data[srcIndex] = _data[srcIndex] - a
        _data[dstIndex] = _data[dstIndex] + a
        return a
    }

    buckets { _data.toList }

    transferRandomAmount() {
        while (_running) {
            var srcIndex = Rnd.int(NUM_BUCKETS)
            var dstIndex = Rnd.int(NUM_BUCKETS)
            var amount   = Rnd.int(MAX_VALUE + 1)
            transfer(srcIndex, dstIndex, amount)
            Timer.sleep(1)
        }
    }

    equalize() {
        while (_running) {
            var srcIndex = Rnd.int(NUM_BUCKETS)
            var dstIndex = Rnd.int(NUM_BUCKETS)
            var amount = ((this[srcIndex] - this[dstIndex])/2).truncate
            if (amount >= 0) transfer(srcIndex, dstIndex, amount)
            Timer.sleep(1)
        }
    }

    stop() { _running = false }

    print() {
        Timer.sleep(1000) // one second delay between prints
        var bucketValues = buckets
        System.print("Current values: %(Nums.sum(bucketValues)) %(bucketValues)")
    }
}

var values = List.filled(NUM_BUCKETS, 0)
for (i in 0...NUM_BUCKETS) values[i] = Rnd.int(MAX_VALUE + 1)
System.print("Initial array : %(Nums.sum(values)) %(values)")
var buckets = Buckets.new(values)
var count = 0
while (true) {
    Scheduler.add {
        buckets.equalize()
    }
    buckets.print()
    Scheduler.add {
        buckets.transferRandomAmount()
    }
    buckets.print()
    count = count + 2
    if (count == 10) {  // stop after 10 prints, say
        buckets.stop()
        break
    }
}


namespace ConsoleApplication1
{
    using System;
    class Program
    {
        static void Main(string[] args)
        {
            bool[] doors = new bool[100];

            //Close all doors to start.
            for (int d = 0; d < 100; d++) doors[d] = false;

            //For each pass...
            for (int p = 0; p < 100; p++)//number of passes
            {
                //For each door to toggle...
                for (int d = 0; d < 100; d++)//door number
                {
                    if ((d + 1) % (p + 1) == 0)
                    {
                        doors[d] = !doors[d];
                    }
                }
            }

            //Output the results.
            Console.WriteLine("Passes Completed!!!  Here are the results: \r\n");
            for (int d = 0; d < 100; d++)
            {
                if (doors[d])
                {
                    Console.WriteLine(String.Format("Door #{0}: Open", d + 1));
                }
                else
                {
                    Console.WriteLine(String.Format("Door #{0}: Closed", d + 1));
                }
            }
            Console.ReadKey(true);
        }
    }
}


class B{
   const N=10;
   var [const]
      buckets=(1).pump(N,List).copy(),  //(1,2,3...)
      lock=Atomic.Lock(), cnt=Atomic.Int();
   fcn init{ "Initial sum: ".println(values().sum()); }
   fcn transferArb{  // transfer arbitary amount from 1 bucket to another
      b1:=(0).random(N); b2:=(0).random(N);
      critical(lock){
	 t:=(0).random(buckets[b1]);
	 buckets[b1]=buckets[b1]-t; buckets[b2]=buckets[b2]+t;
      }
      cnt.inc();
   }
   fcn transferEq{  // try to make two buckets equal
      b1:=(0).random(N); b2:=(0).random(N);
      critical(lock){
         v1:=buckets[b1]; v2:=buckets[b2];
	 t:=(v1-v2).abs()/2;
	 if (v1<v2) t = -t;
	 buckets[b1]=v1-t; buckets[b2]=v2+t;
      }
      cnt.inc();
   }
   fcn values{ critical(lock){buckets.copy()} }
}

fcn threadA(b){ while(1) { b.transferArb(); } }
fcn threadE(b){ while(1) { b.transferEq();  } }


#include <iostream>

int main()
{
  bool is_open[100] = { false };

  // do the 100 passes
  for (int pass = 0; pass < 100; ++pass)
    for (int door = pass; door < 100; door += pass+1)
      is_open[door] = !is_open[door];

  // output the result
  for (int door = 0; door < 100; ++door)
    std::cout << "door #" << door+1 << (is_open[door]? " is open." : " is closed.") << std::endl;
  return 0;
}


 for i=1:1:100 {
	 set doors(i) = 0
 }
 for i=1:1:100 {
	 for door=i:i:100 {
		  Set doors(door)='doors(door)
	 }
 }
 for i = 1:1:100
 {
	if doors(i)=1 write i_": open",!
 }


shared void run() {
    print("Open doors (naive):     ``naive()``
           Open doors (optimized): ``optimized()``");

}

shared {Integer*} naive(Integer count = 100) {
    variable value doors = [ for (_ in 1..count) closed ];
    for (step in 1..count) {
        doors = [for (i->door in doors.indexed) let (index = i+1) if (step == 1 || step.divides(index)) then door.toggle() else door ];
    }
    return doors.indexesWhere((door) => door == opened).map(1.plusInteger);
}

shared {Integer*} optimized(Integer count = 100) =>
        { for (i in 1..count) i*i }.takeWhile(count.notSmallerThan);

shared abstract class Door(shared actual String string) of opened | closed {
    shared formal Door toggle();
}
object opened extends Door("opened") { toggle() => closed; }
object closed extends Door("closed") { toggle() => opened; }


    program

    map
    end

MAX_DOOR_NUMBER         equate(100)
CRLF                    equate('<13,10>')

Doors                   byte,dim(MAX_DOOR_NUMBER)
Pass                    byte
DoorNumber              byte
DisplayString           cstring(2000)

ResultWindow            window('Result'),at(,,133,291),center,double,auto
                            prompt('Door states:'),at(8,4),use(?PromptTitle)
                            text,at(8,16,116,266),use(DisplayString),boxed,vscroll,font('Courier New',,,,CHARSET:ANSI),readonly
                        end

    code

    Doors :=: false
    loop Pass = 1 to MAX_DOOR_NUMBER
        loop DoorNumber = Pass to MAX_DOOR_NUMBER by Pass
            Doors[DoorNumber] = choose(Doors[DoorNumber], false, true)
        end
    end

    clear(DisplayString)
    loop DoorNumber = 1 to MAX_DOOR_NUMBER
        DisplayString = DisplayString & format(DoorNumber, @n3) & ' is ' & choose(Doors[DoorNumber], 'opened', 'closed') & CRLF
    end
    open(ResultWindow)
    accept
    end
    close(ResultWindow)

    return


fn visit-doors doors step:
  if step > 100: doors
  else:
    [1:100]
      -> * fn index:
            if index % step: doors[(index - 1)]
            else: not doors[(index - 1)]
      -> visit-doors (step + 1)

[1:100] -> * n: false -> visit-doors 1 => doors
[1:100] -> * (@eager) fn i:
  doors[(i - 1)]
    -> if = true: #open
            else: #closed
    -> print #Door i #is @


(deffacts initial-state
  (door-count 100)
)

(deffunction toggle
  (?state)
  (switch ?state
    (case "open" then "closed")
    (case "closed" then "open")
  )
)

(defrule create-doors-and-visits
  (door-count ?count)
  =>
  (loop-for-count (?num 1 ?count) do
    (assert (door ?num "closed"))
    (assert (visit-from ?num ?num))
  )
  (assert (doors initialized))
)

(defrule visit
  (door-count ?max)
  ?visit <- (visit-from ?num ?step)
  ?door <- (door ?num ?state)
  =>
  (retract ?visit)
  (retract ?door)
  (assert (door ?num (toggle ?state)))
  (if
    (<= (+ ?num ?step) ?max)
    then
    (assert (visit-from (+ ?num ?step) ?step))
  )
)

(defrule start-printing
  (doors initialized)
  (not (visit-from ? ?))
  =>
  (printout t "These doors are open:" crlf)
  (assert (print-from 1))
)

(defrule print-door
  (door-count ?max)
  ?pf <- (print-from ?num)
  (door ?num ?state)
  =>
  (retract ?pf)
  (if
    (= 0 (str-compare "open" ?state))
    then
    (printout t ?num " ")
  )
  (if
    (< ?num ?max)
    then
    (assert (print-from (+ ?num 1)))
    else
    (printout t crlf "All other doors are closed." crlf)
  )
)


(defn doors []
  (let [doors (into-array (repeat 100 false))]
    (doseq [pass   (range 1 101)
            i      (range (dec pass) 100 pass) ]
      (aset doors i (not (aget doors i))))
    doors))

(defn open-doors [] (for [[d n] (map vector (doors) (iterate inc 1)) :when d] n))

(defn print-open-doors []
  (println
    "Open doors after 100 passes:"
    (apply str (interpose ", " (open-doors)))))


V d = [‘key1’ = ‘value1’, ‘key2’ = ‘value2’]

L(key, value) d
   print(key‘ = ’value)

L(key) d.keys()
   print(key)

L(value) d.values()
   print(value)


start_up = proc ()
    max = 100
    po: stream := stream$primary_output()
    open: array[bool] := array[bool]$fill(1, max, false)

    for pass: int in int$from_to(1, max) do
        for door: int in int$from_to_by(pass, max, pass) do
            open[door] := ~open[door]
        end
    end

    for door: int in array[bool]$indexes(open) do
        if open[door] then
            stream$putl(po, "Door " || int$unparse(door) || " is open.")
        end
    end
end start_up


{"one": 1, "two": "bad"}
( swap . space . cr )
m:each


with Ada.Text_IO;  use Ada.Text_IO;
with Ada.Containers.Indefinite_Ordered_Maps;

procedure Test_Iteration is
   package String_Maps is
      new Ada.Containers.Indefinite_Ordered_Maps (String, Integer);
   use String_Maps;
   A     : Map;
   Index : Cursor;
begin
   A.Insert ("hello", 1);
   A.Insert ("world", 2);
   A.Insert ("!",     3);
   Index := A.First;
   while Index /= No_Element loop
      Put_Line (Key (Index) & Integer'Image (Element (Index)));
      Index := Next (Index);
   end loop;
end Test_Iteration;


record r;
text s;

r_put(r, "A", 33);              # an integer value
r_put(r, "C", 2.5);             # a real value
r_put(r, "B", "associative");   # a string value

if (r_first(r, s)) {
    do {
        o_form("key ~, value ~ (~)\n", s, r[s], r_type(r, s));
    } while (rsk_greater(r, s, s));
}


       IDENTIFICATION DIVISION.
       PROGRAM-ID. 100Doors.

       DATA DIVISION.
       WORKING-STORAGE SECTION.
       01 Current-n      PIC 9(3).
       01 StepSize       PIC 9(3).
       01 DoorTable.
          02 Doors       PIC 9(1)   OCCURS 100 TIMES.
             88 ClosedDoor          VALUE ZERO.
       01 Idx            PIC 9(3).

       PROCEDURE DIVISION.
       Begin.
           INITIALIZE DoorTable
           PERFORM VARYING StepSize FROM 1 BY 1 UNTIL StepSize > 100
             PERFORM VARYING Current-n FROM StepSize BY StepSize
                     UNTIL Current-n > 100
               SUBTRACT Doors (Current-n) FROM 1 GIVING Doors (Current-n)
             END-PERFORM
           END-PERFORM

           PERFORM VARYING Idx FROM 1 BY 1
                   UNTIL Idx > 100
             IF ClosedDoor (Idx)
               DISPLAY Idx " is closed."
             ELSE
               DISPLAY Idx " is open."
             END-IF
           END-PERFORM

           STOP RUN
           .