Monads/Maybe monad

Demonstrate in your programming language the following:

#Construct a Maybe Monad by writing the 'bind' function and the 'unit' (sometimes known as 'return') function for that Monad (or just use what the language already has implemented)
#Make two functions, each which take a number and return a monadic number, e.g. Int -> Maybe Int and Int -> Maybe String
#Compose the two functions with bind

A Monad is a single type which encapsulates several other types, eliminating boilerplate code. In practice it acts like a dynamically typed computational sequence, though in many cases the type issues can be resolved at compile time.

A Maybe Monad is a monad which specifically encapsulates the type of an undefined value.

Solution:
class Maybe
  def initialize(value)
    @value = value
  end

  def map
    if @value.nil?
      self
    else
      Maybe.new(yield @value)
    end
  end
end

Maybe.new(3).map { |n| 2*n }.map { |n| n+1 }
#=> #<Maybe @value=7>

Maybe.new(nil).map { |n| 2*n }.map { |n| n+1 }
#=> #<Maybe @value=nil>

Maybe.new(3).map { |n| nil }.map { |n| n+1 }
#=> #<Maybe @value=nil>

# alias Maybe#new and write bind to be in line with task

class Maybe
  class << self
    alias :unit :new
  end

  def initialize(value)
    @value = value
  end

  def bind
    if @value.nil?
      self
    else
      yield @value
    end
  end
end

Maybe.unit(3).bind { |n| Maybe.unit(2*n) }.bind { |n| Maybe.unit(n+1) }
#=> #<Maybe @value=7>

Maybe.unit(nil).bind { |n| Maybe.unit(2*n) }.bind { |n| Maybe.unit(n+1) }
#=> #<Maybe @value=nil>


Monads/Writer monad

The Writer monad is a programming design pattern which makes it possible to compose functions which return their result values paired with a log string. The final result of a composed function yields both a value, and a concatenation of the logs from each component function application.

Demonstrate in your programming language the following:

# Construct a Writer monad by writing the 'bind' function and the 'unit' (sometimes known as 'return') function for that monad (or just use what the language already provides)
# Write three simple functions: root, addOne, and half
# Derive Writer monad versions of each of these functions
# Apply a composition of the Writer versions of root, addOne, and half to the integer 5, deriving both a value for the Golden Ratio ph, and a concatenated log of the function applications (starting with the initial value, and followed by the application of root, etc.)

Solution:
# 20220720 Ruby programming solution
class Writer
  attr_reader :value, :log

  def initialize(value, log = "New")
    @value = value
    if value.is_a? Proc
      @log = log
    else
      @log = log + ": " + @value.to_s
    end
  end

  def self.unit(value, log)
    Writer.new(value, log)
  end

  def bind(mwriter)
    new_value = mwriter.value.call(@value)
    new_log = @log + "\n" + mwriter.log
    self.class.new(new_value, new_log)
  end
end

lam_sqrt = ->(number) { Math.sqrt(number) }
lam_add_one = ->(number) { number + 1 }
lam_half = ->(number) { number / 2.0 }

sqrt = Writer.unit( lam_sqrt, "Took square root")
add_one = Writer.unit( lam_add_one, "Added one")
half = Writer.unit( lam_half, "Divided by 2")

m1 = Writer.unit(5, "Initial value")
m2 = m1.bind(sqrt).bind(add_one).bind(half)

puts "The final value is #{m2.value}\n\n"
puts "This value was derived as follows:"
puts m2.log


Move-to-front algorithm

Given a symbol table of a ''zero-indexed'' array of all possible input symbols
this algorithm reversibly transforms a sequence
of input symbols into an array of output numbers (indices).

The transform in many cases acts to give frequently repeated input symbols
lower indices which is  useful in some compression algorithms.

;Encoding algorithm:

    for each symbol of the input sequence:
        output the index of the symbol in the symbol table
        move that symbol to the front of the symbol table

;Decoding algorithm:

    # Using the same starting symbol table
    for each index of the input sequence:
        output the symbol at that index of the symbol table
        move that symbol to the front of the symbol table

;Example:
Encoding the string of character symbols 'broood' using a symbol table of the lowercase characters   '''a'''-to-'''z'''

:::::{| class="wikitable" border="1"
|-
! Input
! Output
! SymbolTable
|-
| '''b'''roood
| 1
| 'abcdefghijklmnopqrstuvwxyz'
|-
| b'''r'''oood
| 1 17
| 'bacdefghijklmnopqrstuvwxyz'
|-
| br'''o'''ood
| 1 17 15
| 'rbacdefghijklmnopqstuvwxyz'
|-
| bro'''o'''od
| 1 17 15 0
| 'orbacdefghijklmnpqstuvwxyz'
|-
| broo'''o'''d
| 1 17 15 0 0
| 'orbacdefghijklmnpqstuvwxyz'
|-
| brooo'''d'''
| 1 17 15 0 0 5
| 'orbacdefghijklmnpqstuvwxyz'
|}

Decoding the indices back to the original symbol order:
:::::{| class="wikitable" border="1"
|-
! Input
! Output
! SymbolTable
|-
|  '''1''' 17 15 0 0 5
| b
| 'abcdefghijklmnopqrstuvwxyz'
|-
| 1 '''17''' 15 0 0 5
| br
| 'bacdefghijklmnopqrstuvwxyz'
|-
| 1 17 '''15''' 0 0 5
| bro
| 'rbacdefghijklmnopqstuvwxyz'
|-
| 1 17 15 '''0''' 0 5
| broo
| 'orbacdefghijklmnpqstuvwxyz'
|-
| 1 17 15 0 '''0''' 5
| brooo
| 'orbacdefghijklmnpqstuvwxyz'
|-
| 1 17 15 0 0 '''5'''
| broood
| 'orbacdefghijklmnpqstuvwxyz'
|}

;Task:
:*   Encode and decode the following three strings of characters using the symbol table of the lowercase characters   '''a'''-to-'''z'''   as above.
:*   Show the strings and their encoding here.
:*   Add a check to ensure that the decoded string is the same as the original.

The strings are:

    broood
 bananaaa
 hiphophiphop
(Note the misspellings in the above strings.)

Solution:
module MoveToFront

  ABC = ("a".."z").to_a.freeze

  def self.encode(str)
    ar = ABC.dup
    str.chars.each_with_object([]) do |char, memo|
      memo << (i = ar.index(char))
      ar = m2f(ar,i)
    end
  end

  def self.decode(indices)
    ar = ABC.dup
    indices.each_with_object("") do |i, str|
      str << ar[i]
      ar = m2f(ar,i)
    end
  end

  private
  def self.m2f(ar,i)
    [ar.delete_at(i)] + ar
  end

end

['broood', 'bananaaa', 'hiphophiphop'].each do |word|
  p word == MoveToFront.decode(p MoveToFront.encode(p word))
end


Multifactorial

The factorial of a number, written as n!, is defined as n! = n(n-1)(n-2)...(2)(1).

Multifactorials generalize factorials as follows:
: n! = n(n-1)(n-2)...(2)(1)
: n!! = n(n-2)(n-4)...
: n!! ! = n(n-3)(n-6)...
: n!! !! = n(n-4)(n-8)...
: n!! !! ! = n(n-5)(n-10)...

In all cases, the terms in the products are positive integers.

If we define the degree of the multifactorial as the difference in successive terms that are multiplied together for a multifactorial (the number of exclamation marks), then the task is twofold:
# Write a function that given n and the degree, calculates the multifactorial.
# Use the function to generate and display here a table of the first ten members (1 to 10) of the first five degrees of multifactorial.

'''Note:''' The wikipedia entry on multifactorials gives a different formula. This task uses the Wolfram mathworld definition.

Solution:
def multifact(n, d)
  n.step(1, -d).inject( :* )
end

(1..5).each {|d| puts "Degree #{d}: #{(1..10).map{|n| multifact(n, d)}.join "\t"}"}


Multiple distinct objects

Create a [[sequence]] (array, list, whatever) consisting of n distinct, initialized items of the same type. n should be determined at runtime.

By ''distinct'' we mean that if they are mutable, changes to one do not affect all others; if there is an appropriate equality operator they are considered unequal; etc. The code need not specify a particular kind of distinction, but do not use e.g. a numeric-range generator which does not generalize.

By ''initialized'' we mean that each item must be in a well-defined state appropriate for its type, rather than e.g. arbitrary previous memory contents in an array allocation. Do not show only an initialization technique which initializes only to "zero" values (e.g. calloc() or int a[n] = {}; in C), unless user-defined types can provide definitions of "zero" for that type.

This task was inspired by the common error of intending to do this, but instead creating a sequence of n references to the ''same'' mutable object; it might be informative to show the way to do that as well, both as a negative example and as how to do it when that's all that's actually necessary.

This task is most relevant to languages operating in the pass-references-by-value style (most object-oriented, garbage-collected, and/or 'dynamic' languages).

See also: [[Closures/Value capture]]

Solution:
[Foo.new] * n         # here Foo.new can be any expression that returns a new object
Array.new(n, Foo.new)


Multisplit

It is often necessary to split a string into pieces
based on several different (potentially multi-character) separator strings,
while still retaining the information about which separators were present in the input.

This is particularly useful when doing small parsing tasks.
The task is to write code to demonstrate this.

The function (or procedure or method, as appropriate) should
take an input string and an ordered collection of separators.

The order of the separators is significant:
The delimiter order represents priority in matching, with the first defined delimiter having the highest priority.
In cases where there would be an ambiguity as to
which separator to use at a particular point
(e.g., because one separator is a prefix of another)
the separator with the highest priority should be used.
Delimiters can be reused and the output from the function should be an ordered sequence of substrings.

Test your code using the input string "a!===b=!=c" and the separators "==", "!=" and "=".

For these inputs the string should be parsed as "a" (!=) "" (==) "b" (=) "" (!=) "c", where matched delimiters are shown in parentheses, and separated strings are quoted, so our resulting output is "a", empty string, "b", empty string, "c".
Note that the quotation marks are shown for clarity and do not form part of the output.

'''Extra Credit:''' provide information that indicates which separator was matched at each separation point and where in the input string that separator was matched.

Solution:
def multisplit(text, separators)
  sep_regex = Regexp.union(separators)
  separator_info = []
  pieces = []
  i = prev = 0
  while i = text.index(sep_regex, i)
    separator = Regexp.last_match(0)
    pieces << text[prev .. i-1]
    separator_info << [separator, i]
    i = i + separator.length
    prev = i
  end
  pieces << text[prev .. -1]
  [pieces, separator_info]
end

p multisplit(text, separators)
# => [["a", "", "b", "", "c"], [["!=", 1], ["==", 3], ["=", 6], ["!=", 7]]]


Mutex

{{requires|Concurrency}}

A '''mutex''' (''abbreviated'' '''Mut'''ually '''Ex'''clusive access) is a synchronization object, a variant of [[semaphore]] with ''k''=1.
A mutex is said to be seized by a [[task]] decreasing ''k''.
It is released when the task restores ''k''. Mutexes are typically used to protect a shared resource from concurrent access.
A [[task]] seizes (or acquires) the mutex, then accesses the resource, and after that releases the mutex.

A mutex is a low-level synchronization primitive exposed to deadlocking. A deadlock can occur with just two tasks and two mutexes (if each task attempts to acquire both mutexes, but in the opposite order).
Entering the deadlock is usually aggravated by a [[race condition]] state, which leads to sporadic hangups, which are very difficult to track down.

=Variants of mutexes=

==Global and local mutexes==
Usually the [[OS]] provides various implementations of mutexes corresponding to the variants of [[task]]s available in the OS. For example, system-wide mutexes can be used by [[process]]es. Local mutexes can be used only by [[threads]] etc. This distinction is maintained because, depending on the hardware, seizing a global mutex might be a thousand times slower than seizing a local one.

==Reentrant mutex==
A reentrant mutex can be seized by the same [[task]] multiple times. Each seizing of the mutex is matched by releasing it, in order to allow another task to seize it.

