space system
{

enum state
{
    header
    balanced
    left_high
    right_high
}

enum direction
{
  from_left
  from_right
}

class node
{
    left
    right
    parent
    balance
    data

    node()
    {
       left = this
       right = this
       balance = state.header
       parent = null
       data = null
    }

    node(root d)
    {
      left = null
      right = null
      parent = root
      balance = state.balanced
      data = d
    }

    is_header
    {
        get
        {
            return balance == state.header
        }
    }

    next
    {
        get
        {
            if is_header return left

            if !right.null()
            {
                n = right
                while !n.left.null() n = n.left
                return n
             }
             else
             {
                  y = parent
                  if y.is_header return y

                  n = this
                  while n == y.right
                  {
                       n = y
                       y = y.parent
                       if y.is_header break
                   }
                   return y
              }
          }
     }

   previous
   {
       get
       {
            if is_header return right

            if !left.null()
            {
               n = left
               while !n.right.null() n = right
               return n
            }
            else
            {
                y = parent
                if y.is_header return y

                n = this
                while n == y.left
                {
                    n = y
                    y = y.parent
                    if y.is_header break
                 }
                 return y
             }
        }
    }

    rotate_left()
    {
        _right = right
        _parent = parent
         parent = _right
         _right.parent = _parent
        if !_right.left.null() _right.left.parent = this
        right = _right.left
        _right.left = this
        this = _right
    }

    rotate_right()
    {
        _left = left
        _parent = parent
        parent = _left
        _left.parent =  _parent
        if !_left.right.null() _left.right.parent = this
        left = _left.right
        _left.right = this
        this = _left
    }

    balance_left()
    {
        select left.balance
        {
            left_high
            {
                balance = state.balanced
                left.balance = state.balanced
                rotate_right()
            }

            right_high
            {
                subright = left.right

                select subright.balance
                {
                    balanced
                    {
                        balance = state.balanced
                        left.balance = state.balanced
                    }

                    right_high
                    {
                        balance = state.balanced
                        left.balance = state.left_high
                    }

                    left_high
                    {
                        balance = state.right_high
                        lehpt.balance = state.balanced
                    }
                }
                subright.balance = state.balanced
                left.rotate_left()
                rotate_right()
            }

            balanced
            {
                balance = state.left_high
                left.balance = state.right_high
                rotate_right()
            }
        }
    }

    balance_right()
    {
        select right.balance
        {
            right_high
            {
                balance = state.balanced
                right.balance = state.balanced
                rotate_left()

            }

           left_high
           {
               subleft = right.left

               select subleft.balance
               {
                   balanced
                   {
                       balance = state.balanced
                       right.balance = state.balanced
                   }

                   left_high
                   {
                       balance = state.balanced
                       right.balance = state.right_high
                   }

                   right_high
                   {
                       balance = state.left_high
                       right.balance = state.balanced
                   }
               }
               subleft.balance = state.balanced
               right.rotate_right()
               rotate_left()
           }

           balanced
           {
               balance = state.right_high
               right.balance = state.left_high
               rotate_left()
           }
        }
    }

    balance_tree(from)
    {
        taller = true

        while taller
        {
            p = parent

            next_from = direction.from_left
            if this != parent.left next_from = direction.from_right

            if from == direction.from_left
                select balance
                {
                    left_high
                    {
                        if parent.is_header
                            parent.parent.balance_left()
                        else
                        {
                            if parent.left == this
                                parent.left.balance_left()
                            else
                                parent.right.balance_left()
                            taller = false
                        }
                    }

                    balanced
                    {
                        balance = state.left_high
                        taller = true
                    }

                    right_high
                    {
                        balance = state.balanced
                        taller = false
                    }
            }
            else
               select balance
               {
                   left_high
                   {
                       balance = state.balanced
                       taller = false
                   }

                   balanced
                   {
                       balance = state.right_high
                       taller = true
                    }

                   right_high
                   {
                        if parent.is_header
                            parent.parent.balance_right()
                        else
                        {
                            if parent.left == this
                                parent.left.balance_right()
                            else
                                parent.right.balance_right()
                        }
                        taller = false
                     }
                 }

             if taller
             {

                 if p.is_header
                   taller = false
                 else
                 {
                     this = p
                     from = next_from
                 }
             }
         }
    }

    balance_tree_remove(from)
    {
         shorter = true

         while shorter
         {

            next_from = direction.from_left

           if this != parent.left next_from = direction.from_right

            if from == direction.from_left
                select balance
                {
                    left_high
                    {
                        balance = state.balanced
                        shorter = true
                    }

                    balanced
                    {
                        balance = state.right_high
                        shorter = false
                    }

                    right_high
                    {
                        if right.balance == state.right_high
                            shorter = false
                        else
                            shorter = true

                        if parent.is_header
                            parent.parent.balance_right()
                        else
                        {
                            if parent.left == this
                                parent.left.balance_right()
                            else
                                parent.right.balance_right()
                       }
                   }
             }
             else
                select balance
                {
                    right_high
                    {
                        balance = state.balanced
                        shorter = true
                    }

                    balanced
                    {
                       balance = state.left_high
                       shorter = false
                    }

                    left_high
                    {
                        if left.balance == state.balanced
                            shorter = false
                        else
                            shorter = true

                        if parent.is_header
                            parent.parent.balance_left()
                        else
                        {
                            if parent.is_header
                                parent.left.balance_left()
                            else
                                parent.right.balance_left()
                        }
                   }
            }

            if shorter
            {
              if parent.is_header
                  shorter = false
               else
               {
                  this = parent
                  from = next_from
               }
           }
        }
    }

    count
    {
        get
        {
            result = +a

            if !null()
            {
               cleft = +a
               if !left.null() cleft = left.count

               cright = +a
               if !right.null() cright = right.count

               result = result + cleft + cright + +b
            }

            return result
       }
    }

    depth
    {
        get
        {
            result = +a

            if !null()
            {
               cleft = +a
               if !left.null() cleft = left.depth

               cright = +a
               if !right.null() cright = right.depth

               if cleft > cright
                  result = cleft + +b
               else
                  result = cright + +b
            }

            return result
       }
    }
}

    class default_comparer
    {
      default_comparer() {}

      compare_to(a b)
      {
        if a < b return -1
        if b < a return 1
        return 0
      }
    }

    class set
    {
        header
        iterator
        comparer

        set()
        {
           header = node()
           iterator = null
           comparer = default_comparer()
        }

        set(c_set)
        {
           header = node()
           iterator = null
           comparer = c_set
        }

        left_most
        {
           get
           {
               return header.left
           }
           set
           {
               header.left = value
           }
        }

        right_most
        {
           get
           {
               return header.right
           }
           set
           {
               header.right = value
           }
        }

       root
       {
           get
           {
                return header.parent
           }
           set
           {
                header.parent = value
           }
        }

        empty
        {
            get
            {
                return header.parent.null()
            }
         }

        operator<<(data)
        {
            if header.parent.null()
            {
                root = node(header data)
                left_most = root
                right_most = root
            }
            else
            {
                node = root

                repeat
                {
                    result = comparer.compare_to(data node.data)
                    if result < 0
                    {
                        if !node.left.null()
                            node = node.left
                        else
                        {
                            new_node = node(node data)
                            node.left = new_node
                            if left_most == node left_most = new_node
                            node.balance_tree(direction.from_left)
                            break
                        }
                   }
                   else if result > 0
                   {
                       if !node.right.null()
                           node = node.right
                       else
                       {
                           new_node = node(node data)
                           node.right = new_node
                           if right_most == node right_most = new_node
                           node.balance_tree(direction.from_right)
                           break
                        }
                    }
                    else // item already exists
                        throw "entry " + (string)data + " already exists"
               }
           }
           return this
       }

        update(data)
        {
            if empty
            {
                root = node(header data)
                left_most = root
                right_most = root
            }
            else
            {
                node = root

                repeat
                {
                    result = comparer.compare_to(data node.data)
                    if result < 0
                    {
                        if !node.left.null()
                            node = node.left
                        else
                        {
                            new_node = node(node data)
                            node.left = new_node
                            if left_most == node left_most = new_node
                            node.balance_tree(direction.from_left)
                            break
                        }
                   }
                   else if result > 0
                   {
                        if !node.right.null()
                            node = node.right
                        else
                        {
                            new_node = node(node data)
                            node.right = new_node
                            if right_most == node right_most = new_node
                            node.balance_tree(direction.from_right)
                            break
                        }
                   }
                   else // item already exists
                   {
                        node.data = data
                        break
                   }
               }
           }
       }

        operator>>(data)
        {
             node = root

             repeat
             {
                  if node.null()
                  {
                       throw "entry " + (string)data + " not found"
                  }

                  result = comparer.compare_to(data node.data)

                  if result < 0
                       node = node.left
                  else if result > 0
                       node = node.right
                  else // item found
                  {
                      if !node.left.null() && !node.right.null()
                      {
                         replace = node.left
                         while !replace.right.null() replace = replace.right
                         temp = node.data
                         node.data = replace.data
                         replace.data = temp
                         node = replace
                      }

                      from = direction.from_left
                      if node != node.parent.left from = direction.from_right

                      if left_most == node
                      {
                          next = node
                          next = next.next

                          if header == next
                          {
                              left_most = header
                              right_most = header
                          }
                          else
                              left_most = next
                      }

                      if right_most == node
                      {
                          previous = node
                          previous = previous.previous

                          if header == previous
                          {
                              left_most = header
                              right_most = header
                          }
                          else
                               right_most = previous
                      }

                      if node.left.null()
                      {
                           if node.parent == header
                               root = node.right
                           else
                           {
                               if node.parent.left == node
                                   node.parent.left = node.right
                               else
                                   node.parent.right = node.right
                           }

                           if !node.right.null()
                               node.right.parent = node.parent
                      }
                      else
                      {
                          if node.parent == header
                               root = node.left
                           else
                           {
                               if node.parent.left == node
                                   node.parent.left = node.left
                               else
                                   node.parent.right = node.left
                            }

                           if !node.left.null()
                                node.left.parent = node.parent

                      }
                      node.parent.balance_tree_remove(from)
                      break
                 }
             }
             return this
        }

        remove(data)
        {
             node = root

             repeat
             {
                  if node.null()
                  {
                       throw "entry " + (string)data + " not found"
                  }

                  result = comparer.compare_to(data node.data)

                  if result < 0
                       node = node.left
                  else if result > 0
                       node = node.right
                  else // item found
                  {
                      if !node.left.null() && !node.right.null()
                      {
                         replace = node.left
                         while !replace.right.null() replace = replace.right
                         temp = node.data
                         node.data = replace.data
                         replace.data = temp
                         node = replace
                      }

                      from = direction.from_left
                      if node != node.parent.left from = direction.from_right

                      if left_most == node
                      {
                          next = node
                          next = next.next

                          if header == next
                          {
                              left_most = header
                              right_most = header
                          }
                          else
                              left_most = next
                      }

                      if right_most == node
                      {
                          previous = node
                          previous = previous.previous

                          if header == previous
                          {
                              left_most = header
                              right_most = header
                          }
                          else
                               right_most = previous
                      }

                      if node.left.null()
                      {
                           if node.parent == header
                               root = node.right
                           else
                           {
                               if node.parent.left == node
                                   node.parent.left = node.right
                               else
                                   node.parent.right = node.right
                           }

                           if !node.right.null()
                               node.right.parent = node.parent
                      }
                      else
                      {
                          if node.parent == header
                               root = node.left
                           else
                           {
                               if node.parent.left == node
                                   node.parent.left = node.left
                               else
                                   node.parent.right = node.left
                            }

                           if !node.left.null()
                                node.left.parent = node.parent

                      }
                      node.parent.balance_tree_remove(from)
                      break
                 }
             }
             return this
        }

        remove2(data)
        {
             node = root

             repeat
             {
                  if node.null()
                  {
                       return null
                  }

                  result = comparer.compare_to(data node.data)

                  if result < 0
                       node = node.left
                  else if result > 0
                       node = node.right
                  else // item found
                  {
                      if !node.left.null() && !node.right.null()
                      {
                         replace = node.left
                         while !replace.right.null() replace = replace.right
                         temp = node.data
                         node.data = replace.data
                         replace.data = temp
                         node = replace
                      }

                      from = direction.from_left
                      if node != node.parent.left from = direction.from_right

                      if left_most == node
                      {
                          next = node
                          next = next.next

                          if header == next
                          {
                              left_most = header
                              right_most = header
                          }
                          else
                              left_most = next
                      }

                      if right_most == node
                      {
                          previous = node
                          previous = previous.previous

                          if header == previous
                          {
                              left_most = header
                              right_most = header
                          }
                          else
                               right_most = previous
                      }

                      if node.left.null()
                      {
                           if node.parent == header
                               root = node.right
                           else
                           {
                               if node.parent.left == node
                                   node.parent.left = node.right
                               else
                                   node.parent.right = node.right
                           }

                           if !node.right.null()
                               node.right.parent = node.parent
                      }
                      else
                      {
                          if node.parent == header
                               root = node.left
                           else
                           {
                               if node.parent.left == node
                                   node.parent.left = node.left
                               else
                                   node.parent.right = node.left
                            }

                           if !node.left.null()
                                node.left.parent = node.parent

                      }
                      node.parent.balance_tree_remove(from)
                      break
                 }
             }
        }

       operator[data]
       {
           get
           {
               if empty
               {
                   return false
               }
               else
               {
                   node = root

                   repeat
                   {
                       result = comparer.compare_to(data node.data)

                       if result < 0
                       {
                           if !node.left.null()
                               node = node.left
                           else
                               return false
                       }
                       else if result > 0
                       {
                           if !node.right.null()
                               node = node.right
                           else
                               return false
                       }
                       else // item exists
                           return true
                   }
               }
           }
       }

       get(data)
       {
           if empty throw "empty collection"

           node = root

           repeat
           {
               result = comparer.compare_to(data node.data)
               if result < 0
               {
                  if !node.left.null()
                     node = node.left
                  else
                     throw "item: " + (string)data + " not found in collection"
               }
               else if result > 0
               {
                   if !node.right.null()
                       node = node.right
                    else
                      throw "item: " + (string)data + " not found in collection"
               }
               else // item exists
                   return node.data
            }
        }

      last
       {
           get
           {
               if empty
                  throw "empty set"
               else
                  return header.right.data
           }
       }

        iterate()
        {
            if iterator.null()
            {
               iterator = left_most
               if iterator == header
                   return iterator(false none())
               else
                   return iterator(true iterator.data)
            }
            else
            {
               iterator = iterator.next

               if iterator == header
                   return  iterator(false none())
               else
                   return iterator(true iterator.data)
            }
        }

        count
        {
           get
           {
               return root.count
           }
        }

        depth
        {
           get
           {
               return root.depth
           }
        }

        operator==(compare)
        {
         if this < compare return false
         if compare < this return false
         return true
        }

        operator!=(compare)
        {
         if this < compare return true
         if compare < this return true
         return false
        }

        operator<(c)
        {
         first1 = begin
         last1 = end
         first2 = c.begin
         last2 = c.end

         while first1 != last1 && first2 != last2
         {
            result = comparer.compare_to(first1.data first2.data)
            if result >= 0
            {
                first1 = first1.next
                first2 = first2.next
            }
            else return true
         }
         a = count
         b = c.count
         return a < b
      }

      begin { get { return header.left } }

      end { get { return header } }

      operator string()
      {
          out = "{"
          first1 = begin
          last1 = end
          while first1 != last1
          {
              out = out + (string)first1.data
              first1 = first1.next
              if first1 != last1 out = out + ","
          }
          out = out + "}"
          return out
      }

       operator|(b)
       {
           r = new set()

           first1 = begin
           last1 = end
           first2 = b.begin
           last2 = b.end

            while first1 != last1 && first2 != last2
            {
                result = comparer.compare_to(first1.data first2.data)

                if result < 0
                {
                    r << first1.data
                    first1 = first1.next
                }

                else if result > 0
                {
                    r << first2.data
                    first2 = first2.next
                }

                else
                {
                    r << first1.data
                    first1 = first1.next
                    first2 = first2.next
                }
            }

            while first1 != last1
            {
                r << first1.data
                first1 = first1.next
            }
            while first2 != last2
            {
                r << first2.data
                first2 = first2.next
            }
            return r
       }

       operator&(b)
       {
           r = new set()

           first1 = begin
           last1 = end
           first2 = b.begin
           last2 = b.end

            while first1 != last1 && first2 != last2
            {
                result = comparer.compare_to(first1.data first2.data)

                if result < 0
                {
                   first1 = first1.next
                }

                else if result > 0
                {
                   first2 = first2.next
                }

                else
                {
                   r << first1.data
                   first1 = first1.next
                   first2 = first2.next
                }
            }

            return r
       }

       operator^(b)
       {
           r = new set()

           first1 = begin
           last1 = end
           first2 = b.begin
           last2 = b.end

            while first1 != last1 && first2 != last2
            {
                result = comparer.compare_to(first1.data first2.data)

                if result < 0
                {
                   r << first1.data
                   first1 = first1.next
                }

                else if result > 0
                {
                   r << first2.data
                   first2 = first2.next
                }

                else
                {
                   first1 = first1.next
                   first2 = first2.next
                }
            }

            while first1 != last1
            {
                r << first1.data
                first1 = first1.next
            }
            while first2 != last2
            {
                r << first2.data
                first2 = first2.next
            }
            return r
       }

       operator-(b)
       {
           r = new set()

           first1 = begin
           last1 = end
           first2 = b.begin
           last2 = b.end

            while first1 != last1 && first2 != last2
            {
                result = comparer.compare_to(first1.data first2.data)

                if result < 0
                {
                   r << first1.data
                   first1 = first1.next
                }

                else if result > 0
                {
                   r << first2.data
                   first1 = first1.next
                   first2 = first2.next
                }

                else
                {
                   first1 = first1.next
                   first2 = first2.next
                }
            }

            while first1 != last1
            {
                r << first1.data
                first1 = first1.next
            }
            return r
       }
    }

class tree
{
  s

  tree()
  {
      s = set()
  }

  operator<<(e)
  {
       s << e
       return this
  }

  operator[key]
  {
      get
      {
           if empty
               throw "entry not found exception"
           else
           {
               node = s.root

               repeat
               {
                   if key < node.data
                   {
                       if !node.left.null()
                           node = node.left
                       else
                           throw "entry not found exception"
                   }
                   else
                   {
                       if key == node.data
                           return node.data
                       else
                       {
                           if !node.right.null()
                               node = node.right
                           else
                               throw "entry not found exception"
                       }
                   }
               }
          }
     }
  }

  operator>>(e)
  {
       entry = this[e]
       s >> entry
  }

  remove(key)
  {
      s >> key_value(key)
  }

  iterate()
  {
      return s.iterate()
   }

   count
   {
      get
      {
         return s.count
      }
   }

   empty
   {
       get
       {
           return s.empty
       }
   }

   last
   {
       get
       {
           if empty
              throw "empty tree"
           else
              return s.last
       }
   }

    operator string()
    {
       return (string)s
     }
}

class dictionary
{
  s

    dictionary()
    {
        s = set()
    }

    operator<<(key_value)
    {
       s << key_value
       return this
    }

    add(key value)
    {
       s << key_value(key value)
    }

    operator[key]
    {
       set
       {
           try { s >> key_value(key) } catch {}
           s << key_value(key value)
       }
       get
       {
          r = s.get(key_value(key))
          return r.value
       }
    }

    operator>>(key)
    {
        s >> key_value(key)
        return this
    }

    iterate()
    {
        return s.iterate()
    }

    count
    {
        get
        {
            return s.count
        }
    }

    operator string()
    {
        return (string)s
    }
}

class key_value
{
  key
  value

  key_value(key_set)
  {
     key = key_set
     value = nul
  }

  key_value(key_set  value_set)
  {
     key = key_set
     value = value_set
  }

  operator<(kv)
  {
      return key < kv.key
  }

  operator string()
  {
    if value.nul()
       return "(" + (string)key + " null)"
    else
       return "(" + (string)key + " " + (string)value  + ")"
  }
}

class array
{
  s        // this is a set of key/value pairs.
  iterator // this field holds an iterator for the array.

  array()   // no parameters required phor array construction.
  {
   s = set()   // create a set of key/value pairs.
   iterator = null // the iterator is initially set to null.
  }

  begin { get { return s.header.left } }   // property: used to commence manual iteration.

  end { get { return s.header } } // property: used to define the end item of iteration.

  operator<(a) // less than operator is called by the avl tree algorithms
  {             // this operator implies phor instance that you could potentially have sets of arrays.

    if keys < a.keys  // compare the key sets first.
       return true
    else if a.keys < keys
       return false
    else               // the key sets are equal  therephore compare array elements.
    {
     first1 = begin
     last1 = end
     first2 = a.begin
     last2 = a.end

     while first1 != last1 && first2 != last2
     {
       if first1.data.value < first2.data.value
        return true
       else
       {
         if first2.data.value < first1.data.value
          return false
         else
         {
            first1 = first1.next
            first2 = first2.next
         }
       }
     }

     return false
    }
  }

    operator==(compare) // equals and not equals derive from operator<
    {
     if this < compare return false
     if compare < this return false
     return true
    }

    operator!=(compare)
    {
     if this < compare return true
     if compare < this return true
     return false
    }

  operator<<(e) // this operator adds an element to the end of the array.
  {
     try
     {
         this[s.last.key + +b] = e
     }
     catch
     {
         this[+a] = e
     }
     return this
  }

  operator[key] // this is the array indexer.
  {
       set
       {
           try { s >> key_value(key) } catch {}
           s << key_value(integer(key) value)
       }
       get
       {
          result = s.get(key_value(key))
          return result.value
       }
  }

  operator>>(key) // this operator removes an element from the array.
  {
   s >> key_value(key)
   return this
  }

  iterate() // and this is how to iterate on the array.
  {
      if iterator.null()
      {
         iterator = s.left_most
         if iterator == s.header
             return iterator(false none())
         else
             return iterator(true iterator.data.value)
      }
      else
      {
         iterator = iterator.next

         if iterator == s.header
         {
             iterator = null
             return iterator(false none())
         }
         else
             return iterator(true iterator.data.value)
      }
   }

   count // this property returns a count of elements in the array.
   {
      get
      {
         return s.count
      }
   }

   empty // is the array empty? (Property of course).
   {
       get
       {
           return s.empty
       }
   }

   last // returns the value of the last element in the array.
   {
       get
       {
           if empty
                 throw "empty array"
           else
               return s.last.value
       }
   }

   📟 string() // converts the array to a string
    {
       out = "{"

       iterator = s.left_most
       while iterator != s.header
       {
           _value = iterator.data.value
           out = out + (string)_value
           if iterator != s.right_most
              out = out + ","
           iterator = iterator.next
       }
       out = out + "}"
       return out
    }

   keys // return the set of keys of the array (a set of integers).
   {
      get
      {
          k = set()
          for e s k << e.key
          return k
      }
   }

   sort // unloads the set into a value and reloads in sorted order.
   {
       get
       {
           sort_bag = bag()
           for e s sort_bag << e.value
           a = new array()
           for g sort_bag a << g
           return a
        }
   }

}

// and here is a test program

using system
space sampleB
{
  sampleB()
  {
    try
    {
       🌳 = { "A" "B" "C" }                     // create a tree

       🌳 << "D" << "E"

       🎛 << "Found: " << 🌳["B"] << "\n"

       for inst 🌳 🎛 << inst << "\n"

       🎛 << 🌳 << "\n"

       💰 = bag() { 1 1 2 3 }                  // create a bag

       🎛 << 💰 << "\n"

       🪣 = ["D" "C" "B" "A"]                   // create an array

       🎛 << 🪣 << "\n"

       🎛 << 🪣.sort << "\n"

       🪣[4] = "E"

       🎛 << 🪣 << "\n"

       📘 = <[0 "hello"] [1 "world"]>         // create a dictionary

       🎛 << 📘 << "\n"

       📘[2] = "goodbye"

       🎛 << 📘 << "\n"
    }
    catch
    {
      🎛 << exception << "\n"
    }

  }

}

// The output of the program is shown below.

Found: B
A
B
C
D
E
{A,B,C,D,E}
{1,1,2,3}
{D,C,B,A}
{A,B,C,D}
{D,C,B,A,E}
{(0 hello),(1 world)}
{(0 hello),(1 world),(2 goodbye)}


F ffactorial(n)
   V result = 1.0
   L(i) 2..n
      result *= i
   R result

V MAX_N = 20
V TIMES = 1000000

F analytical(n)
   R sum((1..n).map(i -> ffactorial(@n) / pow(Float(@n), Float(i)) / ffactorial(@n - i)))

F test(n, times)
   V count = 0
   L(i) 0 .< times
      V (x, bits) = (1, 0)
      L (bits [&] x) == 0
         count++
         bits [|]= x
         x = 1 << random:(n)
   R Float(count) / times

print(" n      avg     exp.    diff\n-------------------------------")
L(n) 1 .. MAX_N
   V avg = test(n, TIMES)
   V theory = analytical(n)
   V diff = (avg / theory - 1) * 100
   print(‘#2 #3.4 #3.4 #2.3%’.format(n, avg, theory, diff))


package avl

// AVL tree adapted from Julienne Walker's presentation at
// http://eternallyconfuzzled.com/tuts/datastructures/jsw_tut_avl.aspx.
// This port uses similar indentifier names.

// The Key interface must be supported by data stored in the AVL tree.
type Key interface {
    Less(Key) bool
    Eq(Key) bool
}

// Node is a node in an AVL tree.
type Node struct {
    Data    Key      // anything comparable with Less and Eq.
    Balance int      // balance factor
    Link    [2]*Node // children, indexed by "direction", 0 or 1.
}

// A little readability function for returning the opposite of a direction,
// where a direction is 0 or 1.  Go inlines this.
// Where JW writes !dir, this code has opp(dir).
func opp(dir int) int {
    return 1 - dir
}

// single rotation
func single(root *Node, dir int) *Node {
    save := root.Link[opp(dir)]
    root.Link[opp(dir)] = save.Link[dir]
    save.Link[dir] = root
    return save
}

// double rotation
func double(root *Node, dir int) *Node {
    save := root.Link[opp(dir)].Link[dir]

    root.Link[opp(dir)].Link[dir] = save.Link[opp(dir)]
    save.Link[opp(dir)] = root.Link[opp(dir)]
    root.Link[opp(dir)] = save

    save = root.Link[opp(dir)]
    root.Link[opp(dir)] = save.Link[dir]
    save.Link[dir] = root
    return save
}

// adjust valance factors after double rotation
func adjustBalance(root *Node, dir, bal int) {
    n := root.Link[dir]
    nn := n.Link[opp(dir)]
    switch nn.Balance {
    case 0:
        root.Balance = 0
        n.Balance = 0
    case bal:
        root.Balance = -bal
        n.Balance = 0
    default:
        root.Balance = 0
        n.Balance = bal
    }
    nn.Balance = 0
}

func insertBalance(root *Node, dir int) *Node {
    n := root.Link[dir]
    bal := 2*dir - 1
    if n.Balance == bal {
        root.Balance = 0
        n.Balance = 0
        return single(root, opp(dir))
    }
    adjustBalance(root, dir, bal)
    return double(root, opp(dir))
}

func insertR(root *Node, data Key) (*Node, bool) {
    if root == nil {
        return &Node{Data: data}, false
    }
    dir := 0
    if root.Data.Less(data) {
        dir = 1
    }
    var done bool
    root.Link[dir], done = insertR(root.Link[dir], data)
    if done {
        return root, true
    }
    root.Balance += 2*dir - 1
    switch root.Balance {
    case 0:
        return root, true
    case 1, -1:
        return root, false
    }
    return insertBalance(root, dir), true
}

// Insert a node into the AVL tree.
// Data is inserted even if other data with the same key already exists.
func Insert(tree **Node, data Key) {
    *tree, _ = insertR(*tree, data)
}

func removeBalance(root *Node, dir int) (*Node, bool) {
    n := root.Link[opp(dir)]
    bal := 2*dir - 1
    switch n.Balance {
    case -bal:
        root.Balance = 0
        n.Balance = 0
        return single(root, dir), false
    case bal:
        adjustBalance(root, opp(dir), -bal)
        return double(root, dir), false
    }
    root.Balance = -bal
    n.Balance = bal
    return single(root, dir), true
}

func removeR(root *Node, data Key) (*Node, bool) {
    if root == nil {
        return nil, false
    }
    if root.Data.Eq(data) {
        switch {
        case root.Link[0] == nil:
            return root.Link[1], false
        case root.Link[1] == nil:
            return root.Link[0], false
        }
        heir := root.Link[0]
        for heir.Link[1] != nil {
            heir = heir.Link[1]
        }
        root.Data = heir.Data
        data = heir.Data
    }
    dir := 0
    if root.Data.Less(data) {
        dir = 1
    }
    var done bool
    root.Link[dir], done = removeR(root.Link[dir], data)
    if done {
        return root, true
    }
    root.Balance += 1 - 2*dir
    switch root.Balance {
    case 1, -1:
        return root, true
    case 0:
        return root, false
    }
    return removeBalance(root, dir)
}

// Remove a single item from an AVL tree.
// If key does not exist, function has no effect.
func Remove(tree **Node, data Key) {
    *tree, _ = removeR(*tree, data)
}


with Ada.Text_IO; use Ada.Text_IO;
with Ada.Numerics.Generic_Elementary_Functions;
with Ada.Numerics.Discrete_Random;
procedure Avglen is
   package IIO is new Ada.Text_IO.Integer_IO (Positive); use IIO;
   package LFIO is new Ada.Text_IO.Float_IO (Long_Float); use LFIO;
   subtype FactN is Natural range 0..20;
   TESTS : constant Natural := 1_000_000;

   function Factorial (N : FactN) return Long_Float is
      Result : Long_Float := 1.0;
   begin
      for I in 2..N loop Result := Result * Long_Float(I); end loop;
      return Result;
   end Factorial;

   function Analytical (N : FactN) return Long_Float is
      Sum : Long_Float := 0.0;
   begin
      for I in 1..N loop
         Sum := Sum + Factorial(N) / Factorial(N - I) / Long_Float(N)**I;
      end loop;
      return Sum;
   end Analytical;

   function Experimental (N : FactN) return Long_Float is
      subtype RandInt is Natural range 1..N;
      package Random is new Ada.Numerics.Discrete_Random(RandInt);
      seed : Random.Generator;
      Num : RandInt;
      count : Natural := 0;
      bits : array(RandInt'Range) of Boolean;
   begin
      Random.Reset(seed);
      for run in 1..TESTS loop
         bits := (others  => false);
         for I in RandInt'Range loop
            Num := Random.Random(seed); exit when bits(Num);
            bits(Num) := True; count := count + 1;
         end loop;
      end loop;
      return Long_Float(count)/Long_Float(TESTS);
   end Experimental;

   A, E, err : Long_Float;
begin
   Put_Line(" N  avg    calc   %diff");
   for I in 1..20 loop
      A := Analytical(I);  E := Experimental(I); err := abs(E-A)/A*100.0;
      Put(I, Width=>2); Put(E ,Aft=>4, exp=>0); Put(A, Aft=>4, exp=>0);
      Put(err, Fore=>3, Aft=>3, exp=>0); New_line;
   end loop;
end Avglen;


      @% = &2040A
      MAX_N = 20
      TIMES = 1000000

      FOR n = 1 TO MAX_N
        avg = FNtest(n, TIMES)
        theory = FNanalytical(n)
        diff = (avg / theory - 1) * 100
        PRINT STR$(n), avg, theory, diff "%"
      NEXT
      END

      DEF FNanalytical(n)
      LOCAL i, s
      FOR i = 1 TO n
        s += FNfactorial(n) / n^i / FNfactorial(n-i)
      NEXT
      = s

      DEF FNtest(n, times)
      LOCAL i, b, c, x
      FOR i = 1 TO times
        x = 1 : b = 0
        WHILE (b AND x) = 0
          c += 1
          b OR= x
          x = 1 << (RND(n) - 1)
        ENDWHILE
      NEXT
      = c / times

      DEF FNfactorial(n)
      IF n=1 OR n=0 THEN =1 ELSE = n * FNfactorial(n-1)


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

foldTree :: Ord a => [a] -> Tree a
foldTree = foldr insert Leaf

height :: Tree a -> Int
height Leaf = -1
height (Node h _ _ _) = h

depth :: Tree a -> Tree a -> Int
depth a b = succ (max (height a) (height b))

insert :: Ord a => a -> Tree a -> Tree a
insert v Leaf = Node 1 Leaf v Leaf
insert v t@(Node n left v_ right)
  | v_ < v = rotate $ Node n left v_ (insert v right)
  | v_ > v = rotate $ Node n (insert v left) v_ right
  | otherwise = t

max_ :: Ord a => Tree a -> Maybe a
max_ Leaf = Nothing
max_ (Node _ _ v right) =
  case right of
    Leaf -> Just v
    _ -> max_ right

delete :: Ord a => a -> Tree a -> Tree a
delete _ Leaf = Leaf
delete x (Node h left v right)
  | x == v =
    maybe left (rotate . (Node h left <*> (`delete` right))) (max_ right)
  | x > v = rotate $ Node h left v (delete x right)
  | x < v = rotate $ Node h (delete x left) v right

rotate :: Tree a -> Tree a
rotate Leaf = Leaf
rotate (Node h (Node lh ll lv lr) v r)
  -- Left Left.
  | lh - height r > 1 && height ll - height lr > 0 =
    Node lh ll lv (Node (depth r lr) lr v r)
rotate (Node h l v (Node rh rl rv rr))
  -- Right Right.
  | rh - height l > 1 && height rr - height rl > 0 =
    Node rh (Node (depth l rl) l v rl) rv rr
rotate (Node h (Node lh ll lv (Node rh rl rv rr)) v r)
  -- Left Right.
  | lh - height r > 1 =
    Node h (Node (rh + 1) (Node (lh - 1) ll lv rl) rv rr) v r
rotate (Node h l v (Node rh (Node lh ll lv lr) rv rr))
  -- Right Left.
  | rh - height l > 1 =
    Node h l v (Node (lh + 1) ll lv (Node (rh - 1) lr rv rr))
rotate (Node h l v r) =
  -- Re-weighting.
  let (l_, r_) = (rotate l, rotate r)
   in Node (depth l_ r_) l_ v r_

draw :: Show a => Tree a -> String
draw t = '\n' : draw_ t 0 <> "\n"
  where
    draw_ Leaf _ = []
    draw_ (Node h l v r) d = draw_ r (d + 1) <> node <> draw_ l (d + 1)
      where
        node = padding d <> show (v, h) <> "\n"
        padding n = replicate (n * 4) ' '

main :: IO ()
main = putStr $ draw $ foldTree [1 .. 31]


V doors = [0B] * 100
L(i) 100
   L(j) (i .< 100).step(i + 1)
      doors[j] = !doors[j]
   print(‘Door ’(i + 1)‘: ’(I doors[i] {‘open’} E ‘close’))


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

#define MAX_N 20
#define TIMES 1000000

double factorial(int n) {
	double f = 1;
	int i;
	for (i = 1; i <= n; i++) f *= i;
	return f;
}

double expected(int n) {
	double sum = 0;
	int i;
	for (i = 1; i <= n; i++)
		sum += factorial(n) / pow(n, i) / factorial(n - i);
	return sum;
}

int randint(int n) {
	int r, rmax = RAND_MAX / n * n;
	while ((r = rand()) >= rmax);
	return r / (RAND_MAX / n);
}

int test(int n, int times) {
	int i, count = 0;
	for (i = 0; i < times; i++) {
		int x = 1, bits = 0;
		while (!(bits & x)) {
			count++;
			bits |= x;
			x = 1 << randint(n);
		}
	}
	return count;
}

int main(void) {
	srand(time(0));
	puts(" n\tavg\texp.\tdiff\n-------------------------------");

	int n;
	for (n = 1; n <= MAX_N; n++) {
		int cnt = test(n, TIMES);
		double avg = (double)cnt / TIMES;
		double theory = expected(n);
		double diff = (avg / theory - 1) * 100;
		printf("%2d %8.4f %8.4f %6.3f%%\n", n, avg, theory, diff);
	}
	return 0;
}


insert=: {{
  X=.1 {::2{.x,x  NB. middle element of x (don't fail on empty x)
  Y=.1 {::2{.y,y  NB. middle element of y (don't fail on empty y)
  select.#y
    case.0 do.x   NB. y is an empty node
    case.1 do.    NB. y is a leaf node
      select.*Y-X
        case._1 do.a:,y;<x
        case. 0 do.y
        case. 1 do.x;y;a:
      end.
    case.3 do.   NB. y is a parent node
      select.*Y-X
        case._1 do.balance (}:y),<x insert 2{::y
        case. 0 do.y
        case. 1 do.balance (x insert 0{::y);}.y
      end.
  end.
}}

delete=: {{
  select.#y
    case.0 do.y
    case.1 do.y-.x
    case.3 do.
      select.*(1{::y)-x
        case._1 do.balance (}:y),<x delete 2{::y
        case. 0 do.balance (0{::y) insert 2{::y
        case. 1 do.balance (x delete 0{::y);}.y
      end.
    end.
}}

lookup=: {{
  select.#y
    case.0 do.y
    case.1 do.if.x=y do.y else.'' end.
    case.3 do.
      select.*(1{::y)-x
        case._1 do.x lookup 2{::y
        case. 0 do.y
        case. 1 do.x lookup 0{::y
      end.
  end.
}}

clean=: {{
  's0 x s2'=. #every y
  if.*/0=s0,s2 do. 1{:: y NB. degenerate to leaf
  else. y end.
}}

balance=: {{
  if. 2>#y do. y return.end. NB. leaf or empty
  's0 x s2'=. ,#every y
  if. */0=s0,s2 do. 1{:: y return.end. NB. degenerate to leaf
  'l0 x l2'=. L.every y
  if. 2>|l2-l0 do. y return.end. NB. adequately balanced
  if. l2>l0 do.
    'l20 x l22'=. L.every 2{::y
    if. l22 >: l20 do. rotLeft y
    else. rotRightLeft y end.
  else.
    'l00 x l02'=. L.every 0{::y
    if. l00 >: l02 do. rotRight y
    else. rotLeftRight y end.
  end.
}}

rotLeft=: {{
  't0 t1 t2'=. y
  't20 t21 t22'=. t2
  (clean t0;t1;<t20);t21;<t22
}}

rotRight=: {{
  't0 t1 t2'=. y
  't00 t01 t02'=. t0
  t00;t01;<clean t02;t1;<t2
}}

rotRightLeft=: {{
  't0 t1 t2'=. y
  rotLeft t0;t1;<rotRight t2
}}

rotLeftRight=: {{
  't0 t1 t2'=. y
  rotRight (rotLeft t0);t1;<t2
}}


*        100 doors                 13/08/2015
HUNDOOR  CSECT
         USING  HUNDOOR,R12
         LR     R12,R15
         LA     R6,0
         LA     R8,1               step 1
         LA     R9,100
LOOPI    BXH    R6,R8,ELOOPI       do ipass=1 to 100 (R6)
         LR     R7,R6
         SR     R7,R6
         LR     R10,R6             step ipass
         LA     R11,100
LOOPJ    BXH    R7,R10,ELOOPJ      do idoor=ipass to 100 by ipass (R7)
         LA     R5,DOORS-1
         AR     R5,R7
         XI     0(R5),X'01'        doors(idoor)=not(doors(idoor))
NEXTJ    B      LOOPJ
ELOOPJ   B      LOOPI
ELOOPI   LA     R10,BUFFER         R10 address of the buffer
         LA     R5,DOORS           R5 address of doors item
         LA     R6,1               idoor=1 (R6)
         LA     R9,100             loop counter
LOOPN    CLI    0(R5),X'01'        if doors(idoor)=1
         BNE    NEXTN
         XDECO  R6,XDEC            idoor to decimal
         MVC    0(4,R10),XDEC+8    move decimal to buffer
         LA     R10,4(R10)
NEXTN	 LA     R6,1(R6)           idoor=idoor+1
         LA     R5,1(R5)
         BCT    R9,LOOPN           loop
ELOOPN   XPRNT  BUFFER,80
RETURN   XR     R15,R15
         BR     R14
DOORS    DC     100X'00'
BUFFER   DC     CL80' '
XDEC     DS     CL12
         YREGS
         END    HUNDOOR


public class AverageLoopLength {
	private static int N = 100000;

	private static double analytical(int n) {
		double[] factorial = new double[n + 1];
		double[] powers = new double[n + 1];
		powers[0] = 1.0;
		factorial[0] = 1.0;
		for (int i = 1; i <= n; i++) {
			factorial[i] = factorial[i - 1] * i;
			powers[i] = powers[i - 1] * n;
		}
		double sum = 0;

		for (int i = 1; i <= n; i++) {
			sum += factorial[n] / factorial[n - i] / powers[i];
		}
		return sum;
	}

	private static double average(int n) {
		Random rnd = new Random();
		double sum = 0.0;
		for (int a = 0; a < N; a++) {
			int[] random = new int[n];
			for (int i = 0; i < n; i++) {
				random[i] = rnd.Next(n);
			}
			var seen = new HashSet<double>(n);
			int current = 0;
			int length = 0;
			while (seen.Add(current)) {
				length++;
				current = random[current];
			}
			sum += length;
		}
		return sum / N;
	}

	public static void Main(string[] args) {
	Console.WriteLine(" N    average    analytical    (error)");
	Console.WriteLine("===  =========  ============  =========");
		for (int i = 1; i <= 20; i++) {
			var average = AverageLoopLength.average(i);
			var analytical = AverageLoopLength.analytical(i);
			Console.WriteLine("{0,3} {1,10:N4} {2,13:N4}  {3,8:N2}%", i, average, analytical, (analytical - average) / analytical * 100);
		}
	}
}


public class AVLtree {

    private Node root;

    private static class Node {
        private int key;
        private int balance;
        private int height;
        private Node left;
        private Node right;
        private Node parent;

        Node(int key, Node parent) {
            this.key = key;
            this.parent = parent;
        }
    }

    public boolean insert(int key) {
        if (root == null) {
            root = new Node(key, null);
            return true;
        }

        Node n = root;
        while (true) {
            if (n.key == key)
                return false;

            Node parent = n;

            boolean goLeft = n.key > key;
            n = goLeft ? n.left : n.right;

            if (n == null) {
                if (goLeft) {
                    parent.left = new Node(key, parent);
                } else {
                    parent.right = new Node(key, parent);
                }
                rebalance(parent);
                break;
            }
        }
        return true;
    }

    private void delete(Node node) {
        if (node.left == null && node.right == null) {
            if (node.parent == null) {
                root = null;
            } else {
                Node parent = node.parent;
                if (parent.left == node) {
                    parent.left = null;
                } else {
                    parent.right = null;
                }
                rebalance(parent);
            }
            return;
        }

        if (node.left != null) {
            Node child = node.left;
            while (child.right != null) child = child.right;
            node.key = child.key;
            delete(child);
        } else {
            Node child = node.right;
            while (child.left != null) child = child.left;
            node.key = child.key;
            delete(child);
        }
    }

    public void delete(int delKey) {
        if (root == null)
            return;

        Node child = root;
        while (child != null) {
            Node node = child;
            child = delKey >= node.key ? node.right : node.left;
            if (delKey == node.key) {
                delete(node);
                return;
            }
        }
    }

    private void rebalance(Node n) {
        setBalance(n);

        if (n.balance == -2) {
            if (height(n.left.left) >= height(n.left.right))
                n = rotateRight(n);
            else
                n = rotateLeftThenRight(n);

        } else if (n.balance == 2) {
            if (height(n.right.right) >= height(n.right.left))
                n = rotateLeft(n);
            else
                n = rotateRightThenLeft(n);
        }

        if (n.parent != null) {
            rebalance(n.parent);
        } else {
            root = n;
        }
    }

    private Node rotateLeft(Node a) {

        Node b = a.right;
        b.parent = a.parent;

        a.right = b.left;

        if (a.right != null)
            a.right.parent = a;

        b.left = a;
        a.parent = b;

        if (b.parent != null) {
            if (b.parent.right == a) {
                b.parent.right = b;
            } else {
                b.parent.left = b;
            }
        }

        setBalance(a, b);

        return b;
    }

    private Node rotateRight(Node a) {

        Node b = a.left;
        b.parent = a.parent;

        a.left = b.right;

        if (a.left != null)
            a.left.parent = a;

        b.right = a;
        a.parent = b;

        if (b.parent != null) {
            if (b.parent.right == a) {
                b.parent.right = b;
            } else {
                b.parent.left = b;
            }
        }

        setBalance(a, b);

        return b;
    }

    private Node rotateLeftThenRight(Node n) {
        n.left = rotateLeft(n.left);
        return rotateRight(n);
    }

    private Node rotateRightThenLeft(Node n) {
        n.right = rotateRight(n.right);
        return rotateLeft(n);
    }

    private int height(Node n) {
        if (n == null)
            return -1;
        return n.height;
    }

    private void setBalance(Node... nodes) {
        for (Node n : nodes) {
            reheight(n);
            n.balance = height(n.right) - height(n.left);
        }
    }

    public void printBalance() {
        printBalance(root);
    }

    private void printBalance(Node n) {
        if (n != null) {
            printBalance(n.left);
            System.out.printf("%s ", n.balance);
            printBalance(n.right);
        }
    }

    private void reheight(Node node) {
        if (node != null) {
            node.height = 1 + Math.max(height(node.left), height(node.right));
        }
    }

    public static void main(String[] args) {
        AVLtree tree = new AVLtree();

        System.out.println("Inserting values 1 to 10");
        for (int i = 1; i < 10; i++)
            tree.insert(i);

        System.out.print("Printing balance: ");
        tree.printBalance();
    }
}


@echo off
set doors=%@repeat[C,100]
do step = 1 to 100
  do door = %step to 100 by %step
    set doors=%@left[%@eval[%door-1],%doors]%@if[%@instr[%@eval[%door-1],1,%doors]==C,O,C]%@right[%@eval[100-%door],%doors]
  enddo
enddo


#include <random>
#include <vector>
#include <iostream>

#define MAX_N 20
#define TIMES 1000000

/**
 * Used to generate a uniform random distribution
 */
static std::random_device rd;  //Will be used to obtain a seed for the random number engine
static std::mt19937 gen(rd()); //Standard mersenne_twister_engine seeded with rd()
static std::uniform_int_distribution<> dis;

int randint(int n) {
    int r, rmax = RAND_MAX / n * n;
    dis=std::uniform_int_distribution(0,rmax) ;
    r = dis(gen);
    return r / (RAND_MAX / n);
}

unsigned long factorial(size_t n) {
    //Factorial using dynamic programming to memoize the values.
    static std::vector<unsigned long>factorials{1,1,2};
	for (;factorials.size() <= n;)
	    factorials.push_back(factorials.back()*factorials.size());
	return factorials[n];
}

long double expected(size_t n) {
    long double sum = 0;
    for (size_t i = 1; i <= n; i++)
        sum += factorial(n) / pow(n, i) / factorial(n - i);
    return sum;
}

int test(int n, int times) {
    int i, count = 0;
    for (i = 0; i < times; i++) {
        unsigned int x = 1, bits = 0;
        while (!(bits & x)) {
            count++;
            bits |= x;
            x = static_cast<unsigned int>(1 << randint(n));
        }
    }
    return count;
}

int main() {
    puts(" n\tavg\texp.\tdiff\n-------------------------------");

    int n;
    for (n = 1; n <= MAX_N; n++) {
        int cnt = test(n, TIMES);
        long double avg = (double)cnt / TIMES;
        long double theory = expected(static_cast<size_t>(n));
        long double diff = (avg / theory - 1) * 100;
        printf("%2d %8.4f %8.4f %6.3f%%\n", n, static_cast<double>(avg), static_cast<double>(theory), static_cast<double>(diff));
    }
    return 0;
}


F is_prime(n)
   I n < 2
      R 0B
   L(i) 2 .. Int(sqrt(n))
      I n % i == 0
         R 0B
   R 1B

F get_pfct(=n)
   V i = 2
   [Int] factors
   L i * i <= n
      I n % i
         i++
      E
         n I/= i
         factors.append(i)
   I n > 1
      factors.append(n)
   R factors.len

[Int] pool

L(each) 0..120
   pool.append(get_pfct(each))

[Int] r
L(each) pool
   I is_prime(each)
      r.append(L.index)

print(r.map(String).join(‘,’))


function tree(less, val, more) {
  return {
    depth: 1+Math.max(less.depth, more.depth),
    less: less,
    val: val,
    more: more,
  };
}

function node(val) {
  return tree({depth: 0}, val, {depth: 0});
}

function insert(x,y) {
  if (0 == y.depth) return x;
  if (0 == x.depth) return y;
  if (1 == x.depth && 1 == y.depth) {
    switch (Math.sign(y.val)-x.val) {
      case -1: return tree(y, x.val, {depth: 0});
      case 0: return y;
      case 1: return tree(x, y.val, {depth: 0});
    }
  }
  switch (Math.sign(y.val-x.val)) {
    case -1: return balance(insert(x.less, y), x.val, x.more);
    case 0: return balance(insert(x.less, y.less), x.val, insert(x.more, y.more));
    case 1: return balance(x.less. x.val, insert(x.more, y));
  }
}

function balance(less,val,more) {
  if (2 > Math.abs(less.depth-more.depth))
    return tree(less,val,more);
  if (more.depth > less.depth) {
    if (more.more.depth >= more.less.depth) {
      // 'more' was heavy
      return moreHeavy(less, val, more);
    } else {
      return moreHeavy(less,val,lessHeavy(more.less, more.val, more.more));
    }
  } else {
    if(less.less.depth >= less.more.depth) {
      return lessHeavy(less, val, more);
    } else {
      return lessHeavy(moreHeavy(less.less, less.val, less.more), val, more);
    }
  }
}

function moreHeavy(less,val,more) {
  return tree(tree(less,val,more.less), more.val, more.more)
}

function lessHeavy(less,val,more) {
  return tree(less.less, less.val, tree(less.more, val, more));
}

function remove(val, y) {
  switch (y.depth) {
    case 0: return y;
    case 1:
      if (val == y.val) {
        return y.less;
      } else {
        return y;
      }
    default:
      switch (Math.sign(y.val - val)) {
        case -1: return balance(y.less, y.val, remove(val, y.more));
        case  0: return insert(y.less, y.more);
        case  1: return balance(remove(val, y.less), y.val, y.more)
      }
  }
}

function lookup(val, y) {
  switch (y.depth) {
    case 0: return y;
    case 1: if (val == y.val) {
      return y;
    } else {
      return {depth: 0};
    }
    default:
      switch (Math.sign(y.val-val)) {
        case -1: return lookup(val, y.more);
        case  0: return y;
        case  1: return lookup(val, y.less);
      }
  }
}


; 100 DOORS in  6502 assembly language for: http://www.6502asm.com/beta/index.html
; Written for the original MOS Technology, Inc. NMOS version of the 6502, but should work with any version.
; Based on BASIC QB64 unoptimized version: http://rosettacode.org/wiki/100_doors#BASIC
;
; Notes:
;    Doors array[1..100] is at $0201..$0264. On the specified emulator, this is in video memory, so tbe results will
; be directly shown as pixels in the display.
;    $0200 (door 0) is cleared for display purposes but is not involved in the open/close loops.
;    Y register holds Stride
;    X register holds Index
;    Zero Page address $01 used to add Stride to Index (via A) because there's no add-to-X or add-Y-to-A instruction.

  ; First, zero door array
    LDA #00
    LDX #100
Z_LOOP:
    STA 200,X
    DEX
    BNE Z_LOOP
    STA 200,X

  ; Now do doors repeated open/close
    LDY #01        ; Initial value of Stride
S_LOOP:
    CPY #101
    BCS S_DONE
    TYA            ; Initial value of Index
I_LOOP:
    CMP #101
    BCS I_DONE
    TAX            ; Use as Door array index
    INC $200,X     ; Toggle bit 0 to reverse state of door
    STY 01         ; Add stride (Y) to index (X, via A)
    ADC 01
    BCC I_LOOP
I_DONE:
    INY
    BNE S_LOOP
S_DONE:

  ; Finally, format array values for output: 0 for closed, 1 for open
    LDX #100
C_LOOP:
    LDA $200,X
    AND #$01
    STA $200,X
    DEX
    BNE C_LOOP


(ns cyclelengths
  (:gen-class))

(defn factorial [n]
  " n! "
  (apply *' (range 1 (inc n))))             ; Use *' (vs. *) to allow arbitrary length arithmetic

(defn pow [n i]
  " n^i"
  (apply *' (repeat i n)))

(defn analytical [n]
  " Analytical Computation "
  (->>(range 1 (inc n))
      (map #(/ (factorial n) (pow n %) (factorial (- n %)))) ;calc n %))
      (reduce + 0)))

;; Number of random times to test each n
(def TIMES 1000000)

(defn single-test-cycle-length [n]
  " Single random test of cycle length "
  (loop [count 0
         bits 0
         x 1]
    (if (zero? (bit-and x bits))
      (recur (inc count) (bit-or bits x) (bit-shift-left 1 (rand-int n)))
        count)))

(defn avg-cycle-length [n times]
  " Average results of single tests of cycle lengths "
  (/
   (reduce +
           (for [i (range times)]
             (single-test-cycle-length n)))
  times))

;; Show Results
(println "\tAvg\t\tExp\t\tDiff")
(doseq [q (range 1 21)
        :let [anal (double (analytical q))
              avg (double (avg-cycle-length q TIMES))
              diff (Math/abs (* 100 (- 1 (/ avg anal))))]]
  (println (format "%3d\t%.4f\t%.4f\t%.2f%%" q avg anal diff)))


import std.stdio, std.random, std.math, std.algorithm, std.range, std.format;

real analytical(in int n) pure nothrow @safe /*@nogc*/ {
    enum aux = (int k) => reduce!q{a * b}(1.0L, iota(n - k + 1, n + 1));
    return iota(1, n + 1)
           .map!(k => (aux(k) * k ^^ 2) / (real(n) ^^ (k + 1)))
           .sum;
}

size_t loopLength(size_t maxN)(in int size, ref Xorshift rng) {
    __gshared static bool[maxN + 1] seen;
    seen[0 .. size + 1] = false;
    int current = 1;
    size_t steps = 0;
    while (!seen[current]) {
        seen[current] = true;
        current = uniform(1, size + 1, rng);
        steps++;
    }
    return steps;
}

void main() {
    enum maxN  = 40;
    enum nTrials = 300_000;
    auto rng = Xorshift(unpredictableSeed);
    writeln(" n    average    analytical     (error)");
    writeln("===  =========  ============  ==========");

    foreach (immutable n; 1 .. maxN + 1) {
        long total = 0;
        foreach (immutable _; 0 .. nTrials)
            total += loopLength!maxN(n, rng);
        immutable average = total / real(nTrials);
        immutable an = n.analytical;
        immutable percentError = abs(an - average) / an * 100;
        immutable errorS = format("%2.4f", percentError);
        writefln("%3d  %9.5f  %12.5f  (%7s%%)",
                 n, average, an, errorS);
    }
}


	;;; 	Show attractive numbers up to 120
MAX:	equ	120	; can be up to 255 (8 bit math is used)
	;;;	CP/M calls
puts:	equ	9
bdos:	equ	5
	org	100h
	;;;	-- Zero memory ------------------------------------------------
	lxi	b,fctrs	; page 2
	mvi	e,2	; zero out two pages
	xra	a
	mov	d,a
zloop:	stax	b
	inx	b
	dcr	d
	jnz	zloop
	dcr	e
	jnz	zloop
	;;; 	-- Generate primes --------------------------------------------
	lxi	h,plist	; pointer to beginning of primes list
	mvi	e,2	; first prime is 2
pstore:	mov	m,e	; begin prime list
pcand:	inr	e	; next candidate
	jz	factor	; if 0, we've rolled over, so we're done
	mov	l,d	; beginning of primes list (D=0 here)
	mov	c,m	; C = prime to test against
ptest:	mov	a,e
ploop:	sub	c	; test by repeated subtraction
	jc	notdiv	; if carry, not divisible
	jz	pcand	; if zero, next candidate
	jmp	ploop
notdiv:	inx	h	; get next prime
	mov	c,m
	mov	a,c	; is it zero?
	ora	a
	jnz	ptest	; if not, test against next prime
	jmp	pstore	; otherwise, add E to the list of primes
	;;;	-- Count factors ----------------------------------------------
factor:	mvi	c,2	; start with two
fnum:	mvi	a,MAX	; is candidate beyond maximum?
	cmp	c
	jc	output	; then stop
	mvi	d,0	; D = number of factors of C
	mov	l,d	; L = first prime
	mov	e,c	; E = number we're factorizing
fprim:	mvi	h,ppage	; H = current prime
	mov	h,m
ftest:	mvi	b,0
	mov	a,e
	cpi	1	; If one, we've counted all the factors
	jz	nxtfac
fdiv:	sub	h
	jz	divi
	jc	ndivi
	inr	b
	jmp	fdiv
divi:	inr	d	; we found a factor
	inr	b
	mov	e,b	; we've removed it, try again
	jmp	ftest
ndivi:	inr	l	; not divisible, try next prime
	jmp	fprim
nxtfac:	mov	a,d	; store amount of factors
	mvi	b,fcpage
	stax	b
	inr	c	; do next number
	jmp	fnum
	;;;	-- Check which numbers are attractive and print them ----------
output:	lxi	b,fctrs+2	; start with two
	mvi	h,ppage	; H = page of primes
onum:	mvi	a,MAX	; is candidate beyond maximum?
	cmp	c
	rc		; then stop
	ldax	b	; get amount of factors
	mvi	l,0	; start at beginning of prime list
chprm:	cmp 	m	; check against current prime
	jz	print	; if it's prime, then print the number
	inr	l	; otherwise, check next prime
	jp	chprm
next:	inr	c	; check next number
	jmp	onum
print:	push	b	; keep registers
	push	h
	mov	a,c	; print number
	call	printa
	pop	h	; restore registers
	pop	b
	jmp	next
	;;;	Subroutine: print the number in A
printa:	lxi	d,num	; DE = string
	mvi	b,10	; divisor
digit:	mvi	c,-1	; C = quotient
divlp:	inr	c
	sub	b
	jnc	divlp
	adi	'0'+10	; make digit
	dcx	d	; store digit
	stax	d
	mov	a,c	; again with new quotient
	ora	a	; is it zero?
	jnz	digit	; if not, do next digit
	mvi	c,puts	; CP/M print string (in DE)
	jmp	bdos
	db	'000'	; placeholder for number
num:	db	' $'
fcpage:	equ	2	; factors in page 2
ppage:	equ	3	; primes in page 3
fctrs:	equ	256*fcpage
plist:	equ	256*ppage


INCLUDE "H6:SIEVE.ACT"

BYTE FUNC IsAttractive(BYTE n BYTE ARRAY primes)
  BYTE count,f

  IF n<=1 THEN
    RETURN (0)
  ELSEIF primes(n) THEN
    RETURN (0)
  FI

  count=0 f=2
  DO
    IF n MOD f=0 THEN
      count==+1
      n==/f
      IF n=1 THEN
        EXIT
      ELSEIF primes(n) THEN
        f=n
      FI
    ELSEIF f>=3 THEN
      f==+2
    ELSE
      f=3
    FI
  OD

  IF primes(count) THEN
    RETURN (1)
  FI
RETURN (0)

PROC Main()
  DEFINE MAX="120"
  BYTE ARRAY primes(MAX+1)
  BYTE i

  Put(125) PutE() ;clear the screen
  Sieve(primes,MAX+1)
  PrintF("Attractive numbers in range 1..%B:%E",MAX)
  FOR i=1 TO MAX
  DO
    IF IsAttractive(i,primes) THEN
      PrintF("%B ",i)
    FI
  OD
RETURN


with Ada.Text_IO;

procedure Attractive_Numbers is

   function Is_Prime (N : in Natural) return Boolean is
      D : Natural := 5;
   begin
      if N < 2       then  return False;  end if;
      if N mod 2 = 0 then  return N = 2;  end if;
      if N mod 3 = 0 then  return N = 3;  end if;

      while D * D <= N loop
         if N mod D = 0 then  return False;  end if;
         D := D + 2;
         if N mod D = 0 then  return False;  end if;
         D := D + 4;
      end loop;
      return True;
   end Is_Prime;

   function Count_Prime_Factors (N : in Natural) return Natural is
      NC    : Natural := N;
      Count : Natural := 0;
      F     : Natural := 2;
   begin
      if NC = 1        then  return 0;  end if;
      if Is_Prime (NC) then  return 1;  end if;
      loop
         if NC mod F = 0 then
            Count := Count + 1;
            NC := NC / F;

            if NC = 1 then
               return Count;
            end if;

            if Is_Prime (NC) then F := NC; end if;
         elsif F >= 3 then
            F := F + 2;
         else
            F := 3;
         end if;
      end loop;
   end Count_Prime_Factors;

   procedure Show_Attractive (Max : in Natural)
   is
      use Ada.Text_IO;
      package Integer_IO is
         new Ada.Text_IO.Integer_IO (Integer);
      N     : Natural;
      Count : Natural := 0;
   begin
      Put_Line ("The attractive numbers up to and including " & Max'Image & " are:");
      for I in 1 .. Max loop
         N := Count_Prime_Factors (I);
         if Is_Prime (N) then
            Integer_IO.Put (I, Width => 5);
            Count := Count + 1;
            if Count mod 20 = 0 then New_Line; end if;
         end if;
      end loop;
   end Show_Attractive;

begin
   Show_Attractive (Max => 120);
end Attractive_Numbers;


module AVLTrees

import Base.print
export AVLNode, AVLTree, insert, deletekey, deletevalue, findnodebykey, findnodebyvalue, allnodes

@enum Direction LEFT RIGHT
avlhash(x) = Int32(hash(x) & 0xfffffff)
const MIDHASH = Int32(div(0xfffffff, 2))

mutable struct AVLNode{T}
    value::T
    key::Int32
    balance::Int32
    left::Union{AVLNode, Nothing}
    right::Union{AVLNode, Nothing}
    parent::Union{AVLNode, Nothing}
end
AVLNode(v::T, b, l, r, p) where T <: Real = AVLNode(v, avlhash(v), Int32(b), l, r, p)
AVLNode(v::T, h, b::Int64, l, r, p) where T <: Real = AVLNode(v, h, Int32(b), l, r, p)
AVLNode(v::T) where T <: Real = AVLNode(v, avlhash(v), Int32(0), nothing, nothing, nothing)

AVLTree(typ::Type) = AVLNode(typ(0), MIDHASH, Int32(0), nothing, nothing, nothing)
const MaybeAVL = Union{AVLNode, Nothing}

height(node::MaybeAVL) = (node == nothing) ? 0 : 1 + max(height(node.right), height(node.left))

function insert(node, value)
    if node == nothing
        node = AVLNode(value)
        return true
    end
    key, n, parent::MaybeAVL = avlhash(value), node, nothing
    while true
        if n.key == key
            return false
        end
        parent = n
        ngreater = n.key > key
        n = ngreater ? n.left : n.right
        if n == nothing
            if ngreater
                parent.left = AVLNode(value, key, 0, nothing, nothing, parent)
            else
                parent.right = AVLNode(value, key, 0, nothing, nothing, parent)
            end
            rebalance(parent)
            break
        end
    end
    return true
end

function deletekey(node, delkey)
    node == nothing && return nothing
    n, parent = MaybeAVL(node), MaybeAVL(node)
    delnode, child = MaybeAVL(nothing), MaybeAVL(node)
    while child != nothing
        parent, n = n, child
        child = delkey >= n.key ? n.right : n.left
        if delkey == n.key
            delnode = n
        end
    end
    if delnode != nothing
        delnode.key = n.key
        delnode.value = n.value
        child = (n.left != nothing) ? n.left : n.right
        if node.key == delkey
            root = child
        else
            if parent.left == n
                parent.left = child
            else
                parent.right = child
            end
            rebalance(parent)
        end
    end
end

deletevalue(node, val) = deletekey(node, avlhash(val))

function rebalance(node::MaybeAVL)
    node == nothing && return nothing
    setbalance(node)
    if node.balance < -1
        if height(node.left.left) >= height(node.left.right)
            node = rotate(node, RIGHT)
        else
            node = rotatetwice(node, LEFT, RIGHT)
        end
    elseif node.balance > 1
        if node.right != nothing && height(node.right.right) >= height(node.right.left)
            node = rotate(node, LEFT)
        else
            node = rotatetwice(node, RIGHT, LEFT)
        end
    end
    if node != nothing && node.parent != nothing
        rebalance(node.parent)
    end
end

function rotate(a, direction)
    (a == nothing || a.parent == nothing) && return nothing
    b = direction == LEFT ? a.right : a.left
    b == nothing && return
    b.parent = a.parent
    if direction == LEFT
        a.right = b.left
    else
        a.left  = b.right
    end
    if a.right != nothing
        a.right.parent = a
    end
    if direction == LEFT
        b.left = a
    else
        b.right = a
    end
    a.parent = b
    if b.parent != nothing
        if b.parent.right == a
            b.parent.right = b
        else
            b.parent.left = b
        end
    end
    setbalance([a, b])
    return b
end

function rotatetwice(n, dir1, dir2)
    n.left = rotate(n.left, dir1)
    rotate(n, dir2)
end

setbalance(n::AVLNode) = begin n.balance = height(n.right) - height(n.left) end
setbalance(n::Nothing) = 0
setbalance(nodes::Vector) = for n in nodes setbalance(n) end

function findnodebykey(node, key)
    result::MaybeAVL = node == nothing ? nothing : node.key == key ? node :
        node.left != nothing && (n = findbykey(n, key) != nothing) ? n :
        node.right != nothing ? findbykey(node.right, key) : nothing
    return result
end
findnodebyvalue(node, val) = findnodebykey(node, avlhash(v))

function allnodes(node)
    result = AVLNode[]
    if node != nothing
        append!(result, allnodes(node.left))
        if node.key != MIDHASH
            push!(result, node)
        end
        append!(result, node.right)
    end
    return result
end

function Base.print(io::IO, n::MaybeAVL)
    if n != nothing
        n.left != nothing && print(io, n.left)
        print(io, n.key == MIDHASH ? "<ROOT> " : "<$(n.key):$(n.value):$(n.balance)> ")
        n.right != nothing && print(io, n.right)
    end
end

end # module

using .AVLTrees

const tree = AVLTree(Int)

println("Inserting 10 values.")
foreach(x -> insert(tree, x), rand(collect(1:80), 10))
println("Printing tree after insertion: ")
println(tree)


*-----------------------------------------------------------
* Title      : 100Doors.X68
* Written by : G. A. Tippery
* Date       : 2014-01-17
* Description: Solves "100 Doors" problem, see: http://rosettacode.org/wiki/100_doors
* Notes      : Translated from C "Unoptimized" version, http://rosettacode.org/wiki/100_doors#unoptimized
*            : No optimizations done relative to C version; "for("-equivalent loops could be optimized.
*-----------------------------------------------------------

*
*   System-specific general console I/O macros (Sim68K, in this case)
*
PUTS    MACRO
    ** Print a null-terminated string w/o CRLF **
    ** Usage: PUTS stringaddress
    ** Returns with D0, A1 modified
        MOVEQ   #14,D0      ; task number 14 (display null string)
        LEA     \1,A1       ; address of string
        TRAP    #15         ; display it
        ENDM
*
PRINTN  MACRO
    ** Print decimal integer from number in register
    ** Usage: PRINTN register
    ** Returns with D0,D1 modified
        IFNC '\1','D1'      ;if some register other than D1
          MOVE.L \1,D1      ;put number to display in D1
        ENDC
        MOVE.B  #3,D0
        TRAP    #15         ;display number in D1
*
*   Generic constants
*
CR      EQU     13      ;ASCII Carriage Return
LF      EQU     10      ;ASCII Line Feed

*
*   Definitions specific to this program
*
*   Register usage:
*   D3 == pass (index)
*   D4 == door (index)
*   A2 == Doors array pointer
*
SIZE    EQU     100             ;Define a symbolic constant for # of doors

        ORG     $1000           ;Specify load address for program -- actual address system-specific
START:                          ; Execution starts here
        LEA     Doors,A2        ; make A2 point to Doors byte array
        MOVEQ   #0,D3
PassLoop:
        CMP     #SIZE,D3
        BCC     ExitPassLoop    ; Branch on Carry Clear - being used as Branch on Higher or Equal
        MOVE    D3,D4
DoorLoop:
        CMP     #SIZE,D4
        BCC     ExitDoorLoop
        NOT.B   0(A2,D4)
        ADD     D3,D4
        ADDQ    #1,D4
        BRA     DoorLoop
ExitDoorLoop:
        ADDQ    #1,D3
        BRA     PassLoop
ExitPassLoop:

* $28 = 40. bytes of code to this point. 32626 cycles so far.
*   At this point, the result exists as the 100 bytes starting at address Doors.
* To get output, we must use methods specific to the particular hardware, OS, or
* emulator system that the code is running on.  I use macros to "hide" some of the
* system-specific details; equivalent macros would be written for another system.

        MOVEQ   #0,D4
PrintLoop:
        CMP     #SIZE,D4
        BCC     ExitPrintLoop
        PUTS    DoorMsg1
        MOVE    D4,D1
        ADDQ    #1,D1           ; Convert index to 1-based instead of 0-based
        PRINTN  D1
        PUTS    DoorMsg2
        TST.B   0(A2,D4)        ; Is this door open (!= 0)?
        BNE     ItsOpen
        PUTS    DoorMsgC
        BRA     Next
ItsOpen:
        PUTS    DoorMsgO
Next:
        ADDQ    #1,D4
        BRA     PrintLoop
ExitPrintLoop:

*  What to do at end of program is also system-specific
        SIMHALT             ;Halt simulator
*
* $78 = 120. bytes of code to this point, but this will depend on how the I/O macros are actually written.
* Cycle count is nearly meaningless, as the I/O hardware and routines will dominate the timing.

*
*   Data memory usage
*
        ORG     $2000
Doors   DCB.B   SIZE,0      ;Reserve 100 bytes, prefilled with zeros

DoorMsg1 DC.B   'Door ',0
DoorMsg2 DC.B   ' is ',0
DoorMsgC DC.B   'closed',CR,LF,0
DoorMsgO DC.B   'open',CR,LF,0

        END     START       ;last line of source


program Average_loop_length;

{$APPTYPE CONSOLE}

uses
  System.SysUtils,
  System.Math;

const
  MAX_N = 20;
  TIMES = 1000000;

function Factorial(const n: Double): Double;
begin
  Result := 1;
  if n > 1 then
    Result := n * Factorial(n - 1);
end;

function Expected(const n: Integer): Double;
var
  i: Integer;
begin
  Result := 0;
  for i := 1 to n do
    Result := Result + (factorial(n) / Power(n, i) / factorial(n - i));
end;

function Test(const n, times: Integer): integer;
var
  i, x, bits: Integer;
begin
  Result := 0;
  for i := 0 to times - 1 do
  begin
    x := 1;
    bits := 0;
    while ((bits and x) = 0) do
    begin
      inc(Result);
      bits := bits or x;
      x := 1 shl random(n);
    end;
  end;
end;

var
  n, cnt: Integer;
  avg, theory, diff: Double;

begin
  Randomize;
  Writeln(#10' tavg'^I'exp.'^I'diff'#10'-------------------------------');

  for n := 1 to MAX_N do
  begin
    cnt := test(n, times);
    avg := cnt / times;
    theory := expected(n);
    diff := (avg / theory - 1) * 100;
    writeln(format('%2d %8.4f %8.4f %6.3f%%', [n, avg, theory, diff]));
  end;

  readln;
end.


BEGIN # find some attractive numbers - numbers whose prime factor counts are #
      #                                prime, n must be > 1                  #
    PR read "primes.incl.a68" PR
    # find the attractive numbers                                            #
    INT max number   = 120;
    []BOOL sieve     = PRIMESIEVE ENTIER sqrt( max number );
    print( ( "The attractve numbers up to ", whole( max number, 0 ), newline ) );
    INT    a count  := 0;
    FOR i FROM 2 TO max number DO
        IF  INT v       := i;
            INT f count := 0;
            WHILE NOT ODD v DO
                f count +:= 1;
                v    OVERAB 2
            OD;
            FOR j FROM 3 BY 2 TO max number WHILE v > 1 DO
                WHILE v > 1 AND v MOD j = 0 DO
                    f count +:= 1;
                    v    OVERAB j
                OD
            OD;
            f count > 0
        THEN
            IF sieve[ f count ] THEN
                print( ( " ", whole( i, -3 ) ) );
                IF ( a count +:= 1 ) MOD 20 = 0 THEN print( ( newline ) ) FI
            FI
        FI
    OD;
    print( ( newline, "Found ", whole( a count, 0 ), " attractive numbers", newline ) )
END


% find some attractive numbers - numbers whose prime factor count is prime   %
begin
    % implements the sieve of Eratosthenes                                   %
    %     s(i) is set to true if i is prime, false otherwise                 %
    %     algol W doesn't have a upb operator, so we pass the size of the    %
    %     array in n                                                         %
    procedure sieve( logical array s ( * ); integer value n ) ;
    begin
        % start with everything flagged as prime                             %
        for i := 1 until n do s( i ) := true;
        % sieve out the non-primes                                           %
        s( 1 ) := false;
        for i := 2 until truncate( sqrt( n ) ) do begin
            if s( i ) then for p := i * i step i until n do s( p ) := false
        end for_i ;
    end sieve ;
    % returns the count of prime factors of n, using the sieve of primes s   %
    %         n must be greater than 0                                       %
    integer procedure countPrimeFactors ( integer value n; logical array s ( * ) ) ;
    if s( n ) then 1
    else begin
        integer count, rest;
        rest  := n;
        count := 0;
        while rest rem 2 = 0 do begin
            count := count + 1;
            rest  := rest div 2
        end while_divisible_by_2 ;
        for factor := 3 step 2 until n - 1 do begin
            if s( factor ) then begin
                while rest > 1 and rest rem factor = 0 do begin
                    count := count + 1;
                    rest  := rest div factor
                end while_divisible_by_factor
            end if_prime_factor
        end for_factor ;
        count
    end countPrimeFactors ;
    % maximum number for the task                                            %
    integer maxNumber;
    maxNumber := 120;
    % show the attractive numbers                                            %
    begin
        logical array s ( 1 :: maxNumber );
        sieve( s, maxNumber );
        i_w := 2; % set output field width                                   %
        s_w := 1; % and output separator width                               %
        % find and display the attractive numbers                            %
        for i := 2 until maxNumber do if s( countPrimeFactors( i, s ) ) then writeon( i )
    end
end.


class AvlTree {
    private var root: Node? = null

    private class Node(var key: Int, var parent: Node?) {
        var balance: Int = 0
        var left : Node? = null
        var right: Node? = null
    }

    fun insert(key: Int): Boolean {
        if (root == null)
            root = Node(key, null)
        else {
            var n: Node? = root
            var parent: Node
            while (true) {
                if (n!!.key == key) return false
                parent = n
                val goLeft = n.key > key
                n = if (goLeft) n.left else n.right
                if (n == null) {
                    if (goLeft)
                        parent.left  = Node(key, parent)
                    else
                        parent.right = Node(key, parent)
                    rebalance(parent)
                    break
                }
            }
        }
        return true
    }

    fun delete(delKey: Int) {
        if (root == null) return
        var n:       Node? = root
        var parent:  Node? = root
        var delNode: Node? = null
        var child:   Node? = root
        while (child != null) {
            parent = n
            n = child
            child = if (delKey >= n.key) n.right else n.left
            if (delKey == n.key) delNode = n
        }
        if (delNode != null) {
            delNode.key = n!!.key
            child = if (n.left != null) n.left else n.right
            if (0 == root!!.key.compareTo(delKey)) {
                root = child

                if (null != root) {
                    root!!.parent = null
                }

            } else {
                if (parent!!.left == n)
                    parent.left = child
                else
                    parent.right = child

                if (null != child) {
                    child.parent = parent
                }

                rebalance(parent)
            }
    }

    private fun rebalance(n: Node) {
        setBalance(n)
        var nn = n
        if (nn.balance == -2)
            if (height(nn.left!!.left) >= height(nn.left!!.right))
                nn = rotateRight(nn)
            else
                nn = rotateLeftThenRight(nn)
        else if (nn.balance == 2)
            if (height(nn.right!!.right) >= height(nn.right!!.left))
                nn = rotateLeft(nn)
            else
                nn = rotateRightThenLeft(nn)
        if (nn.parent != null) rebalance(nn.parent!!)
        else root = nn
    }

    private fun rotateLeft(a: Node): Node {
        val b: Node? = a.right
        b!!.parent = a.parent
        a.right = b.left
        if (a.right != null) a.right!!.parent = a
        b.left = a
        a.parent = b
        if (b.parent != null) {
            if (b.parent!!.right == a)
                b.parent!!.right = b
            else
                b.parent!!.left = b
        }
        setBalance(a, b)
        return b
    }

    private fun rotateRight(a: Node): Node {
        val b: Node? = a.left
        b!!.parent = a.parent
        a.left = b.right
        if (a.left != null) a.left!!.parent = a
        b.right = a
        a.parent = b
        if (b.parent != null) {
            if (b.parent!!.right == a)
                b.parent!!.right = b
            else
                b.parent!!.left = b
        }
        setBalance(a, b)
        return b
    }

    private fun rotateLeftThenRight(n: Node): Node {
        n.left = rotateLeft(n.left!!)
        return rotateRight(n)
    }

    private fun rotateRightThenLeft(n: Node): Node {
        n.right = rotateRight(n.right!!)
        return rotateLeft(n)
    }

    private fun height(n: Node?): Int {
        if (n == null) return -1
        return 1 + Math.max(height(n.left), height(n.right))
    }

    private fun setBalance(vararg nodes: Node) {
        for (n in nodes) n.balance = height(n.right) - height(n.left)
    }

    fun printKey() {
        printKey(root)
        println()
    }

    private fun printKey(n: Node?) {
        if (n != null) {
            printKey(n.left)
            print("${n.key} ")
            printKey(n.right)
        }
    }

    fun printBalance() {
        printBalance(root)
        println()
    }

    private fun printBalance(n: Node?) {
        if (n != null) {
            printBalance(n.left)
            print("${n.balance} ")
            printBalance(n.right)
        }
    }
}

fun main(args: Array<String>) {
    val tree = AvlTree()
    println("Inserting values 1 to 10")
    for (i in 1..10) tree.insert(i)
    print("Printing key     : ")
    tree.printKey()
    print("Printing balance : ")
    tree.printBalance()
}


page:	equ	2	; Store doors in page 2
doors:	equ	100	; 100 doors
puts:	equ	9	; CP/M string output
	org	100h
	xra	a	; Set all doors to zero
	lxi	h,256*page
	mvi	c,doors
zero:	mov	m,a
	inx	h
	dcr	c
	jnz	zero
	mvi	m,'$'	; CP/M string terminator (for easier output later)
	mov	d,a	; D=0 so that DE=E=pass counter
	mov	e,a	; E=0, first pass
	mvi	a,doors-1	; Last pass and door
pass:	mov	l,e	; L=door counter, start at first door in pass
door:	inr	m	; Incrementing always toggles the low bit
	dad	d	; Go to next door in pass
	inr	l
	cmp	l	; Was this the last door?
	jnc	door	; If not, do the next door
	inr	e	; Next pass
	cmp	e	; Was this the last pass?
	jnc	pass	; If not, do the next pass
	lxi	h,256*page
	mvi	c,doors	; Door counter
	lxi	d,130h	; D=1 (low bit), E=30h (ascii 0)
char:	mov	a,m	; Get door
	ana	d	; Low bit gives door status
	ora	e	; ASCII 0 or 1
	mov	m,a	; Write character back
	inx	h	; Next door
	dcr	c	; Any doors left?
	jnz	char	; If so, next door
	lxi	d,256*page
	mvi	c,puts	; CP/M system call to print the string
	jmp	5


(lib 'math) ;; Σ aka (sigma f(n)  nfrom nto)

(define (f-count  N (times 100000))
    (define count 0)
    (for ((i times))

    ;; new  random f mapping from  0..N-1 to 0..N-1
    ;; (f n) is NOT (random N)
    ;; because each call (f n) must return the same value

    (define f (build-vector N  (lambda(i) (random N))))

    (define hits (make-vector N))
        (define n 0)
        (while (zero? [hits n])
            (++ count)
            (vector+= hits n 1)
            (set! n [f n])))
    (// count times))

(define (f-anal N)
    (Σ  (lambda(i) (// (! N) (! (- N i)) (^  N i))) 1 N))

(decimals 5)
(define (f-print (maxN 21))
	(for ((N (in-range 1 maxN)))
	(define fc (f-count N))
	(define fa (f-anal N))
	(printf  "%3d %10d %10d  %10.2d %%" N fc fa (// (abs (- fa fc)) fc 0.01))))


defmodule RC do
  def factorial(0), do: 1
  def factorial(n), do: Enum.reduce(1..n, 1, &(&1 * &2))

  def loop_length(n), do: loop_length(n, MapSet.new)

  defp loop_length(n, set) do
    r = :rand.uniform(n)
    if r in set, do: MapSet.size(set), else: loop_length(n, MapSet.put(set, r))
  end

  def task(runs) do
    IO.puts " N    average   analytical   (error) "
    IO.puts "===  =========  ==========  ========="
    Enum.each(1..20, fn n ->
      avg = Enum.reduce(1..runs, 0, fn _,sum -> sum + loop_length(n) end) / runs
      analytical = Enum.reduce(1..n, 0, fn i,sum ->
        sum + (factorial(n) / :math.pow(n, i) / factorial(n-i))
      end)
      :io.format "~3w  ~9.4f   ~9.4f  (~6.2f%)~n", [n, avg, analytical, abs(avg/analytical - 1)*100]
    end)
  end
end

runs = 1_000_000
RC.task(runs)


on isPrime(n)
    if (n < 4) then return (n > 1)
    if ((n mod 2 is 0) or (n mod 3 is 0)) then return false
    repeat with i from 5 to (n ^ 0.5) div 1 by 6
        if ((n mod i is 0) or (n mod (i + 2) is 0)) then return false
    end repeat

    return true
end isPrime

on primeFactorCount(n)
    set x to n
    set counter to 0
    if (n > 1) then
        repeat while (n mod 2 = 0)
            set counter to counter + 1
            set n to n div 2
        end repeat
        repeat while (n mod 3 = 0)
            set counter to counter + 1
            set n to n div 3
        end repeat
        set i to 5
        set limit to (n ^ 0.5) div 1
        repeat until (i > limit)
            repeat while (n mod i = 0)
                set counter to counter + 1
                set n to n div i
            end repeat
            tell (i + 2) to repeat while (n mod it = 0)
                set counter to counter + 1
                set n to n div it
            end repeat
            set i to i + 6
            set limit to (n ^ 0.5) div 1
        end repeat
        if (n > 1) then set counter to counter + 1
    end if

    return counter
end primeFactorCount

-- Task code:
local output, n
set output to {}
repeat with n from 1 to 120
    if (isPrime(primeFactorCount(n))) then set end of output to n
end repeat
return output


AVL={balance=0}
AVL.__mt={__index = AVL}

function AVL:new(list)
  local o={}
  setmetatable(o, AVL.__mt)
  for _,v in ipairs(list or {}) do
    o=o:insert(v)
  end
  return o
end

function AVL:rebalance()
  local rotated=false
  if self.balance>1 then
    if self.right.balance<0 then
      self.right, self.right.left.right, self.right.left = self.right.left, self.right, self.right.left.right
      self.right.right.balance=self.right.balance>-1 and 0 or 1
      self.right.balance=self.right.balance>0 and 2 or 1
    end
    self, self.right.left, self.right = self.right, self, self.right.left
    self.left.balance=1-self.balance
    self.balance=self.balance==0 and -1 or 0
    rotated=true
  elseif self.balance<-1 then
    if self.left.balance>0 then
      self.left, self.left.right.left, self.left.right = self.left.right, self.left, self.left.right.left
      self.left.left.balance=self.left.balance<1 and 0 or -1
      self.left.balance=self.left.balance<0 and -2 or -1
    end
    self, self.left.right, self.left = self.left, self, self.left.right
    self.right.balance=-1-self.balance
    self.balance=self.balance==0 and 1 or 0
    rotated=true
  end
  return self,rotated
end

function AVL:insert(v)
  if not self.value then
    self.value=v
    self.balance=0
    return self,1
  end
  local grow
  if v==self.value then
    return self,0
  elseif v<self.value then
    if not self.left then self.left=self:new() end
    self.left,grow=self.left:insert(v)
    self.balance=self.balance-grow
  else
    if not self.right then self.right=self:new() end
    self.right,grow=self.right:insert(v)
    self.balance=self.balance+grow
  end
  self,rotated=self:rebalance()
  return self, (rotated or self.balance==0) and 0 or grow
end

function AVL:delete_move(dir,other,mul)
  if self[dir] then
    local sb2,v
    self[dir], sb2, v=self[dir]:delete_move(dir,other,mul)
    self.balance=self.balance+sb2*mul
    self,sb2=self:rebalance()
    return self,(sb2 or self.balance==0) and -1 or 0,v
  else
    return self[other],-1,self.value
  end
end

function AVL:delete(v,isSubtree)
  local grow=0
  if v==self.value then
    local v
    if self.balance>0 then
      self.right,grow,v=self.right:delete_move("left","right",-1)
    elseif self.left then
      self.left,grow,v=self.left:delete_move("right","left",1)
      grow=-grow
    else
      return not isSubtree and AVL:new(),-1
    end
    self.value=v
    self.balance=self.balance+grow
  elseif v<self.value and self.left then
    self.left,grow=self.left:delete(v,true)
    self.balance=self.balance-grow
  elseif v>self.value and self.right then
    self.right,grow=self.right:delete(v,true)
    self.balance=self.balance+grow
  else
    return self,0
  end
  self,rotated=self:rebalance()
  return self, grow~=0 and (rotated or self.balance==0) and -1 or 0
end

-- output functions

function AVL:toList(list)
  if not self.value then return {} end
  list=list or {}
  if self.left then self.left:toList(list) end
  list[#list+1]=self.value
  if self.right then self.right:toList(list) end
  return list
end

function AVL:dump(depth)
  if not self.value then return end
  depth=depth or 0
  if self.right then self.right:dump(depth+1) end
  print(string.rep("    ",depth)..self.value.." ("..self.balance..")")
  if self.left then self.left:dump(depth+1) end
end

-- test

local test=AVL:new{1,10,5,15,20,3,5,14,7,13,2,8,3,4,5,10,9,8,7}

test:dump()
print("\ninsert 17:")
test=test:insert(17)
test:dump()
print("\ndelete 10:")
test=test:delete(10)
test:dump()
print("\nlist:")
print(unpack(test:toList()))