==Read write mutex==
A read write mutex can be seized at two levels for ''read'' and for ''write''. The mutex can be seized for ''read'' by any number of tasks. Only one task may seize it for '''write''. Read write mutexes are usually used to protect resources which can be accessed in mutable and immutable ways. Immutable (read) access is granted concurrently for many tasks because they do not change the resource state. Read write mutexes can be reentrant, global or local. Further, promotion operations may be provided. That's when a [[task]] that has seized the mutex for ''write'' releases it while keeping seized for ''read''. Note that the reverse operation is potentially deadlocking and requires some additional access policy control.

=Deadlock prevention=
There exists a simple technique of deadlock prevention when mutexes are seized in some fixed order. This is discussed in depth in the [[Dining philosophers]] problem.

=Sample implementations / APIs=

Solution:
# acquire a lock -- block execution until it becomes free
an_object.mu_lock

# acquire a lock -- return immediately even if not acquired
got_lock = an_object.mu_try_lock

# have a lock?
if an_object.mu_locked? then ...

# release the lock
an_object.mu_unlock

# wrap a lock around a block of code -- block execution until it becomes free
an_object.my_synchronize do
  do critical stuff
end


N-queens problem

right

Solve the eight queens puzzle.

You can extend the problem to solve the puzzle with a board of size   '''N'''x'''N'''.

For the number of solutions for small values of   '''N''',   see   OEIS: A000170.

;Related tasks:
* [[A* search algorithm]]
* [[Solve a Hidato puzzle]]
* [[Solve a Holy Knight's tour]]
* [[Knight's tour]]
* [[Peaceful chess queen armies]]
* [[Solve a Hopido puzzle]]
* [[Solve a Numbrix puzzle]]
* [[Solve the no connection puzzle]]

Solution:
# 1. Divide n by 12. Remember the remainder (n is 8 for the eight queens
#    puzzle).
# 2. Write a list of the even numbers from 2 to n in order.
# 3. If the remainder is 3 or 9, move 2 to the end of the list.
# 4. Append the odd numbers from 1 to n in order, but, if the remainder is 8,
#    switch pairs (i.e. 3, 1, 7, 5, 11, 9, …).
# 5. If the remainder is 2, switch the places of 1 and 3, then move 5 to the
#    end of the list.
# 6. If the remainder is 3 or 9, move 1 and 3 to the end of the list.
# 7. Place the first-column queen in the row with the first number in the
#    list, place the second-column queen in the row with the second number in
#    the list, etc.

def n_queens(n)
  if n == 1
    return "Q"
  elsif n < 4
    puts "no solutions for n=#{n}"
    return ""
  end

  evens = (2..n).step(2).to_a
  odds = (1..n).step(2).to_a

  rem = n % 12  # (1)
  nums = evens  # (2)

  nums.rotate if rem == 3 or rem == 9  # (3)

  # (4)
  if rem == 8
    odds = odds.each_slice(2).flat_map(&:reverse)
  end
  nums.concat(odds)

  # (5)
  if rem == 2
    nums[nums.index(1)], nums[nums.index(3)] = nums[nums.index(3)], nums[nums.index(1)]
    nums << nums.delete(5)
  end

  # (6)
  if rem == 3 or rem == 9
    nums << nums.delete(1)
    nums << nums.delete(3)
  end

  # (7)
  nums.map do |q|
    a = Array.new(n,".")
    a[q-1] = "Q"
    a*(" ")
  end
end

(1 .. 15).each {|n| puts "n=#{n}"; puts n_queens(n); puts}


Narcissist

Quoting from the Esolangs wiki page:

A '''narcissist''' (or '''Narcissus program''') is the decision-problem version of a [[quine]].

A quine, when run, takes no input, but produces a copy of its own source code at its output. In contrast, a narcissist reads a string of symbols from its input, and produces no output except a "1" or "accept" if that string matches its own source code, or a "0" or "reject" if it does not.

For concreteness, in this task we shall assume that symbol = character.

The narcissist should be able to cope with any finite input, whatever its length.

Any form of output is allowed, as long as the program always halts, and "accept", "reject" and "not yet finished" are distinguishable.

Solution: s = "s = %s%s%s; puts(gets.chomp == (s %% [34.chr, s, 34.chr]) ? 'accept' : 'reject')"; puts(gets.chomp == (s % [34.chr, s, 34.chr]) ? 'accept' : 'reject')


Narcissistic decimal number

A   Narcissistic decimal number   is a non-negative integer,   n,   that is equal to the sum of the   m-th   powers of each of the digits in the decimal representation of   n,   where   m   is the number of digits in the decimal representation of   n.

Narcissistic (decimal) numbers are sometimes called   '''Armstrong'''   numbers, named after Michael F. Armstrong.
They are also known as   '''Plus Perfect'''   numbers.

;An example:
::::*   if   n   is   '''153'''
::::*   then   m,   (the number of decimal digits)   is   '''3'''
::::*   we have    13 + 53 + 33   =   1 + 125 + 27   =   '''153'''
::::*   and so   '''153'''   is a narcissistic decimal number

;Task:
Generate and show here the first   '''25'''   narcissistic decimal numbers.

Note:   0^1 = 0,   the first in the series.

;See also:
*   the  OEIS entry:     Armstrong (or Plus Perfect, or narcissistic) numbers.
*   MathWorld entry:   Narcissistic Number.
*   Wikipedia entry:     Narcissistic number.

Solution:
class Integer
  def narcissistic?
    return false if negative?
    digs = self.digits
    m    = digs.size
    digs.map{|d| d**m}.sum == self
  end
end

puts 0.step.lazy.select(&:narcissistic?).first(25)


Nautical bell

Task

Write a small program that emulates a nautical bell producing a ringing bell pattern at certain times throughout the day.

The bell timing should be in accordance with Greenwich Mean Time, unless locale dictates otherwise.

It is permissible for the program to daemonize, or to slave off a scheduler, and it is permissible to use alternative notification methods (such as producing a written notice "Two Bells Gone"), if these are more usual for the system type.

;Related task:
* [[Sleep]]

Solution:
watches = [ "First", "Middle", "Morning", "Forenoon", "Afternoon", "First dog", "Last dog", "First" ]
watch_ends = [ "00:00", "04:00", "08:00", "12:00", "16:00", "18:00", "20:00", "23:59" ]
words = ["One","Two","Three","Four","Five","Six","Seven","Eight"]
sound = "ding!"

loop do
  time = Time.now
  if time.sec == 0 and time.min % 30 == 0
    num = (time.hour * 60 + time.min) / 30 % 8
    num = 8 if num == 0
    hr_min = time.strftime "%H:%M"
    idx = watch_ends.find_index {|t| hr_min <= t}
    text = "%s - %s watch, %s bell%s gone" % [
        hr_min,
        watches[idx],
        words[num-1],
        num==1 ? "" : "s"
    ]
    bells = (sound * num).gsub(sound + sound) {|dd| dd + ' '}
    puts "%-45s %s" % [text, bells]
  end
  sleep 1
end


Negative base numbers

Negative base numbers are an alternate way to encode numbers without the need for a minus sign. Various negative bases may be used including negadecimal (base -10), negabinary (-2) and negaternary (-3).Negabinary on Wolfram MathworldNegative base on Wikipedia

;Task:

*Encode the decimal number 10 as negabinary (expect 11110)
*Encode the decimal number 146 as negaternary (expect 21102)
*Encode the decimal number 15 as negadecimal (expect 195)
*In each of the above cases, convert the encoded number back to decimal.

;extra credit:

* supply an integer, that when encoded to base   -62   (or something "higher"),   expresses the name of the language being used   (with correct capitalization).   If the computer language has non-alphanumeric characters,   try to encode them into the negatory numerals,   or use other characters instead.

Solution:
DIGITS = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'

# convert a base 10 integer into a negative base value (as a string)

def negative_base_encode(n, b)
  raise 'base out of range' if (b < -62) || (b > -2)
  return '0' if n == 0
  revdigs = []
  while n != 0 do
    n, r = n.divmod(b)
    if r < 0
      n += 1
      r -= b
    end
    revdigs << r
  end
  return revdigs.reduce('') { |digstr, digit| DIGITS[digit] + digstr }
end

# convert a negative base value (as a string) into a base 10 integer

def negative_base_decode(n, b)
  raise 'base out of range' if (b < -62) || (b > -2)
  value = 0
  n.reverse.each_char.with_index do |ch, inx|
    value += DIGITS.index(ch) * b**inx
  end
  return value
end

# do the task

[ [10, -2], [146, -3], [15, -10], [0, -31], [-6221826, -62] ].each do |pair|
  decimal, base = pair
  encoded = negative_base_encode(decimal, base)
  decoded = negative_base_decode(encoded, base)
  puts("Enc: %8i base %-3i = %5s base %-3i  Dec: %5s base %-3i = %8i base %-3i" %
       [decimal, 10, encoded, base, encoded, base, decoded, 10])
end


Nested function

In many languages, functions can be nested, resulting in outer functions and inner functions. The inner function can access variables from the outer function. In most languages, the inner function can also modify variables in the outer function.

;Task:
Write a program consisting of two nested functions that prints the following text.

 1. first
 2. second
 3. third

The outer function (called MakeList or equivalent) is responsible for creating the list as a whole and is given the separator ". " as argument. It also defines a counter variable to keep track of the item number. This demonstrates how the inner function can influence the variables in the outer function.

The inner function (called MakeItem or equivalent) is responsible for creating a list item. It accesses the separator from the outer function and modifies the counter.

;References:
:* Nested function

Solution:
def makeList(separator)
  counter = 1

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

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

print makeList(". ")


Nim game

Nim is a simple game where the second player-if they know the trick-will always win.

The game has only 3 rules:
::*   start with   '''12'''   tokens
::*   each player takes    '''1,  2,  or  3'''   tokens in turn
::*  the player who takes the last token wins.

To win every time,   the second player simply takes 4 minus the number the first player took.   So if the first player takes 1,   the second takes 3; if the first player takes 2,   the second should take 2; and if the first player takes 3,   the second player will take 1.

;Task:
Design a simple Nim game where the human player goes first, and the computer always wins. The game should enforce the rules.

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

puts "Computer took the last and wins."


Nonoblock

Nonogram puzzle.

;Given:
* The number of cells in a row.
* The size of each, (space separated), connected block of cells to fit in the row, in left-to right order.

;Task:
* show all possible positions.
* show the number of positions of the blocks for the following cases within the row.
* show all output on this page.
* use a "neat" diagram of the block positions.

;Enumerate the following configurations:
#   '''5'''   cells   and   '''[2, 1]'''   blocks
#   '''5'''   cells   and   '''[]'''   blocks   (no blocks)
#   '''10'''   cells   and   '''[8]'''   blocks
#   '''15'''   cells   and   '''[2, 3, 2, 3]'''   blocks
#   '''5'''   cells   and   '''[2, 3]'''   blocks   (should give some indication of this not being possible)

;Example:
Given a row of five cells and a block of two cells followed by a block of one cell - in that order, the example could be shown as:

    |_|_|_|_|_| # 5 cells and [2, 1] blocks

And would expand to the following 3 possible rows of block positions:

    |A|A|_|B|_|
    |A|A|_|_|B|
    |_|A|A|_|B|

Note how the sets of blocks are always separated by a space.

Note also that it is not necessary for each block to have a separate letter.
Output approximating

This:
                        |#|#|_|#|_|
                        |#|#|_|_|#|
                        |_|#|#|_|#|

This would also work:
                        ##.#.
                        ##..#
                       .##.#

;An algorithm:
* Find the minimum space to the right that is needed to legally hold all but the leftmost block of cells (with a space between blocks remember).
* The leftmost cell can legitimately be placed in all positions from the LHS up to a RH position that allows enough room for the rest of the blocks.
* for each position of the LH block recursively compute the position of the rest of the blocks in the ''remaining'' space to the right of the current placement of the LH block.

(This is the algorithm used in the [[Nonoblock#Python]] solution).

;Reference:
* The blog post Nonogram puzzle solver (part 1) Inspired this task and donated its [[Nonoblock#Python]] solution.

Solution:
def nonoblocks(cell, blocks)
  raise 'Those blocks will not fit in those cells' if cell < blocks.inject(0,:+) + blocks.size - 1
  nblock(cell, blocks, '', [])
end

def nblock(cell, blocks, position, result)
  if cell <= 0
    result << position[0..cell-1]
  elsif blocks.empty? or blocks[0].zero?
    result << position + '.' * cell
  else
    rest = cell - blocks.inject(:+) - blocks.size + 2
    bl, *brest = blocks
    rest.times.inject(result) do |res, i|
      nblock(cell-i-bl-1, brest, position + '.'*i + '#'*bl + '.', res)
    end
  end
end

conf = [[ 5, [2, 1]],
        [ 5, []],
        [10, [8]],
        [15, [2, 3, 2, 3]],
        [ 5, [2, 3]],      ]
conf.each do |cell, blocks|
  begin
    puts "#{cell} cells and #{blocks} blocks"
    result = nonoblocks(cell, blocks)
    puts result, result.size, ""
  rescue => e
    p e
  end
end


Example
Consider the number 24. Its proper divisors are: 1, 2, 3, 4, 6, 8 and 12. Their product is 13,824 and the cube root of this is 24. So 24 satisfies the definition in the task title.

;Task
Compute and show here the first '''50''' positive integers which are the cube roots of the product of their proper divisors.

Also show the '''500th''' and '''5,000th''' such numbers.

;Stretch
Compute and show the '''50,000th''' such number.

;Reference
* OEIS:A111398 - Numbers which are the cube roots of the product of their proper divisors.

;Note
OEIS considers 1 to be the first number in this sequence even though, strictly speaking, it has no proper divisors. Please therefore do likewise.

Solution:
require 'prime'

def tau(n) = n.prime_division.inject(1){|res, (d, exp)| res *= exp+1}
a111398 = [1].chain (1..).lazy.select{|n| tau(n) == 8}

puts "The first 50 numbers which are the cube roots of the products of their proper divisors:"
p a111398.first(50)
[500, 5000, 50000].each{|n| puts "#{n}th: #{a111398.drop(n-1).next}" }


Numbers with equal rises and falls

When a number is written in base 10,   adjacent digits may "rise" or "fall" as the number is read   (usually from left to right).

;Definition:
Given the decimal digits of the number are written as a series   d:
:*   A   ''rise''         is an index   i   such that    d(i)  <  d(i+1)
:*   A   ''fall''    is an index   i   such that    d(i)  >  d(i+1)

;Examples:
:*   The number          '''726,169'''   has   '''3'''   rises and   '''2'''   falls,   so it isn't in the sequence.
:*   The number     '''83,548'''    has   '''2'''   rises and   '''2'''   falls,   so it   is   in the sequence.

;Task:
:*   Print the first   '''200'''    numbers in the sequence
:*   Show that the   '''10 millionth'''   (10,000,000th)   number in the sequence is   '''41,909,002'''

;See also:
*   OEIS Sequence  A296712   describes numbers whose digit sequence in base 10 have equal "rises" and "falls".

;Related tasks:
*   Esthetic numbers

Solution:
class Integer
  def eq_rise_fall? = digits.each_cons(2).sum{|a,b| a <=> b} == 0
end

puts (1..).lazy.select(&:eq_rise_fall?).take(200).force.join(" ")

n = 10_000_000
res = (1..).lazy.select(&:eq_rise_fall?).take(n).drop(n-1).first
puts "The #{n}th number in the sequence is #{res}."


Numeric error propagation

If   '''f''',   '''a''',   and   '''b'''   are values with uncertainties   sf,   sa,   and   sb,   and   '''c'''   is a constant;
then if   '''f'''   is derived from   '''a''',   '''b''',   and   '''c'''   in the following ways,
then   sf   can be calculated as follows:

:;Addition/Subtraction
:* If   f = a +- c,   or   f = c +- a   then   '''sf = sa'''
:* If   f = a +- b   then   '''sf2 = sa2 + sb2'''

:;Multiplication/Division
:* If   f = ca   or   f = ac       then   '''sf = |csa|'''
:* If   f = ab   or   f = a / b              then   '''sf2 = f2( (sa / a)2 + (sb / b)2)'''

:;Exponentiation
:* If   f = ac   then   '''sf = |fc(sa / a)|'''

Caution:
::This implementation of error propagation does not address issues of dependent and independent values.   It is assumed that   '''a'''   and   '''b'''   are independent and so the formula for multiplication should not be applied to   '''a*a'''   for example.   See   the talk page   for some of the implications of this issue.

;Task details:
# Add an uncertain number type to your language that can support addition, subtraction, multiplication, division, and exponentiation between numbers with an associated error term together with 'normal' floating point numbers without an associated error term. Implement enough functionality to perform the following calculations.
# Given coordinates and their errors:x1 = 100 +- 1.1y1 =  50 +- 1.2x2 = 200 +- 2.2y2 = 100 +- 2.3 if point p1 is located at (x1, y1) and p2 is at (x2, y2); calculate the distance between the two points using the classic Pythagorean formula:   d =    (x1 - x2)2   +   (y1 - y2)2
# Print and display both    '''d'''    and its error.

;References:
* A Guide to Error Propagation B. Keeney, 2005.
* Propagation of uncertainty Wikipedia.

;Related task:
*   [[Quaternion type]]

Solution:
class NumberWithUncertainty
  def initialize(number, error)
    @num = number
    @err = error.abs
  end
  attr_reader :num, :err

  def +(other)
    if other.kind_of?(self.class)
      self.class.new(num + other.num, Math::hypot(err, other.err))
    else
      self.class.new(num + other, err)
    end
  end

  def -(other)
    if other.kind_of?(self.class)
      self.class.new(num - other.num, Math::hypot(err, other.err))
    else
      self.class.new(num - other, err)
    end
  end

  def *(other)
    if other.kind_of?(self.class)
      prod = num * other.num
      e = Math::hypot((prod * err / num), (prod * other.err / other.num))
      self.class.new(prod, e)
    else
      self.class.new(num * other, (err * other).abs)
    end
  end

  def /(other)
    if other.kind_of?(self.class)
      quo = num / other.num
      e = Math::hypot((quo * err / num), (quo * other.err / other.num))
      self.class.new(quo, e)
    else
      self.class.new(num / other, (err * other).abs)
    end
  end

  def **(exponent)
    Float(exponent) rescue raise ArgumentError, "not an number: #{exponent}"
    prod = num ** exponent
    self.class.new(prod, (prod * exponent * err / num).abs)
  end

  def sqrt
    self ** 0.5
  end

  def to_s
    "#{num} \u00b1 #{err}"
  end
end

x1 = NumberWithUncertainty.new(100, 1.1)
y1 = NumberWithUncertainty.new( 50, 1.2)
x2 = NumberWithUncertainty.new(200, 2.2)
y2 = NumberWithUncertainty.new(100, 2.3)

puts ((x1 - x2) ** 2 + (y1 - y2) ** 2).sqrt


Odd word problem

Write a program that solves the odd word problem with the restrictions given below.

;Description:
You are promised an input stream consisting of English letters and punctuations.

It is guaranteed that:
* the words (sequence of consecutive letters) are delimited by one and only one punctuation,
* the stream will begin with a word,
* the words will be at least one letter long,   and
* a full stop (a period, [.]) appears after, and only after, the last word.

;Example:
A stream with six words:
:: what,is,the;meaning,of:life.

The task is to reverse the letters in every other word while leaving punctuations intact, producing:
:: what,si,the;gninaem,of:efil.
while observing the following restrictions:
# Only I/O allowed is reading or writing one character at a time, which means: no reading in a string, no peeking ahead, no pushing characters back into the stream, and no storing characters in a global variable for later use;
# You '''are not''' to explicitly save characters in a collection data structure, such as arrays, strings, hash tables, etc, for later reversal;
# You '''are''' allowed to use recursions, closures, continuations, threads, co-routines, etc., even if their use implies the storage of multiple characters.

;Test cases:
Work on both the   "life"   example given above, and also the text:
:: we,are;not,in,kansas;any,more.

Solution:
These Ruby programs store each character in a single-character string.

===Using fibers and recursion===


Odd word problem

Solution:
f, r = nil
fwd = proc {|c|
  c =~ /[[:alpha:]]/ ? [(print c), fwd[Fiber.yield f]][1] : c }
rev = proc {|c|
  c =~ /[[:alpha:]]/ ? [rev[Fiber.yield r], (print c)][0] : c }

(f = Fiber.new { loop { print fwd[Fiber.yield r] }}).resume
(r = Fiber.new { loop { print rev[Fiber.yield f] }}).resume

coro = f
until $stdin.eof?
  coro = coro.resume($stdin.getc)
end


Old Russian measure of length

Write a program to perform a conversion of the old Russian measures of length to the metric system   (and vice versa).

It is an example of a linear transformation of several variables.

The program should accept a single value in a selected unit of measurement, and convert and return it to the other units:
''vershoks'', ''arshins'', ''sazhens'', ''versts'', ''meters'', ''centimeters'' and ''kilometers''.

;Also see:
:*   Old Russian measure of length

Solution:
module Distances

  RATIOS =
  {arshin: 0.7112, centimeter: 0.01,     diuym:   0.0254,
   fut:    0.3048, kilometer:  1000.0,   liniya:  0.00254,
   meter:  1.0,    milia:      7467.6,   piad:    0.1778,
   sazhen: 2.1336, tochka:     0.000254, vershok: 0.04445,
   versta: 1066.8}

  def self.method_missing(meth, arg)
    from, to = meth.to_s.split("2").map(&:to_sym)
    raise NoMethodError, meth if ([from,to]-RATIOS.keys).size > 0
    RATIOS[from] * arg / RATIOS[to]
  end

  def self.print_others(name, num)
    puts "#{num} #{name} ="
    RATIOS.except(name.to_sym).each {|k,v| puts "#{ (1.0 / v*num)} #{k}" }
  end
end

Distances.print_others("meter", 2)
puts
p Distances.meter2centimeter(3)
p Distances.arshin2meter(1)
p Distances.versta2kilometer(20) # en Hoeperdepoep zat op de stoep
# 13*13 = 169 methods supported, but not:
p Distances.mile2piad(1)


Old lady swallowed a fly

Present a program which emits the lyrics to the song   ''I Knew an Old Lady Who Swallowed a Fly'',   taking advantage of the repetitive structure of the song's lyrics.

This song has multiple versions with slightly different lyrics, so all these programs might not emit identical output.

Solution:
descriptions = {
  :fly    => "I don't know why S",
  :spider => "That wriggled and jiggled and tickled inside her.",
  :bird   => "Quite absurd T",
  :cat    => "Fancy that, S",
  :dog    => "What a hog, S",
  :goat   => "She opened her throat T",
  :cow    => "I don't know how S",
  :horse  => "She's dead, of course.",
}
animals = descriptions.keys

animals.each_with_index do |animal, idx|
  puts "There was an old lady who swallowed a #{animal}."

  d = descriptions[animal]
  case d[-1]
  when "S" then d[-1] = "she swallowed a #{animal}."
  when "T" then d[-1] = "to swallow a #{animal}."
  end
  puts d
  break if animal == :horse

  idx.downto(1) do |i|
    puts "She swallowed the #{animals[i]} to catch the #{animals[i-1]}."
    case animals[i-1]
    when :spider, :fly then puts descriptions[animals[i-1]]
    end
  end

  print "Perhaps she'll die.\n\n"
end


One of n lines in a file

A method of choosing a line randomly from a file:
::* Without reading the file more than once
::* When substantial parts of the file cannot be held in memory
::* Without knowing how many lines are in the file
Is to:
::* keep the first line of the file as a possible choice, then
::* Read the second line of the file if possible and make it the possible choice if a uniform random value between zero and one is less than 1/2.
::* Read the third line of the file if possible and make it the possible choice if a uniform random value between zero and one is less than 1/3.
::* ...
::* Read the Nth line of the file if possible and make it the possible choice if a uniform random value between zero and one is less than 1/N

::* Return the computed possible choice when no further lines exist in the file.

;Task:
# Create a function/method/routine called one_of_n that given n, the number of actual lines in a file, follows the algorithm above to return an integer - the line number of the line chosen from the file. The number returned can vary, randomly, in each run.
# Use one_of_n in a ''simulation'' to find what would be the chosen line of a 10-line file simulated 1,000,000 times.
# Print and show how many times each of the 10 lines is chosen as a rough measure of how well the algorithm works.

Note: You may choose a smaller number of repetitions if necessary, but mention this up-front.

Note: This is a specific version of a Reservoir Sampling algorithm: https://en.wikipedia.org/wiki/Reservoir_sampling

Solution:
# Returns a random line from _io_, or nil if _io_ has no lines.
#  # Get a random line from /etc/passwd
#  line = open("/etc/passwd") {|f| random_line(f) }
def random_line(io)
  choice = io.gets; count = 1
  while line = io.gets
    rand(count += 1).zero? and choice = line
  end
  choice
end

def one_of_n(n)
  # Create a mock IO that provides line numbers instead of lines.
  # Assumes that #random_line calls #gets.
  (mock_io = Object.new).instance_eval do
    @count = 0
    @last = n
    def self.gets
      (@count < @last) ? (@count += 1) : nil
    end
  end
  random_line(mock_io)
end

chosen = Hash.new(0)
1_000_000.times { chosen[one_of_n(10)] += 1 }
chosen.keys.sort.each do |key|
  puts "#{key} chosen #{chosen[key]} times"
end


Operator precedence

Operators in C and C++}}

;Task:
Provide a list of   [[wp:order of operations|precedence   and   associativity   of all the operators and constructs that the language utilizes in descending order of precedence such that an operator which is listed on some row will be evaluated prior to any operator that is listed on a row further below it.

Operators that are in the same cell (there may be several rows of operators listed in a cell) are evaluated with the same level of precedence, in the given direction.

State whether arguments are passed by value or by reference.

Solution:
Ruby operators, by precedence (high to low), with arity (N), associativity (A), and definability (D)

{| class="wikitable"
! Operator(s)	|| N	|| A	|| D	|| Operation
|-
| ! ~ +	        || 1	|| R	|| Y	|| Boolean NOT, bitwise complement, unary plus
|-
| **	        || 2	|| R	|| Y	|| Exponentiation
|-
| -	        || 1	|| R	|| Y	|| Unary minus (define with -@)
|-
| * / %	        || 2	|| L	|| Y	|| Multiplication, division, modulo (remainder)
|-
| + -	        || 2	|| L	|| Y	|| Addition (or concatenation), subtraction
|-
| << >>	        || 2	|| L	|| Y	|| Bitwise shift-left (or append), bitwise shift-right
|-
| &	        || 2	|| L	|| Y	|| Bitwise AND
|-
| <nowiki>|</nowiki> ^	        || 2	|| L	|| Y	|| Bitwise OR, bitwise XOR
|-
| < <= >= >	|| 2	|| L	|| Y	|| Ordering
|-
| | == === !=  =~ !~ <=> 	|| 2    || N	|| Y	|| Equality, pattern matching, comparison
|-
| &&	        || 2	|| L	|| N	|| Boolean AND
|-
| <nowiki>||</nowiki>       || 2	|| L	|| N	|| Boolean OR
|-
| .. ...	|| 2	|| N	|| N	|| Range creation and Boolean flip-flops
|-
| ? :	        || 3    || R	|| N    || Conditional
|-
| rescue	|| 2	|| L	|| N	|| Exception-handling modifier
|-
| = **= *= / = %= += -= <<= >>= &&= &= ^=   || 2	|| R	|| N	|| Assignment
|-
| defined?	|| 1	|| N	|| N	|| Test variable definition and type
|-
| not	        || 1    || R    || N	|| Boolean NOT (low precedence)
|-
| and or	|| 2	|| L	|| N	|| Boolean AND, Boolean OR (low precedence)
|-
| if unless while until 	|| 2	|| N	|| N	|| Conditional and loop modifiers
|}


Padovan sequence

The Fibonacci sequence in several ways.
Some are given in the table below, and the referenced video shows some of the geometric
similarities.

::{| class="wikitable"
! Comment !! Padovan !! Fibonacci
|-
|  ||  ||
|-
| Named after. || Richard Padovan || Leonardo of Pisa: Fibonacci
|-
|  ||  ||
|-
| Recurrence initial values. || P(0)=P(1)=P(2)=1 || F(0)=0, F(1)=1
|-
| Recurrence relation. || P(n)=P(n-2)+P(n-3) || F(n)=F(n-1)+F(n-2)
|-
|  ||  ||
|-
| First 10 terms. || 1,1,1,2,2,3,4,5,7,9 || 0,1,1,2,3,5,8,13,21,34
|-
|  ||  ||
|-
| Ratio of successive terms... || Plastic ratio, p || Golden ratio, g
|-
|  || 1.324717957244746025960908854... || 1.6180339887498948482...
|-
| Exact formula of ratios p and q. || ((9+69**.5)/18)**(1/3) + ((9-69**.5)/18)**(1/3) || (1+5**0.5)/2
|-
| Ratio is real root of polynomial. || p: x**3-x-1 || g: x**2-x-1
|-
|  ||  ||
|-
| Spirally tiling the plane using. || Equilateral triangles || Squares
|-
|  ||  ||
|-
| Constants for ... || s= 1.0453567932525329623 || a=5**0.5
|-
| ... Computing by truncation. || P(n)=floor(p**(n-1) / s + .5) || F(n)=floor(g**n / a + .5)
|-
|  ||  ||
|-
| L-System Variables. || A,B,C || A,B
|-
| L-System Start/Axiom. || A || A
|-
| L-System Rules. || A->B,B->C,C->AB || A->B,B->AB
|}

;Task:
* Write a function/method/subroutine to compute successive members of the Padovan series using the recurrence relation.
* Write a function/method/subroutine to compute successive members of the Padovan series using the floor function.
* Show the first twenty terms of the sequence.
* Confirm that the recurrence and floor based functions give the same results for 64 terms,
* Write a function/method/... using the L-system to generate successive strings.
* Show the first 10 strings produced from the L-system
* Confirm that the length of the first 32 strings produced is the Padovan sequence.

Show output here, on this page.

;Ref:
* The Plastic Ratio - Numberphile video.

Solution:
padovan = Enumerator.new do |y|
  ar = [1, 1, 1]
  loop do
    ar << ar.first(2).sum
    y  << ar.shift
  end
end

P, S = 1.324717957244746025960908854, 1.0453567932525329623
def padovan_f(n) = (P**(n-1) / S + 0.5).floor

puts "Recurrence Padovan: #{padovan.take(20)}"
puts "Floor function:     #{(0...20).map{|n| padovan_f(n)}}"

n = 63
bool =  (0...n).map{|n| padovan_f(n)} == padovan.take(n)
puts "Recurrence and floor function are equal upto #{n}: #{bool}."
puts

def l_system(axiom = "A", rules = {"A" => "B", "B" => "C", "C" => "AB"} )
  return enum_for(__method__,  axiom, rules) unless block_given?
  loop do
    yield axiom
    axiom = axiom.chars.map{|c| rules[c] }.join
  end
end

puts "First 10 elements of L-system: #{l_system.take(10).join(", ")} "
n = 32
bool = l_system.take(n).map(&:size) == padovan.take(n)
puts "Sizes of first #{n} l_system strings equal to recurrence padovan? #{bool}."


Palindrome dates

Today   ('''2020-02-02''',   at the time of this writing)   happens to be a palindrome,   without the hyphens,   not only for those countries which express their dates in the   '''yyyy-mm-dd'''   format but,   unusually,   also for countries which use the   '''dd-mm-yyyy'''   format.

;Task
Write a program which calculates and shows the next 15 palindromic dates for those countries which express their dates in the   '''yyyy-mm-dd'''   format.

Solution:
require 'date'

palindate = Enumerator.new do |yielder|
  ("2020"..).each do |y|
    m, d = y.reverse.scan(/../) # let the Y10K kids handle 5 digit years
    strings = [y, m, d]
    yielder << strings.join("-") if Date.valid_date?( *strings.map( &:to_i ) )
  end
end

puts palindate.take(15)


Palindromic gapful numbers

Numbers   (positive integers expressed in base ten)   that are (evenly) divisible by the number formed by the
first and last digit are known as   '''gapful numbers'''.

''Evenly divisible''   means divisible with   no   remainder.

All   one-   and two-digit   numbers have this property and are trivially excluded.   Only
numbers    >=  '''100'''   will be considered for this Rosetta Code task.

;Example:
'''1037'''   is a   '''gapful'''   number because it is evenly divisible by the
number   '''17'''   which is formed by the first and last decimal digits
of    '''1037'''.

A palindromic number is   (for this task, a positive integer expressed in base ten),   when the number is
reversed,   is the same as the original number.

;Task:
:*   Show   (nine sets)   the first   '''20'''   palindromic gapful numbers that   ''end''   with:
:::*   the digit   '''1'''
:::*   the digit   '''2'''
:::*   the digit   '''3'''
:::*   the digit   '''4'''
:::*   the digit   '''5'''
:::*   the digit   '''6'''
:::*   the digit   '''7'''
:::*   the digit   '''8'''
:::*   the digit   '''9'''
:*   Show   (nine sets, like above)   of palindromic gapful numbers:
:::*   the last   '''15'''   palindromic gapful numbers   (out of      '''100''')
:::*   the last   '''10'''   palindromic gapful numbers   (out of                '''1,000''')       {optional}

For other ways of expressing the (above) requirements, see the   ''discussion''   page.

;Note:
All palindromic gapful numbers are divisible by eleven.

;Related tasks:
:*   palindrome detection.
:*   gapful numbers.

;Also see:
:*   The OEIS entry:   A108343 gapful numbers.

Solution:
class PalindromicGapfuls
  include Enumerable

  def initialize(digit)
    @digit = digit
    @nn = @digit * 11                 # digit gapful divisor: 11, 22,...88, 99
  end

  def each
    power = 1                         # these two lines will work
    while power += 1                  # for all Ruby VMs|versions
    #(2..).each do |power|            # Ruby => 2.6; can replace above 2 lines
      base    = 10**(power >> 1)      # value of middle digit position: 10..
      base11  = base * 11             # value of middle two digits positions: 110..
      this_lo = base * @digit         # starting half for this digit: 10.. to  90..
      next_lo = base * (@digit + 1)   # starting half for next digit: 20.. to 100..
      this_lo.step(to: next_lo - 1, by: 10) do |front_half| # d_00; d_10; d_20; ...
        left_half = front_half.to_s; right_half = left_half.reverse
        if power.odd?
          palindrome = (left_half + right_half).to_i
          10.times do
            yield palindrome if palindrome % @nn == 0
            palindrome += base11
          end
        else
          palindrome = (left_half.chop + right_half).to_i
          10.times do
            yield palindrome if palindrome % @nn == 0
            palindrome += base
          end
        end
      end
    end
  end

  # Optimized output method: only keep desired values.
  def keep_from(count, keep)
    to_skip = (count - keep)
    kept = []
    each_with_index do |value, i|
      i < to_skip ? next : kept << value
      return kept if kept.size == keep
    end
  end
end

start = Time.now

count, keep = 20, 20
puts "First 20 palindromic gapful numbers ending with:"
1.upto(9) { |digit| puts "#{digit} : #{PalindromicGapfuls.new(digit).keep_from(count, keep)}" }

count, keep = 100, 15
puts "\nLast 15 of first 100 palindromic gapful numbers ending in:"
1.upto(9) { |digit| puts "#{digit} : #{PalindromicGapfuls.new(digit).keep_from(count, keep)}" }

count, keep = 1_000, 10
puts "\nLast 10 of first 1000 palindromic gapful numbers ending in:"
1.upto(9) { |digit| puts "#{digit} : #{PalindromicGapfuls.new(digit).keep_from(count, keep)}" }

count, keep = 100_000, 1
puts "\n100,000th palindromic gapful number ending with:"
1.upto(9) { |digit| puts "#{digit} : #{PalindromicGapfuls.new(digit).keep_from(count, keep)}" }

count, keep = 1_000_000, 1
puts "\n1,000,000th palindromic gapful number ending with:"
1.upto(9) { |digit| puts "#{digit} : #{PalindromicGapfuls.new(digit).keep_from(count, keep)}" }

count, keep = 10_000_000, 1
puts "\n10,000,000th palindromic gapful number ending with:"
1.upto(9) { |digit| puts "#{digit} : #{PalindromicGapfuls.new(digit).keep_from(count, keep)}" }

puts (Time.now - start)


Palindromic gapful numbers

Solution:
class PalNo
  def initialize(set)
    @set, @l=set, 3
  end
  def fN(n)
    return [0,1,2,3,4,5,6,7,8,9] if n==1
    return [0,11,22,33,44,55,66,77,88,99] if n==2
    a=[]; [0,1,2,3,4,5,6,7,8,9].product(fN(n-2)).each{|g| a.push(g[0]*10**(n-1)+g[0]+10*g[1])}; return a
  end
  def each
    while true do fN(@l-2).each{|g| a=@set*10**(@l-1)+@set+10*g; yield a if a%(11*@set)==0}; @l+=1 end
  end
end

for n in 1..9 do palNo=PalNo.new(n); g=1; palNo.each{|n| print "#{n} "; g+=1; break unless g<21}; puts "" end; puts "####"
for n in 1..9 do palNo=PalNo.new(n); g=1; palNo.each{|n| print "#{n} " if g>85; g+=1; break unless g<101}; puts "" end; puts "####"
for n in 1..9 do palNo=PalNo.new(n); g=1; palNo.each{|n| print "#{n} " if g>990; g+=1; break unless g<1001}; puts "" end; puts "####"


Palindromic gapful numbers

Solution:
class PalNo
  def initialize(digit)
    @digit, @l, @dd = digit, 3, 11*digit
  end
  def fN(n)
    return [0,1,2,3,4,5,6,7,8,9] if n==1
    return [0,11,22,33,44,55,66,77,88,99] if n==2
    a=[]; [0,1,2,3,4,5,6,7,8,9].product(fN(n-2)).each{ |g0,g1| a << g0*10**(n-1)+g0+10*g1 }; return a
  end
  def show(count, keep)
    to_skip, palcnt, pals = count - keep, 0, []
    while palcnt < count
      fN(@l-2).each{ |g| pal=@digit*10**(@l-1)+@digit+10*g;
      pals << pal if pal%(@dd)==0 && (palcnt += 1) > to_skip; break if palcnt - to_skip == keep }; @l+=1
    end
    print pals; puts
  end
end

start = Time.now

(1..9).each { |digit| PalNo.new(digit).show(20, 20) }; puts "####"
(1..9).each { |digit| PalNo.new(digit).show(100, 15) }; puts "####"
(1..9).each { |digit| PalNo.new(digit).show(1000, 10) }; puts "####"
(1..9).each { |digit| PalNo.new(digit).show(100_000, 1) }; puts "####"
(1..9).each { |digit| PalNo.new(digit).show(1_000_000, 1) }; puts "####"
(1..9).each { |digit| PalNo.new(digit).show(10_000_000, 1) }; puts "####"

puts (Time.now - start)


Pancake numbers

Adrian Monk has problems and an assistant,  Sharona Fleming. Sharona can deal with most of Adrian's problems except his lack of punctuality paying her remuneration. 2 pay checks down and she prepares him pancakes for breakfast. Knowing that he will be unable to eat them unless they are stacked in ascending order of size she leaves him only a skillet which he can insert at any point in the pile and flip all the above pancakes, repeating until the pile is sorted. Sharona has left the pile of n pancakes such that the maximum number of flips is required. Adrian is determined to do this in as few flips as possible. This sequence n->p(n) is known as the Pancake numbers.

The task is to determine p(n) for n = 1 to 9, and for each show an example requiring p(n) flips.

[[Sorting_algorithms/Pancake_sort]] actually performs the sort some giving the number of flips used. How do these compare with p(n)?

Few people know p(20), generously I shall award an extra credit for anyone doing more than p(16).

;References
# Bill Gates and the pancake problem
# A058986

Solution:
def pancake(n)
    gap = 2
    sum = 2
    adj = -1
    while sum < n
        adj = adj + 1
        gap = gap * 2 - 1
        sum = sum + gap
    end
    return n + adj
end

for i in 0 .. 3
    for j in 1 .. 5
        n = i * 5 + j
        print "p(%2d) = %2d  " % [n, pancake(n)]
    end
    print "\n"
end


Pangram checker

A pangram is a sentence that contains all the letters of the English alphabet at least once.

For example:   ''The quick brown fox jumps over the lazy dog''.

;Task:
Write a function or method to check a sentence to see if it is a   pangram   (or not)   and show its use.

;Related tasks:
:*   determine if a string has all the same characters
:*   determine if a string has all unique characters

Solution:
def pangram?(sentence)
  s = sentence.downcase
  ('a'..'z').all? {|char| s.include? (char) }
end

p pangram?('this is a sentence')  # ==> false
p pangram?('The quick brown fox jumps over the lazy dog.')  # ==> true


Paraffins

This organic chemistry task is essentially to implement a tree enumeration algorithm.

;Task:
Enumerate, without repetitions and in order of increasing size, all possible paraffin molecules (also known as alkanes).

Paraffins are built up using only carbon atoms, which has four bonds, and hydrogen, which has one bond.   All bonds for each atom must be used, so it is easiest to think of an alkane as linked carbon atoms forming the "backbone" structure, with adding hydrogen atoms linking the remaining unused bonds.

In a paraffin, one is allowed neither double bonds (two bonds between the same pair of atoms), nor cycles of linked carbons.   So all paraffins with   '''n'''   carbon atoms share the empirical formula     CnH2n+2

But for all   '''n''' >= 4   there are several distinct molecules ("isomers") with the same formula but different structures.

The number of isomers rises rather rapidly when   '''n'''   increases.

In counting isomers it should be borne in mind that the four bond positions on a given carbon atom can be freely interchanged and bonds rotated (including 3-D "out of the paper" rotations when it's being observed on a flat diagram),   so rotations or re-orientations of parts of the molecule (without breaking bonds) do not give different isomers.   So what seem at first to be different molecules may in fact turn out to be different orientations of the same molecule.

;Example:
With   '''n''' = 3   there is only one way of linking the carbons despite the different orientations the molecule can be drawn;   and with   '''n''' = 4   there are two configurations:
:::*   a   straight   chain:     (CH3)(CH2)(CH2)(CH3)
:::*   a        branched chain:       (CH3)(CH(CH3))(CH3)

Due to bond rotations, it doesn't matter which direction the branch points in.

The phenomenon of "stereo-isomerism" (a molecule being different from its mirror image due to the actual 3-D arrangement of bonds) is ignored for the purpose of this task.

The input is the number   '''n'''   of carbon atoms of a molecule (for instance '''17''').

The output is how many different different paraffins there are with   '''n'''   carbon atoms  (for instance   24,894   if   '''n''' = 17).

The sequence of those results is visible in the OEIS entry:
:::   A00602: number of n-node unrooted quartic trees; number of n-carbon alkanes C(n)H(2n+2) ignoring stereoisomers.

The sequence is (the index starts from zero, and represents the number of carbon atoms):

 1, 1, 1, 1, 2, 3, 5, 9, 18, 35, 75, 159, 355, 802, 1858, 4347, 10359,
 24894, 60523, 148284, 366319, 910726, 2278658, 5731580, 14490245,
 36797588, 93839412, 240215803, 617105614, 1590507121, 4111846763,
 10660307791, 27711253769, ...

;Extra credit:
Show the paraffins in some way.

A flat 1D representation, with arrays or lists is enough, for instance:

*Main> all_paraffins 1
                        [CCP H H H H]
*Main> all_paraffins 2
                        [BCP (C H H H) (C H H H)]
*Main> all_paraffins 3
                        [CCP H H (C H H H) (C H H H)]
*Main> all_paraffins 4
                        [BCP (C H H (C H H H)) (C H H (C H H H)),
                         CCP H (C H H H) (C H H H) (C H H H)]
*Main> all_paraffins 5
                        [CCP H H (C H H (C H H H)) (C H H (C H H H)),
                         CCP H (C H H H) (C H H H) (C H H (C H H H)),
                         CCP (C H H H) (C H H H) (C H H H) (C H H H)]
*Main> all_paraffins 6
                        [BCP (C H H (C H H (C H H H))) (C H H (C H H (C H H H))),
                         BCP (C H H (C H H (C H H H))) (C H (C H H H) (C H H H)),
                         BCP (C H (C H H H) (C H H H)) (C H (C H H H) (C H H H)),
                         CCP H (C H H H) (C H H (C H H H)) (C H H (C H H H)),
                         CCP (C H H H) (C H H H) (C H H H) (C H H (C H H H))]
Showing a basic 2D ASCII-art representation of the paraffins is better; for instance (molecule names aren't necessary):
       methane          ethane               propane               isobutane

          H              H   H              H   H   H              H   H   H
          |              |   |              |   |   |              |   |   |
      H - C - H      H - C - C - H      H - C - C - C - H      H - C - C - C - H
          |              |   |              |   |   |              |   |   |
          H              H   H              H   H   H              H   |   H
                                                                       |
                                                                   H - C - H
                                                                       |
                                                                       H

;Links:
*   A paper that explains the problem and its solution in a functional language:
http://www.cs.wright.edu/~tkprasad/courses/cs776/paraffins-turner.pdf

*   A Haskell implementation:
https://github.com/ghc/nofib/blob/master/imaginary/paraffins/Main.hs

*   A Scheme implementation:
http://www.ccs.neu.edu/home/will/Twobit/src/paraffins.scm

*   A Fortress implementation:         (this site has been closed)
http://java.net/projects/projectfortress/sources/sources/content/ProjectFortress/demos/turnersParaffins0.fss?rev=3005

Solution:
MAX_N = 500
BRANCH = 4

def tree(br, n, l=n, sum=1, cnt=1)
  for b in br+1 .. BRANCH
    sum += n
    return if sum >= MAX_N
    # prevent unneeded long math
    return if l * 2 >= sum and b >= BRANCH
    if b == br + 1
      c = $ra[n] * cnt
    else
      c = c * ($ra[n] + (b - br - 1)) / (b - br)
    end
    $unrooted[sum] += c if l * 2 < sum
    next if b >= BRANCH
    $ra[sum] += c
    (1...n).each {|m| tree(b, m, l, sum, c)}
  end
end

def bicenter(s)
  return if s.odd?
  aux = $ra[s / 2]
  $unrooted[s] += aux * (aux + 1) / 2
end

$ra       = [0] * MAX_N
$unrooted = [0] * MAX_N

$ra[0] = $ra[1] = $unrooted[0] = $unrooted[1] = 1
for n in 1...MAX_N
  tree(0, n)
  bicenter(n)
  puts "%d: %d" % [n, $unrooted[n]]
end


Parse an IP Address

The purpose of this task is to demonstrate parsing of text-format IP addresses, using IPv4 and IPv6.

Taking the following as inputs:
::: {| border="5" cellspacing="0" cellpadding=2
|-
|127.0.0.1
|The "localhost" IPv4 address
|-
|127.0.0.1:80
|The "localhost" IPv4 address, with a specified port (80)
|-
|::1
|The "localhost" IPv6 address
|-
|[::1]:80
|The "localhost" IPv6 address, with a specified port (80)
|-
|2605:2700:0:3::4713:93e3
|Rosetta Code's primary server's public IPv6 address
|-
|[2605:2700:0:3::4713:93e3]:80
|Rosetta Code's primary server's public IPv6 address, with a specified port (80)
|}

;Task:
Emit each described IP address as a hexadecimal integer representing the address, the address space, and the port number specified, if any.

In languages where variant result types are clumsy, the result should be ipv4 or ipv6 address number, something which says which address space was represented, port number and something that says if the port was specified.

;Example:
'''127.0.0.1'''   has the address number   '''7F000001'''   (2130706433 decimal)
in the ipv4 address space.

'''::ffff:127.0.0.1'''   represents the same address in the ipv6 address space where it has the
address number    '''FFFF7F000001'''   (281472812449793 decimal).

'''::1'''   has address number   '''1'''   and serves the same purpose in the ipv6 address
space that   '''127.0.0.1'''   serves in the ipv4 address space.

Solution:
require 'ipaddr'

TESTCASES = ["127.0.0.1",                "127.0.0.1:80",
                "::1",                      "[::1]:80",
                "2605:2700:0:3::4713:93e3", "[2605:2700:0:3::4713:93e3]:80"]

output = [%w(String Address Port Family Hex),
          %w(------ ------- ---- ------ ---)]

def output_table(rows)
  widths = []
  rows.each {|row| row.each_with_index {|col, i| widths[i] = [widths[i].to_i, col.to_s.length].max }}
  format = widths.map {|size| "%#{size}s"}.join("\t")
  rows.each {|row| puts format % row}
end

TESTCASES.each do |str|
  case str  # handle port; IPAddr does not.
  when /\A\[(?<address> .* )\]:(?<port> \d+ )\z/x      # string like "[::1]:80"
    address, port = $~[:address], $~[:port]
  when /\A(?<address> [^:]+ ):(?<port> \d+ )\z/x       # string like "127.0.0.1:80"
    address, port = $~[:address], $~[:port]
  else                                                 # string with no port number
    address, port = str, nil
  end

  ip_addr = IPAddr.new(address)
  family = "IPv4" if ip_addr.ipv4?
  family = "IPv6" if ip_addr.ipv6?

  output << [str, ip_addr.to_s, port.to_s, family, ip_addr.to_i.to_s(16)]
end

output_table(output)


Parsing/RPN calculator algorithm

Create a stack-based evaluator for an expression in   reverse Polish notation (RPN)   that also shows the changes in the stack as each individual token is processed ''as a table''.

* Assume an input of a correct, space separated, string of tokens of an RPN expression
* Test with the RPN expression generated from the   [[Parsing/Shunting-yard algorithm]]   task:
         3 4 2 * 1 5 - 2 3 ^ ^ / +
* Print or display the output here

;Notes:
*    '''^'''    means exponentiation in the expression above.
*    '''/'''    means division.

;See also:
*   [[Parsing/Shunting-yard algorithm]] for a method of generating an RPN from an infix expression.
*   Several solutions to [[24 game/Solve]] make use of RPN evaluators (although tracing how they work is not a part of that task).
*   [[Parsing/RPN to infix conversion]].
*   [[Arithmetic evaluation]].

Solution:
rpn = RPNExpression("3 4 2 * 1 5 - 2 3 ^ ^ / +")
value = rpn.eval


Parsing/Shunting-yard algorithm

Given the operator characteristics and input from the Shunting-yard algorithm page and tables, use the algorithm to show the changes in the operator stack and RPN output
as each individual token is processed.

* Assume an input of a correct, space separated, string of tokens representing an infix expression
* Generate a space separated output string representing the RPN
* Test with the input string:
::::  3 + 4 * 2 / ( 1 - 5 ) ^ 2 ^ 3
* print and display the output here.
* Operator precedence is given in this table:
:{| class="wikitable"

! operator !! associativity !! operation
|- || align="center"
|                     ^   ||  4  ||  right  ||  exponentiation
|- || align="center"
|                     *   ||  3  ||  left   ||  multiplication
|- || align="center"
|                     /   ||  3  ||  left   ||  division
|- || align="center"
|                     +   ||  2  ||  left   ||  addition
|- || align="center"
|                     -   ||  2  ||  left   ||  subtraction
|}

;Extra credit
Add extra text explaining the actions and an optional comment for the action on receipt of each token.

;Note
The handling of functions and arguments is not required.

;See also:
* [[Parsing/RPN calculator algorithm]] for a method of calculating a final value from this output RPN expression.
* [[Parsing/RPN to infix conversion]].

Solution: rpn = RPNExpression.from_infix("3 + 4 * 2 / ( 1 - 5 ) ^ 2 ^ 3")


Pascal's triangle/Puzzle

This puzzle involves a Pascals Triangle, also known as a Pyramid of Numbers.

           [ 151]
          [  ][  ]
        [40][  ][  ]
      [  ][  ][  ][  ]
    [ X][11][ Y][ 4][ Z]

Each brick of the pyramid is the sum of the two bricks situated below it.
Of the three missing numbers at the base of the pyramid,
the middle one is the sum of the other two (that is, Y = X + Z).

;Task:
Write a program to find a solution to this puzzle.

Solution:
require 'rref'

pyramid = [
           [ 151],
          [nil,nil],
        [40,nil,nil],
      [nil,nil,nil,nil],
    ["x", 11,"y", 4,"z"]
]
pyramid.each{|row| p row}

equations = [[1,-1,1,0]]   # y = x + z

def parse_equation(str)
  eqn = [0] * 4
  lhs, rhs = str.split("=")
  eqn[3] = rhs.to_i
  for term in lhs.split("+")
    case term
    when "x" then eqn[0] += 1
    when "y" then eqn[1] += 1
    when "z" then eqn[2] += 1
    else          eqn[3] -= term.to_i
    end
  end
  eqn
end

-2.downto(-5) do |row|
  pyramid[row].each_index do |col|
    val = pyramid[row][col]
    sum = "%s+%s" % [pyramid[row+1][col], pyramid[row+1][col+1]]
    if val.nil?
      pyramid[row][col] = sum
    else
      equations << parse_equation(sum + "=#{val}")
    end
  end
end

reduced = convert_to(reduced_row_echelon_form(equations), :to_i)

for eqn in reduced
  if eqn[0] + eqn[1] + eqn[2] != 1
    fail "no unique solution! #{equations.inspect} ==> #{reduced.inspect}"
  elsif eqn[0] == 1 then x = eqn[3]
  elsif eqn[1] == 1 then y = eqn[3]
  elsif eqn[2] == 1 then z = eqn[3]
  end
end

puts
puts "x == #{x}"
puts "y == #{y}"
puts "z == #{z}"

answer = []
for row in pyramid
  answer << row.collect {|cell| eval cell.to_s}
end
puts
answer.each{|row| p row}


Pascal matrix generation

A pascal matrix is a two-dimensional square matrix holding numbers from   binomial coefficients   and which can be shown as    nCr.

Shown below are truncated   5-by-5   matrices   M[i, j]   for   i,j   in range   0..4.

A Pascal upper-triangular matrix that is populated with   jCi:

[[1, 1, 1, 1, 1],
 [0, 1, 2, 3, 4],
 [0, 0, 1, 3, 6],
 [0, 0, 0, 1, 4],
 [0, 0, 0, 0, 1]]

A Pascal lower-triangular matrix that is populated with   iCj   (the transpose of the upper-triangular matrix):

[[1, 0, 0, 0, 0],
 [1, 1, 0, 0, 0],
 [1, 2, 1, 0, 0],
 [1, 3, 3, 1, 0],
 [1, 4, 6, 4, 1]]

A Pascal symmetric matrix that is populated with   i+jCi:

[[1, 1, 1, 1, 1],
 [1, 2, 3, 4, 5],
 [1, 3, 6, 10, 15],
 [1, 4, 10, 20, 35],
 [1, 5, 15, 35, 70]]

;Task:
Write functions capable of generating each of the three forms of   n-by-n   matrices.

Use those functions to display upper, lower, and symmetric Pascal   5-by-5   matrices on this page.

The output should distinguish between different matrices and the rows of each matrix   (no showing a list of 25 numbers assuming the reader should split it into rows).

;Note:
The   [[Cholesky decomposition]]   of a Pascal symmetric matrix is the Pascal lower-triangle matrix of the same size.

Solution:
#Upper, lower, and symetric Pascal Matrix - Nigel Galloway: May 3rd., 21015
require 'pp'

ng = (g = 0..4).collect{[]}
g.each{|i| g.each{|j| ng[i][j] = i==0 ? 1 : j<i ? 0 : ng[i-1][j-1]+ng[i][j-1]}}
pp ng; puts
g.each{|i| g.each{|j| ng[i][j] = j==0 ? 1 : i<j ? 0 : ng[i-1][j-1]+ng[i-1][j]}}
pp ng; puts
g.each{|i| g.each{|j| ng[i][j] = (i==0 or j==0) ? 1 : ng[i-1][j  ]+ng[i][j-1]}}
pp ng


Password generator

Create a password generation program which will generate passwords containing random ASCII characters from the following groups:
          lower-case letters:  a --> z
          upper-case letters:  A --> Z
                      digits:  0 --> 9
  other printable characters:  !"#$%&'()*+,-./:;<=>?@[]^_{|}~
  (the above character list excludes white-space, backslash and grave)

The generated password(s) must include   ''at least one''   (of each of the four groups):
    lower-case letter,
    upper-case letter,
    digit  (numeral),   and
    one  "other"  character.

The user must be able to specify the password length and the number of passwords to generate.

The passwords should be displayed or written to a file, one per line.

The randomness should be from a system source or library.

The program should implement a help option or button which should describe the program and options when invoked.

You may also allow the user to specify a seed value, and give the option of excluding visually similar characters.

For example:            Il1     O0     5S     2Z            where the characters are:
::::*   capital eye, lowercase ell, the digit one
::::*   capital oh, the digit zero
::::*   the digit five, capital ess
::::*   the digit two, capital zee

Solution:
ARRS = [("a".."z").to_a,
        ("A".."Z").to_a,
        ("0".."9").to_a,
        %q(!"#$%&'()*+,-./:;<=>?@[]^_{|}~).chars] # " quote to reset clumsy code colorizer
ALL  = ARRS.flatten

def generate_pwd(size, num)
  raise ArgumentError, "Desired size too small" unless size >= ARRS.size
  num.times.map do
    arr = ARRS.map(&:sample)
    (size - ARRS.size).times{ arr << ALL.sample}
    arr.shuffle.join
  end
end

puts generate_pwd(8,3)


Pathological floating point problems

Most programmers are familiar with the inexactness of floating point calculations in a binary processor.

The classic example being:

0.1 + 0.2 =  0.30000000000000004

In many situations the amount of error in such calculations is very small and can be overlooked or eliminated with rounding.

There are pathological problems however, where seemingly simple, straight-forward calculations are extremely sensitive to even tiny amounts of imprecision.

This task's purpose is to show how your language deals with such classes of problems.

'''A sequence that seems to converge to a wrong limit.'''

Consider the sequence:
::::::   v1 =  2
::::::   v2 = -4
::::::   vn = 111   -   1130   /   vn-1   +   3000  /   (vn-1 * vn-2)

As   '''n'''   grows larger, the series should converge to   '''6'''   but small amounts of error will cause it to approach   '''100'''.

;Task 1:
Display the values of the sequence where   n =   3, 4, 5, 6, 7, 8, 20, 30, 50 & 100   to at least '''16''' decimal places.

    n = 3     18.5
    n = 4      9.378378
    n = 5      7.801153
    n = 6      7.154414
    n = 7      6.806785
    n = 8      6.5926328
    n = 20     6.0435521101892689
    n = 30     6.006786093031205758530554
    n = 50     6.0001758466271871889456140207471954695237
    n = 100    6.000000019319477929104086803403585715024350675436952458072592750856521767230266

;Task 2:
'''The Chaotic Bank Society'''   is offering a new investment account to their customers.

You first deposit   $e - 1   where   e   is   2.7182818...   the base of natural logarithms.

After each year, your account balance will be multiplied by the number of years that have passed, and $1 in service charges will be removed.

So ...
::* after 1 year, your balance will be multiplied by 1 and $1 will be removed for service charges.
::* after 2 years your balance will be doubled and $1 removed.
::* after 3 years your balance will be tripled and $1 removed.
::*  ...
::* after 10 years, multiplied by 10 and $1 removed,  and so on.

What will your balance be after   25   years?
    Starting balance: $e-1
    Balance = (Balance * year) - 1 for 25 years
    Balance after 25 years: $0.0399387296732302

;Task 3, extra credit:
'''Siegfried Rump's example.'''   Consider the following function, designed by Siegfried Rump in 1988.
::::::   f(a,b) = 333.75b6 + a2( 11a2b2 - b6 - 121b4 - 2 ) + 5.5b8 + a/(2b)
::::::  compute    f(a,b)    where    a=77617.0    and    b=33096.0
::::::   f(77617.0, 33096.0)   =   -0.827396059946821

Demonstrate how to solve at least one of the first two problems, or both, and the third if you're feeling particularly jaunty.

;See also;
*   Floating-Point Arithmetic   Section 1.3.2 Difficult problems.

Solution:
ar = [0, 2, -4]
100.times{ar << (111 - 1130.quo(ar[-1])+ 3000.quo(ar[-1]*ar[-2])) }

[3, 4, 5, 6, 7, 8, 20, 30, 50, 100].each do |n|
  puts "%3d -> %0.16f" % [n, ar[n]]
end


Peaceful chess queen armies

In chess, a queen attacks positions from where it is, in straight lines up-down and left-right as well as on both its diagonals. It attacks only pieces ''not'' of its own colour.

\
|
/

=
=

=
=

/
|
\

/

|

\

|

The goal of Peaceful chess queen armies is to arrange m black queens and m white queens on an n-by-n square grid, (the board), so that ''no queen attacks another of a different colour''.

;Task:
# Create a routine to represent two-colour queens on a 2-D board. (Alternating black/white background colours, Unicode chess pieces and other embellishments are not necessary, but may be used at your discretion).
# Create a routine to generate at least one solution to placing m equal numbers of black and white queens on an n square board.
# Display here results for the m=4, n=5 case.

;References:
* Peaceably Coexisting Armies of Queens (Pdf) by Robert A. Bosch. Optima, the Mathematical Programming Socity newsletter, issue 62.
* A250000 OEIS

Solution:
class Position
    attr_reader :x, :y

    def initialize(x, y)
        @x = x
        @y = y
    end

    def ==(other)
        self.x == other.x &&
        self.y == other.y
    end

    def to_s
        '(%d, %d)' % [@x, @y]
    end

    def to_str
        to_s
    end
end

def isAttacking(queen, pos)
    return queen.x == pos.x ||
           queen.y == pos.y ||
           (queen.x - pos.x).abs() == (queen.y - pos.y).abs()
end

def place(m, n, blackQueens, whiteQueens)
    if m == 0 then
        return true
    end
    placingBlack = true
    for i in 0 .. n-1
        for j in 0 .. n-1
            catch :inner do
                pos = Position.new(i, j)
                for queen in blackQueens
                    if pos == queen || !placingBlack && isAttacking(queen, pos) then
                        throw :inner
                    end
                end
                for queen in whiteQueens
                    if pos == queen || placingBlack && isAttacking(queen, pos) then
                        throw :inner
                    end
                end
                if placingBlack then
                    blackQueens << pos
                    placingBlack = false
                else
                    whiteQueens << pos
                    if place(m - 1, n, blackQueens, whiteQueens) then
                        return true
                    end
                    blackQueens.pop
                    whiteQueens.pop
                    placingBlack = true
                end
            end
        end
    end
    if !placingBlack then
        blackQueens.pop
    end
    return false
end

def printBoard(n, blackQueens, whiteQueens)
    # initialize the board
    board = Array.new(n) { Array.new(n) { ' ' } }
    for i in 0 .. n-1
        for j in 0 .. n-1
            if i % 2 == j % 2 then
                board[i][j] = '•'
            else
                board[i][j] = '◦'
            end
        end
    end

    # insert the queens
    for queen in blackQueens
        board[queen.y][queen.x] = 'B'
    end
    for queen in whiteQueens
        board[queen.y][queen.x] = 'W'
    end

    # print the board
    for row in board
        for cell in row
            print cell, ' '
        end
        print "\n"
    end
    print "\n"
end

nms = [
    [2, 1],
    [3, 1], [3, 2],
    [4, 1], [4, 2], [4, 3],
    [5, 1], [5, 2], [5, 3], [5, 4], [5, 5],
    [6, 1], [6, 2], [6, 3], [6, 4], [6, 5], [6, 6],
    [7, 1], [7, 2], [7, 3], [7, 4], [7, 5], [7, 6], [7, 7]
]
for nm in nms
    m = nm[1]
    n = nm[0]
    print "%d black and %d white queens on a %d x %d board:\n" % [m, m, n, n]

    blackQueens = []
    whiteQueens = []
    if place(m, n, blackQueens, whiteQueens) then
        printBoard(n, blackQueens, whiteQueens)
    else
        print "No solution exists.\n\n"
    end
end


Perfect shuffle

A perfect shuffle (or faro/weave shuffle) means splitting a deck of cards into equal halves, and perfectly interleaving them - so that you end up with the first card from the left half, followed by the first card from the right half, and so on:

::: 7 8 9 J Q K-7  8  9  J  Q  K-7 J 8 Q 9 K

When you repeatedly perform perfect shuffles on an even-sized deck of unique cards, it will at some point arrive back at its original order. How many shuffles this takes, depends solely on the number of cards in the deck - for example for a deck of eight cards it takes three shuffles:

::::: {| style="border-spacing:0.5em 0;border-collapse:separate;margin:0 1em;text-align:right"
|-
| ''original:'' ||
1
2
3
4
5
6
7
8
|-
| ''after 1st shuffle:'' ||
1
5
2
6
3
7
4
8
|-
| ''after 2nd shuffle:'' ||
1
3
5
7
2
4
6
8
|-
| ''after 3rd shuffle:'' ||
1
2
3
4
5
6
7
8
|}

'''''The Task'''''

# Write a function that can perform a perfect shuffle on an even-sized list of values.
# Call this function repeatedly to count how many shuffles are needed to get a deck back to its original order, for each of the deck sizes listed under "Test Cases" below.
#* You can use a list of numbers (or anything else that's convenient) to represent a deck; just make sure that all "cards" are unique within each deck.
#* Print out the resulting shuffle counts, to demonstrate that your program passes the test-cases.
'''''Test Cases'''''

::::: {| class="wikitable"
|-
! input ''(deck size)'' !! output ''(number of shuffles required)''
|-
| 8 || 3
|-
| 24 || 11
|-
| 52 || 8
|-
| 100 || 30
|-
| 1020 || 1018
|-
| 1024 || 10
|-
| 10000 || 300
|}

Solution:
def perfect_shuffle(deck_size = 52)
  deck     = (1..deck_size).to_a
  original = deck.dup
  half     = deck_size / 2
  1.step do |i|
    deck = deck.first(half).zip(deck.last(half)).flatten
    return i if deck == original
  end
end

[8, 24, 52, 100, 1020, 1024, 10000].each {|i| puts "Perfect shuffles required for deck size #{i}: #{perfect_shuffle(i)}"}


Perfect totient numbers

Generate and show here, the first twenty Perfect totient numbers.

;Related task:
::*   [[Totient function]]

;Also see:
::*   the OEIS      entry for   perfect totient numbers.
::*   mrob            list of the first 54

Solution:
require "prime"

class Integer

  def φ
    prime_division.inject(1) {|res, (pr, exp)| res *= (pr-1) * pr**(exp-1) }
  end

  def perfect_totient?
    f, sum = self, 0
    until f == 1 do
      f = f.φ
      sum += f
    end
    self == sum
  end

end

puts (1..).lazy.select(&:perfect_totient?).first(20).join(", ")


Permutations/Derangements

A derangement is a permutation of the order of distinct items in which ''no item appears in its original place''.

For example, the only two derangements of the three items (0, 1, 2) are (1, 2, 0), and (2, 0, 1).

The number of derangements of ''n'' distinct items is known as the subfactorial of ''n'', sometimes written as !''n''.
There are various ways to calculate !''n''.

;Task:
# Create a named function/method/subroutine/... to generate derangements of the integers ''0..n-1'', (or ''1..n'' if you prefer).
# Generate ''and show'' all the derangements of 4 integers using the above routine.
# Create a function that calculates the subfactorial of ''n'', !''n''.
# Print and show a table of the ''counted'' number of derangements of ''n'' vs. the calculated !''n'' for n from 0..9 inclusive.

;Optional stretch goal:
*   Calculate    !''20''

;Related tasks:
*   [[Anagrams/Deranged anagrams]]
*   [[Best shuffle]]
*   [[Left_factorials]]

Solution:
def derangements(n)
  ary = (1 .. n).to_a
  ary.permutation.select do |perm|
    ary.zip(perm).all? {|a,b| a != b}
  end
end

def subfact(n)
  case n
  when 0 then 1
  when 1 then 0
  else (n-1)*(subfact(n-1) + subfact(n-2))
  end
end

puts "derangements for n = 4"
derangements(4).each{|d|p d}

puts "\n n   derange  subfact"
(0..9).each do |n|
  puts "%2d :%8d,%8d" % [n, derangements(n).size, subfact(n)]
end

puts "\nNumber of derangements"
(10..20).each do |n|
  puts "#{n} : #{subfact(n)}"
end


Permutations/Rank of a permutation

A particular ranking of a permutation associates an integer with a particular ordering of all the permutations of a set of distinct items.
For our purposes the ranking will assign integers 0 .. (n! - 1) to an ordering of all the permutations of the integers 0 .. (n - 1).

For example, the permutations of the digits zero to 3 arranged lexicographically have the following rank:

  PERMUTATION      RANK
  (0, 1, 2, 3) ->  0
  (0, 1, 3, 2) ->  1
  (0, 2, 1, 3) ->  2
  (0, 2, 3, 1) ->  3
  (0, 3, 1, 2) ->  4
  (0, 3, 2, 1) ->  5
  (1, 0, 2, 3) ->  6
  (1, 0, 3, 2) ->  7
  (1, 2, 0, 3) ->  8
  (1, 2, 3, 0) ->  9
  (1, 3, 0, 2) -> 10
  (1, 3, 2, 0) -> 11
  (2, 0, 1, 3) -> 12
  (2, 0, 3, 1) -> 13
  (2, 1, 0, 3) -> 14
  (2, 1, 3, 0) -> 15
  (2, 3, 0, 1) -> 16
  (2, 3, 1, 0) -> 17
  (3, 0, 1, 2) -> 18
  (3, 0, 2, 1) -> 19
  (3, 1, 0, 2) -> 20
  (3, 1, 2, 0) -> 21
  (3, 2, 0, 1) -> 22
  (3, 2, 1, 0) -> 23

Algorithms exist that can generate a rank from a permutation for some particular ordering of permutations, and that can generate the same rank from the given individual permutation (i.e. given a rank of 17 produce (2, 3, 1, 0) in the example above).

One use of such algorithms could be in generating a small, random, sample of permutations of n items without duplicates when the total number of permutations is large. Remember that the total number of permutations of n items is given by n! which grows large very quickly: A 32 bit integer can only hold 12!, a 64 bit integer only 20!. It becomes difficult to take the straight-forward approach of generating all permutations then taking a random sample of them.

A question on the Stack Overflow site asked how to generate one million random and indivudual permutations of 144 items.

;Task:
# Create a function to generate a permutation from a rank.
# Create the inverse function that given the permutation generates its rank.
# Show that for n=3 the two functions are indeed inverses of each other.
# Compute and show here 4 random, individual, samples of permutations of 12 objects.

;Stretch goal:
* State how reasonable it would be to use your program to address the limits of the Stack Overflow question.

;References:
# Ranking and Unranking Permutations in Linear Time by Myrvold & Ruskey. (Also available via Google here).
# Ranks on the DevData site.
# Another answer on Stack Overflow to a different question that explains its algorithm in detail.

;Related tasks:
#[[Factorial_base_numbers_indexing_permutations_of_a_collection]]

Solution:
class Permutation
  include Enumerable
  attr_reader :num_elements, :size

  def initialize(num_elements)
    @num_elements = num_elements
    @size = fact(num_elements)
  end

  def each
    return self.to_enum unless block_given?
    (0...@size).each{|i| yield unrank(i)}
  end

  def unrank(r)  # nonrecursive version of Myrvold Ruskey unrank2 algorithm.
    pi = (0...num_elements).to_a
    (@num_elements-1).downto(1) do |n|
      s, r = r.divmod(fact(n))
      pi[n], pi[s] = pi[s], pi[n]
    end
    pi
  end

  def rank(pi)  # nonrecursive version of Myrvold Ruskey rank2 algorithm.
    pi = pi.dup
    pi1 = pi.zip(0...pi.size).sort.map(&:last)
    (pi.size-1).downto(0).inject(0) do |memo,i|
      pi[i], pi[pi1[i]] = pi[pi1[i]], (s = pi[i])
      pi1[s], pi1[i] = pi1[i], pi1[s]
      memo += s * fact(i)
    end
  end

  private
  def fact(n)
    n.zero? ? 1 : n.downto(1).inject(:*)
  end
end


Permutations by swapping

Generate permutations of n items in which successive permutations differ from each other by the swapping of any two items.

Also generate the sign of the permutation which is +1 when the permutation is generated from an even number of swaps from the initial state, and -1 for odd.

Show the permutations and signs of three items, in order of generation ''here''.

Such data are of use in generating the determinant of a square matrix and any functions created should bear this in mind.

Note: The Steinhaus-Johnson-Trotter algorithm generates successive permutations where ''adjacent'' items are swapped, but from this discussion adjacency is not a requirement.

;References:
* Steinhaus-Johnson-Trotter algorithm
* Johnson-Trotter Algorithm Listing All Permutations
* Heap's algorithm
* Tintinnalogia

;Related tasks:
*   [[Matrix arithmetic]
*   [[Gray code]]

Solution:
def perms(n)
  p = Array.new(n+1){|i| -i}
  s = 1
  loop do
    yield p[1..-1].map(&:abs), s
    k = 0
    for i in 2..n
      k = i if p[i] < 0 and p[i].abs > p[i-1].abs and p[i].abs > p[k].abs
    end
    for i in 1...n
      k = i if p[i] > 0 and p[i].abs > p[i+1].abs and  p[i].abs > p[k].abs
    end
    break if k.zero?
    for i in 1..n
      p[i] *= -1 if p[i].abs > p[k].abs
    end
    i = k + (p[k] <=> 0)
    p[k], p[i] = p[i], p[k]
    s = -s
  end
end

for i in 3..4
  perms(i){|perm, sign| puts "Perm: #{perm}  Sign: #{sign}"}
  puts
end


Phrase reversals

Given a string of space separated words containing the following phrase:
  rosetta code phrase reversal

:# Reverse the characters of the string.
:# Reverse the characters of each individual word in the string, maintaining original word order within the string.
:# Reverse the order of each word of the string, maintaining the order of characters in each word.

Show your output here.

Solution:
str = "rosetta code phrase reversal"

puts str.reverse                          # Reversed string.
puts str.split.map(&:reverse).join(" ")   # Words reversed.
puts str.split.reverse.join(" ")          # Word order reversed.


Pig the dice game

The   game of Pig   is a multiplayer game played with a single six-sided die.   The
object of the game is to reach   '''100'''   points or more.
Play is taken in turns.   On each person's turn that person has the option of either:

:# '''Rolling the dice''':   where a roll of two to six is added to their score for that turn and the player's turn continues as the player is given the same choice again;   or a roll of   '''1'''   loses the player's total points   ''for that turn''   and their turn finishes with play passing to the next player.
:# '''Holding''':   the player's score for that round is added to their total and becomes safe from the effects of throwing a   '''1'''   (one).   The player's turn finishes with play passing to the next player.

;Task:
Create a program to score for, and simulate dice throws for, a two-person game.

;Related task:
*   [[Pig the dice game/Player]]

Solution:
class PigGame
  Player = Struct.new(:name, :safescore, :score) do
    def bust!() self.score = safescore end
    def stay!() self.safescore = score end
    def to_s() "#{name} (#{safescore}, #{score})" end
  end

  def initialize(names, maxscore=100, die_sides=6)
    rotation = names.map {|name| Player.new(name,0,0) }

    rotation.cycle do |player|
      loop do
        if wants_to_roll?(player)
          puts "Rolled: #{roll=roll_dice(die_sides)}"
          if bust?(roll)
            puts "Busted!",''
            player.bust!
            break
          else
            player.score += roll
            if player.score >= maxscore
              puts player.name + " wins!"
              return
            end
          end
        else
          player.stay!
          puts "Staying with #{player.safescore}!", ''
          break
        end
      end
    end
  end

  def roll_dice(die_sides) rand(1..die_sides) end
  def bust?(roll) roll==1 end
  def wants_to_roll?(player)
    print "#{player}: Roll? (Y) "
    ['Y','y',''].include?(gets.chomp)
  end
end

PigGame.new( %w|Samuel Elizabeth| )


Pig the dice game/Player

Create a dice simulator and scorer of [[Pig the dice game]] and add to it the ability to play the game to at least one strategy.
* State here the play strategies involved.
* Show play during a game here.

As a stretch goal:
* Simulate playing the game a number of times with two players of given strategies and report here summary statistics such as, but not restricted to, the influence of going first or which strategy seems stronger.

;Game Rules:
The game of Pig is a multiplayer game played with a single six-sided die. The
object of the game is to reach 100 points or more.
Play is taken in turns. On each person's turn that person has the option of either

# '''Rolling the dice''': where a roll of two to six is added to their score for that turn and the player's turn continues as the player is given the same choice again; or a roll of 1 loses the player's total points ''for that turn'' and their turn finishes with play passing to the next player.
# '''Holding''': The player's score for that round is added to their total and becomes safe from the effects of throwing a one. The player's turn finishes with play passing to the next player.

;References
* Pig (dice)
* The Math of Being a Pig and Pigs (extra) - Numberphile videos featuring Ben Sparks.

Solution:
def player1(sum,sm)
for i in 1..100
puts "player1 rolled"
a=gets.chomp().to_i
if (a>1 && a<7)
	sum+=a
	if sum>=100
	puts "player1 wins"
	break
	end
else

goto player2(sum,sm)
end
i+=1
end
end

def player2(sum,sm)
for j in 1..100
puts "player2 rolled"
b=gets.chomp().to_i
if(b>1 && b<7)
 sm+=b
	if sm>=100
	 puts "player2 wins"
	break
	end
else

player1(sum,sm)
end
j+=1
end
end
i=0
j=0
sum=0
sm=0
player1(sum,sm)
return


Playfair cipher

Implement a  Playfair cipher for encryption and decryption.

The user must be able to choose   '''J'''  =  '''I'''      or   no   '''Q'''   in the alphabet.

The output of the encrypted and decrypted message must be in capitalized digraphs, separated by spaces.

;Output example:
                 HI DE TH EG OL DI NT HE TR EX ES TU MP

Solution:
class Playfair
  Size = 5
  def initialize(key, missing)
    @missing = missing.upcase
    alphabet = ('A'..'Z').to_a.join.upcase.delete(@missing).split''
    extended = key.upcase.gsub(/[^A-Z]/,'').split('') + alphabet
    grid = extended.uniq[0...Size*Size].each_slice(Size).to_a
    coords = {}
    grid.each_with_index do |row, i|
      row.each_with_index do |letter, j|
       coords[letter] = [i,j]
      end
    end
    @encode = {}
    alphabet.product(alphabet).reject { |a,b| a==b }.each do |a, b|
      i1, j1 = coords[a]
      i2, j2 = coords[b]
      if i1 == i2 then
         j1 = (j1 + 1) % Size
         j2 = (j2 + 1) % Size
      elsif j1 == j2 then
         i1 = (i1 + 1) % Size
         i2 = (i2 + 1) % Size
      else
         j1, j2 = j2, j1
      end
      @encode["#{a}#{b}"] = "#{grid[i1][j1]}#{grid[i2][j2]}"
      @decode = @encode.invert
    end
  end

  def encode(plaintext)
    plain = plaintext.upcase.gsub(/[^A-Z]/,'')
    if @missing == 'J' then
      plain = plain.gsub(/J/, 'I')
    else
      plain = plain.gsub(@missing, 'X')
    end
    plain = plain.gsub(/(.)\1/, '\1X\1')
    if plain.length % 2 == 1 then
      plain += 'X'
    end
    return plain.upcase.split('').each_slice(2).map do |pair|
      @encode[pair.join]
    end.join.split('').each_slice(5).map{|s|s.join}.join(' ')
  end

  def decode(ciphertext)
    cipher = ciphertext.upcase.gsub(/[^A-Z]/,'')
    return cipher.upcase.split('').each_slice(2).map do |pair|
      @decode[pair.join]
    end.join.split('').each_slice(5).map{|s|s.join}.join(' ')
  end
end


Poker hand analyser

Create a program to parse a single five card poker hand and rank it according to this list of poker hands.

A poker hand is specified as a space separated list of five playing cards.

Each input card has two characters indicating face and suit.

;Example:
::::'''2d'''       (two of diamonds).

Faces are:    '''a''', '''2''', '''3''', '''4''', '''5''', '''6''', '''7''', '''8''', '''9''', '''10''', '''j''', '''q''', '''k'''

Suits are:    '''h''' (hearts),   '''d''' (diamonds),   '''c''' (clubs),   and   '''s''' (spades),   or
alternatively,   the unicode card-suit characters:

Duplicate cards are illegal.

The program should analyze a single hand and produce one of the following outputs:
  straight-flush
  four-of-a-kind
  full-house
  flush
  straight
  three-of-a-kind
  two-pair
  one-pair
  high-card
  invalid

;Examples:
    2 2 2 k q:   three-of-a-kind
    2 5 7 8 9:   high-card
    a 2 3 4 5:   straight
    2 3 2 3 3:   full-house
    2 7 2 3 3:   two-pair
    2 7 7 7 7:   four-of-a-kind
    10 j q k a:  straight-flush
    4 4 k 5 10:  one-pair
    q 10 7 6 q:  invalid

The programs output for the above examples should be displayed here on this page.

;Extra credit:
# use the playing card characters introduced with Unicode 6.0 (U+1F0A1 - U+1F0DE).
# allow two jokers
::* use the symbol   '''joker'''
::* duplicates would be allowed (for jokers only)
::* five-of-a-kind would then be the highest hand

;More extra credit examples:
    joker  2  2  k  q:     three-of-a-kind
    joker  5  7  8  9:     straight
    joker  2  3  4  5:     straight
    joker  3  2  3  3:     four-of-a-kind
    joker  7  2  3  3:     three-of-a-kind
    joker  7  7  7  7:     five-of-a-kind
    joker  j  q  k  A:     straight-flush
    joker  4  k  5 10:     one-pair
    joker  k  7  6  4:     flush
    joker  2  joker  4  5:  straight
    joker  Q  joker  A 10:  straight
    joker  Q  joker  A 10:  straight-flush
    joker  2  2  joker  q:  four-of-a-kind

;Related tasks:
* [[Playing cards]]
* [[Card shuffles]]
* [[Deal cards_for_FreeCell]]
* [[War Card_Game]]
* [[Go Fish]]

Solution:
class Card
  include Comparable
  attr_accessor :ordinal
  attr_reader :suit, :face

  SUITS = %i(♥ ♦ ♣ ♠)
  FACES = %i(2 3 4 5 6 7 8 9 10 j q k a)

  def initialize(str)
    @face, @suit = parse(str)
    @ordinal = FACES.index(@face)
  end

  def <=> (other) #used for sorting
    self.ordinal <=> other.ordinal
  end

  def to_s
    "#@face#@suit"
  end

  private
  def parse(str)
    face, suit = str.chop.to_sym, str[-1].to_sym
    raise ArgumentError, "invalid card: #{str}" unless FACES.include?(face) && SUITS.include?(suit)
    [face, suit]
  end
end

class Hand
  include Comparable
  attr_reader :cards, :rank

  RANKS       = %i(high-card one-pair two-pair three-of-a-kind straight flush
                   full-house four-of-a-kind straight-flush five-of-a-kind)
  WHEEL_FACES = %i(2 3 4 5 a)

  def initialize(str_of_cards)
    @cards = str_of_cards.downcase.tr(',',' ').split.map{|str| Card.new(str)}
    grouped = @cards.group_by(&:face).values
    @face_pattern = grouped.map(&:size).sort
    @rank = categorize
    @rank_num = RANKS.index(@rank)
    @tiebreaker = grouped.map{|ar| [ar.size, ar.first.ordinal]}.sort.reverse
  end

  def <=> (other)    # used for sorting and comparing
    self.compare_value <=> other.compare_value
  end

  def to_s
    @cards.map(&:to_s).join(" ")
  end

  protected          # accessible for Hands
  def compare_value
    [@rank_num, @tiebreaker]
  end

  private
  def one_suit?
    @cards.map(&:suit).uniq.size == 1
  end

  def consecutive?
    sort.each_cons(2).all? {|c1,c2| c2.ordinal - c1.ordinal == 1 }
  end

  def sort
    if @cards.sort.map(&:face) == WHEEL_FACES
      @cards.detect {|c| c.face == :a}.ordinal = -1
    end
    @cards.sort
  end

  def categorize
    if consecutive?
      one_suit? ? :'straight-flush' : :straight
    elsif one_suit?
      :flush
    else
      case @face_pattern
        when [1,1,1,1,1] then :'high-card'
        when [1,1,1,2]   then :'one-pair'
        when [1,2,2]     then :'two-pair'
        when [1,1,3]     then :'three-of-a-kind'
        when [2,3]       then :'full-house'
        when [1,4]       then :'four-of-a-kind'
        when [5]         then :'five-of-a-kind'
      end
    end
  end
end

# Demo
test_hands = <<EOS
2♥ 2♦ 2♣ k♣ q♦
2♥ 5♥ 7♦ 8♣ 9♠
a♥ 2♦ 3♣ 4♣ 5♦
2♥ 3♥ 2♦ 3♣ 3♦
2♥ 7♥ 2♦ 3♣ 3♦
2♥ 6♥ 2♦ 3♣ 3♦
10♥ j♥ q♥ k♥ a♥
4♥ 4♠ k♠ 2♦ 10♠
4♥ 4♠ k♠ 3♦ 10♠
q♣ 10♣ 7♣ 6♣ 4♣
q♣ 10♣ 7♣ 6♣ 3♣
9♥ 10♥ q♥ k♥ j♣
2♥ 3♥ 4♥ 5♥ a♥
2♥ 2♥ 2♦ 3♣ 3♦
EOS

hands = test_hands.each_line.map{|line| Hand.new(line) }
puts "High to low"
hands.sort.reverse.each{|hand| puts "#{hand}\t #{hand.rank}" }
puts

str = <<EOS
joker  2♦  2♠  k♠  q♦
joker  5♥  7♦  8♠  9♦
joker  2♦  3♠  4♠  5♠
joker  3♥  2♦  3♠  3♦
joker  7♥  2♦  3♠  3♦
joker  7♥  7♦  7♠  7♣
joker  j♥  q♥  k♥  A♥
joker  4♣  k♣  5♦ 10♠
joker  k♣  7♣  6♣  4♣
joker  2♦  joker  4♠  5♠
joker  Q♦  joker  A♠ 10♠
joker  Q♦  joker  A♦ 10♦
joker  2♦  2♠  joker  q♦
EOS

# Neither the Card nor the Hand class supports jokers
# but since hands are comparable, they are also sortable.
# Try every card from a deck for a joker and pick the largest hand:

DECK = Card::FACES.product(Card::SUITS).map(&:join)
str.each_line do |line|
  cards_in_arrays = line.split.map{|c| c == "joker" ? DECK.dup : [c]} #joker is array of all cards
  all_tries  = cards_in_arrays.shift.product(*cards_in_arrays).map{|ar| Hand.new(ar.join" ")} #calculate the Whatshisname product
  best = all_tries.max
  puts "#{line.strip}: #{best.rank}"
end


Population count

The   ''population count''   is the number of   '''1'''s   (ones)   in the binary representation of a non-negative integer.

''Population count''   is also known as:
::::*   ''pop count''
::::*   ''popcount''
::::*   ''sideways sum''
::::*   ''bit summation''
::::*   ''Hamming weight''

For example,   '''5'''   (which is   '''101'''   in binary)   has a population count of   '''2'''.

''Evil numbers''   are non-negative integers  that have an   ''even''   population count.

''Odious numbers''      are  positive integers that have an    ''odd''   population count.

;Task:
* write a function (or routine) to return the population count of a non-negative integer.
* all computation of the lists below should start with   '''0'''   (zero indexed).
:* display the   ''pop count''   of the   1st   thirty powers of   '''3'''       ('''30''',   '''31''',   '''32''',   '''33''',   '''34''',      '''329''').
:* display the   1st   thirty     ''evil''        numbers.
:* display the   1st   thirty          ''odious''           numbers.
* display each list of integers on one line   (which may or may not include a title),   each set of integers being shown should be properly identified.

;See also
* The On-Line Encyclopedia of Integer Sequences:   A000120 population count.
* The On-Line Encyclopedia of Integer Sequences:   A000069 odious numbers.
* The On-Line Encyclopedia of Integer Sequences:   A001969 evil numbers.

Solution:
class Integer

  def popcount
    digits(2).count(1)     #pre Ruby 2.4: self.to_s(2).count("1")
  end

  def evil?
    self >= 0 && popcount.even?
  end

end

puts "Powers of 3:",  (0...30).map{|n| (3**n).popcount}.join(' ')
puts "Evil:"  , 0.step.lazy.select(&:evil?).first(30).join(' ')
puts "Odious:", 0.step.lazy.reject(&:evil?).first(30).join(' ')