Bitcoin/address validation

Write a program that takes a bitcoin address as argument,
and checks whether or not this address is valid.

A bitcoin address uses a base58 encoding, which uses an alphabet of the characters 0 .. 9, A ..Z, a .. z, but without the four characters:
:::*   0   zero
:::*   O   uppercase oh
:::*   I   uppercase eye
:::*   l   lowercase ell

With this encoding, a bitcoin address encodes 25 bytes:
* the first byte is the version number, which will be zero for this task ;
* the next twenty bytes are a [[RIPEMD-160]] digest, but you don't have to know that for this task:  you can consider them a pure arbitrary data ;
* the last four bytes are a checksum check.  They are the first four bytes of a double [[SHA-256]] digest of the previous 21 bytes.

To check the bitcoin address, you must read the first twenty-one bytes, compute the checksum, and check that it corresponds to the last four bytes.

The program can either return a boolean value or throw an exception when not valid.

You can use a digest library for [[SHA-256]].

;Example of a bitcoin address:

 1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62i

It doesn't belong to anyone and is part of the test suite of the bitcoin software.
You can change a few characters in this string and check that it'll fail the test.

Solution:
#  Validate Bitcoin address
#
#  Nigel_Galloway
#  October 13th., 2014
require 'digest/sha2'
def convert g
  i,e = '',[]
  (0...g.length/2).each{|n| e[n] = g[n+=n]+g[n+1]; i+='H2'}
  e.pack(i)
end
N = [0,1,2,3,4,5,6,7,8,nil,nil,nil,nil,nil,nil,nil,9,10,11,12,13,14,15,16,nil,17,18,19,20,21,nil,22,23,24,25,26,27,28,29,30,31,32,nil,nil,nil,nil,nil,nil,33,34,35,36,37,38,39,40,41,42,43,nil,44,45,46,47,48,49,50,51,52,53,54,55,56,57]
A = '1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62x'
g = A.bytes.inject(0){|g,n| g*58+N[n-49]}.to_s(16) # A small and interesting piece of code to do the decoding of base58-encoded data.
n = g.slice!(0..-9)
(n.length...42).each{n.insert(0,'0')}
puts "I think the checksum should be #{g}\nI calculate that it is         #{Digest::SHA256.hexdigest(Digest::SHA256.digest(convert(n)))[0,8]}"


Bitcoin/public point to address

elliptic curve public point into a short ASCII string.  The purpose of this task is to perform such a conversion.

The encoding steps are:
* take the X and Y coordinates of the given public point, and concatenate them in order to have a 64 byte-longed string ;
* add one byte prefix equal to 4 (it is a convention for this way of encoding a public point) ;
* compute the [[SHA-256]] of this string ;
* compute the [[RIPEMD-160]] of this SHA-256 digest ;
* compute the checksum of the concatenation of the version number digit (a single zero byte) and this RIPEMD-160 digest, as described in [[bitcoin/address validation]] ;
* Base-58 encode (see below) the concatenation of the version number (zero in this case), the ripemd digest and the checksum

The base-58 encoding is based on an alphabet of alphanumeric characters (numbers, upper case and lower case, in that order) but without the four characters 0, O, l and I.

Here is an example public point:
X = 0x50863AD64A87AE8A2FE83C1AF1A8403CB53F53E486D8511DAD8A04887E5B2352
Y = 0x2CD470243453A299FA9E77237716103ABC11A1DF38855ED6F2EE187E9C582BA6

The corresponding address should be:
16UwLL9Risc3QfPqBUvKofHmBQ7wMtjvM

Nb.  The leading '1' is not significant as 1 is zero in base-58.  It is however often added to the bitcoin address for various reasons.  There can actually be several of them.  You can ignore this and output an address without the leading 1.

''Extra credit:'' add a verification procedure about the public point, making sure it belongs to the secp256k1 elliptic curve

Solution:
#  Translate public point to Bitcoin address
#
#  Nigel_Galloway
#  October 12th., 2014
require 'digest/sha2'
def convert g
  i,e = '',[]
  (0...g.length/2).each{|n| e[n] = g[n+=n]+g[n+1]; i+='H2'}
  e.pack(i)
end
X = '50863AD64A87AE8A2FE83C1AF1A8403CB53F53E486D8511DAD8A04887E5B2352'
Y = '2CD470243453A299FA9E77237716103ABC11A1DF38855ED6F2EE187E9C582BA6'
n = '00'+Digest::RMD160.hexdigest(Digest::SHA256.digest(convert('04'+X+Y)))
n+= Digest::SHA256.hexdigest(Digest::SHA256.digest(convert(n)))[0,8]
G = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"
n,res = n.hex,''
while n > 0 do
  n,ng = n.divmod(58)
  res << G[ng]
end
puts res.reverse


Bitwise IO

The aim of this task is to write functions (or create a class if yourlanguage is Object Oriented and you prefer) for reading and writing sequences of
bits, most significant bit first. While the output of a asciiprint "STRING" is the ASCII byte sequence
"S", "T", "R", "I", "N", "G", the output of a "print" of the bits sequence
0101011101010 (13 bits) must be 0101011101010; real I/O is performed always
''quantized'' by byte (avoiding endianness issues and relying on underlying
buffering for performance), therefore you must obtain as output the bytes
0101 0111 0101 0'''000''' (bold bits are padding bits), i.e. in hexadecimal 57 50.

As test, you can implement a '''rough''' (e.g. don't care about error handling or
other issues) compression/decompression program for ASCII sequences
of bytes, i.e. bytes for which the most significant bit is always unused, so that you can write
seven bits instead of eight (each 8 bytes of input, we write 7 bytes of output).

These bit oriented I/O functions can be used to implement compressors and
decompressors; e.g. Dynamic and Static Huffman encodings use variable length
bits sequences, while LZW (see [[LZW compression]]) use fixed or variable ''words''
nine (or more) bits long.

* Limits in the maximum number of bits that can be written/read in a single read/write operation are allowed.
* Errors handling is not mandatory

Solution:
def crunch(ascii)
  bitstring = ascii.bytes.collect {|b| "%07b" % b}.join
  [bitstring].pack("B*")
end

def expand(binary)
  bitstring = binary.unpack("B*")[0]
  bitstring.scan(/[01]{7}/).collect {|b| b.to_i(2).chr}.join
end

original = "This is an ascii string that will be crunched, written, read and expanded."
puts "my ascii string is #{original.length} bytes"

filename = "crunched.out"

# write the compressed data
File.open(filename, "w") do |fh|
  fh.binmode
  fh.print crunch(original)
end

filesize = File.size(filename)
puts "the file containing the crunched text is #{filesize} bytes"

# read and expand
expanded = File.open(filename, "r") do |fh|
  fh.binmode
  expand(fh.read)
end

if original == expanded
  puts "success"
else
  puts "fail!"
end


Box the compass

Avast me hearties!
There be many a land lubber that knows naught of the pirate ways and gives direction by degree!
They know not how to box the compass!

;Task description:
# Create a function that takes a heading in degrees and returns the correct 32-point compass heading.
# Use the function to print and display a table of Index, Compass point, and Degree; rather like the corresponding columns from, the first table of the wikipedia article, but use only the following 33 headings as input:
:[0.0, 16.87, 16.88, 33.75, 50.62, 50.63, 67.5, 84.37, 84.38, 101.25, 118.12, 118.13, 135.0, 151.87, 151.88, 168.75, 185.62, 185.63, 202.5, 219.37, 219.38, 236.25, 253.12, 253.13, 270.0, 286.87, 286.88, 303.75, 320.62, 320.63, 337.5, 354.37, 354.38]. (They should give the same order of points but are spread throughout the ranges of acceptance).

;Notes;
* The headings and indices can be calculated from this pseudocode:
for i in 0..32 inclusive:
    heading = i * 11.25
    case i %3:
      if 1: heading += 5.62; break
      if 2: heading -= 5.62; break
    end
    index = ( i mod 32) + 1
* The column of indices can be thought of as an enumeration of the thirty two cardinal points (see talk page)..

Solution:
Headings = %w(north east south west north).each_cons(2).flat_map do |a, b|
  [a,
  "#{a} by #{b}",
  "#{a}-#{a}#{b}",
  "#{a}#{b} by #{a}",
  "#{a}#{b}",
  "#{a}#{b} by #{b}",
  "#{b}-#{a}#{b}",
  "#{b} by #{a}"]
end
Headings.prepend nil

def heading(degrees)
  i = degrees.quo(360).*(32).round.%(32).+(1)
  [i, Headings[i]]
end

# an array of angles, in degrees
angles = (0..32).map { |i| i * 11.25 + [0, 5.62, -5.62][i % 3] }

angles.each do |degrees|
  index, name = heading degrees
  printf "%2d %20s %6.2f\n", index, name.center(20), degrees
end


Brazilian numbers

Brazilian numbers are so called as they were first formally presented at the 1994 math Olympiad ''Olimpiada Iberoamericana de Matematica'' in Fortaleza, Brazil.

Brazilian numbers are defined as:

The set of positive integer numbers where each number '''N''' has at least one natural number '''B''' where '''1 < B < N-1''' where the representation of '''N''' in '''base B''' has all equal digits.

;E.G.:

:* '''1, 2 & 3''' can not be Brazilian; there is no base '''B''' that satisfies the condition '''1 < B < N-1'''.
:* '''4''' is not Brazilian; '''4''' in '''base 2''' is '''100'''. The digits are not all the same.
:* '''5''' is not Brazilian; '''5''' in '''base 2''' is '''101''', in '''base 3''' is '''12'''. There is no representation where the digits are the same.
:* '''6''' is not Brazilian; '''6''' in '''base 2''' is '''110''', in '''base 3''' is '''20''', in '''base 4''' is '''12'''. There is no representation where the digits are the same.
:* '''7''' ''is'' Brazilian; '''7''' in '''base 2''' is '''111'''. There is at least one representation where the digits are all the same.
:* '''8''' ''is'' Brazilian; '''8''' in '''base 3''' is '''22'''. There is at least one representation where the digits are all the same.
:* ''and so on...''

All even integers '''2P >= 8''' are Brazilian because '''2P = 2(P-1) + 2''', which is '''22''' in '''base P-1''' when '''P-1 > 2'''. That becomes true when '''P >= 4'''.
More common: for all all integers '''R''' and '''S''', where '''R > 1''' and also '''S-1 > R''', then '''R*S''' is Brazilian because '''R*S = R(S-1) + R''', which is '''RR''' in '''base S-1'''
The only problematic numbers are squares of primes, where R = S. Only 11^2 is brazilian to base 3.
All prime integers, that are brazilian, can only have the digit '''1'''. Otherwise one could factor out the digit, therefore it cannot be a prime number. Mostly in form of '''111''' to base Integer(sqrt(prime number)). Must be an odd count of '''1''' to stay odd like primes >  2

;Task:

Write a routine (function, whatever) to determine if a number is Brazilian and use the routine to show here, on this page;

:* the first '''20''' Brazilian numbers;
:* the first '''20 odd''' Brazilian numbers;
:* the first '''20 prime''' Brazilian numbers;

;See also:

:* '''OEIS:A125134 - Brazilian numbers'''
:* '''OEIS:A257521 - Odd Brazilian numbers'''
:* '''OEIS:A085104 - Prime Brazilian numbers'''

Solution:
def sameDigits(n,b)
    f = n % b
    while (n /= b) > 0 do
        if n % b != f then
            return false
        end
    end
    return true
end

def isBrazilian(n)
    if n < 7 then
        return false
    end
    if n % 2 == 0 then
        return true
    end
    for b in 2 .. n - 2 do
        if sameDigits(n, b) then
            return true
        end
    end
    return false
end

def isPrime(n)
    if n < 2 then
        return false
    end
    if n % 2 == 0 then
        return n == 2
    end
    if n % 3 == 0 then
        return n == 3
    end
    d = 5
    while d * d <= n do
        if n % d == 0 then
            return false
        end
        d = d + 2

        if n % d == 0 then
            return false
        end
        d = d + 4
    end
    return true
end

def main
    for kind in ["", "odd ", "prime "] do
        quiet = false
        bigLim = 99999
        limit = 20
        puts "First %d %sBrazilian numbers:" % [limit, kind]
        c = 0
        n = 7
        while c < bigLim do
            if isBrazilian(n) then
                if not quiet then
                    print "%d " % [n]
                end
                c = c + 1
                if c == limit then
                    puts
                    puts
                    quiet = true
                end
            end
            if quiet and kind != "" then
                next
            end
            if kind == "" then
                n = n + 1
            elsif kind == "odd " then
                n = n + 2
            elsif kind == "prime " then
                loop do
                    n = n + 2
                    if isPrime(n) then
                        break
                    end
                end
            else
                raise "Unexpected"
            end
        end
        if kind == "" then
            puts "The %dth Brazillian number is: %d" % [bigLim + 1, n]
            puts
        end
    end
end

main()


Break OO privacy

Show how to access private or protected members of a class in an object-oriented language from outside an instance of the class, without calling non-private or non-protected members of the class as a proxy.
The intent is to show how a debugger, serializer, or other meta-programming tool might access information that is barred by normal access methods to the object  but can nevertheless be accessed from within the language by some provided escape hatch or reflection mechanism.
The intent is specifically not to demonstrate heroic measures such as peeking and poking raw memory.

Note that cheating on your type system is almost universally regarded
as unidiomatic at best, and poor programming practice at worst.
Nonetheless, if your language intentionally maintains a double-standard for OO privacy, here's where you can show it off.

Solution:
class Example
  def initialize
     @private_data = "nothing" # instance variables are always private
  end
  private
  def hidden_method
     "secret"
  end
end
example = Example.new
p example.private_methods(false) # => [:hidden_method]
#p example.hidden_method # => NoMethodError: private method `name' called for #<Example:0x101308408>
p example.send(:hidden_method) # => "secret"
p example.instance_variables # => [:@private_data]
p example.instance_variable_get :@private_data # => "nothing"
p example.instance_variable_set :@private_data, 42 # => 42
p example.instance_variable_get :@private_data # => 42


Burrows–Wheeler transform

{{Wikipedia|Burrows-Wheeler_transform}}

The Burrows-Wheeler transform (BWT, also called block-sorting compression) rearranges a character string into runs of similar characters.

This is useful for compression, since it tends to be easy to compress a string that has runs of repeated characters by techniques such as move-to-front transform and run-length encoding.

More importantly, the transformation is reversible, without needing to store any additional data.

The BWT is thus a "free" method of improving the efficiency of text compression algorithms, costing only some extra computation.

Source: Burrows-Wheeler transform

Solution:
STX = "\u0002"
ETX = "\u0003"

def bwt(s)
    for c in s.split('')
        if c == STX or c == ETX then
            raise ArgumentError.new("Input can't contain STX or ETX")
        end
    end

    ss = ("%s%s%s" % [STX, s, ETX]).split('')
    table = []
    for i in 0 .. ss.length - 1
        table.append(ss.join)
        ss = ss.rotate(-1)
    end

    table = table.sort
    return table.map{ |e| e[-1] }.join
end

def ibwt(r)
    len = r.length
    table = [""] * len
    for i in 0 .. len - 1
        for j in 0 .. len - 1
            table[j] = r[j] + table[j]
        end
        table = table.sort
    end
    for row in table
        if row[-1] == ETX then
            return row[1 .. -2]
        end
    end
    return ""
end

def makePrintable(s)
    s = s.gsub(STX, "^")
    return s.gsub(ETX, "|")
end

def main
    tests = [
        "banana",
        "appellee",
        "dogwood",
        "TO BE OR NOT TO BE OR WANT TO BE OR NOT?",
        "SIX.MIXED.PIXIES.SIFT.SIXTY.PIXIE.DUST.BOXES",
        "\u0002ABC\u0003"
    ]
    for test in tests
        print makePrintable(test), "\n"
        print " --> "

        begin
            t = bwt(test)
            print makePrintable(t), "\n"

            r = ibwt(t)
            print " --> ", r, "\n\n"
        rescue ArgumentError => e
            print e.message, "\n"
            print " -->\n\n"
        end
    end
end

main()


CSV data manipulation

CSV spreadsheet files are suitable for storing tabular data in a relatively portable way.

The CSV format is flexible but somewhat ill-defined.

For present purposes, authors may assume that the data fields contain no commas, backslashes, or quotation marks.

;Task:
Read a CSV file, change some values and save the changes back to a file.

For this task we will use the following CSV file:

 C1,C2,C3,C4,C5
 1,5,9,13,17
 2,6,10,14,18
 3,7,11,15,19
 4,8,12,16,20

Suggestions

 Show how to add a column, headed 'SUM', of the sums of the rows.
 If possible, illustrate the use of built-in or standard functions, methods, or libraries, that handle generic CSV files.

Solution:
require 'csv'
# read:
ar = CSV.table("test.csv").to_a #table method assumes headers and converts numbers if possible.

# manipulate:
ar.first << "SUM"
ar[1..-1].each{|row| row << row.sum}

# write:
CSV.open("out.csv", 'w') do |csv|
  ar.each{|line| csv << line}
end


CSV to HTML translation

Consider a simplified CSV format where all rows are separated by a newline
and all columns are separated by commas.

No commas are allowed as field data, but the data may contain
other characters and character sequences that would
normally be   ''escaped''   when converted to HTML

;Task:
Create a function that takes a string representation of the CSV data
and returns a text string of an HTML table representing the CSV data.

Use the following  data as the CSV text to convert, and show your output.
: Character,Speech
: The multitude,The messiah! Show us the messiah!
: Brians mother,Now you listen here! He's not the messiah; he's a very naughty boy! Now go away!
: The multitude,Who are you?
: Brians mother,I'm his mother; that's who!
: The multitude,Behold his mother! Behold his mother!

;Extra credit:
''Optionally'' allow special formatting for the first row of the table as if it is the tables header row
(via  preferably; CSS if you must).

Solution:
require 'cgi'

puts '
'

def row2html str, wrap = "td"
  "
" +
    str.split(",").map { |cell| "<#{wrap}>#{CGI.escapeHTML cell}</#{wrap}>" }.join +
  "
"
end

puts row2html gets.chomp, "th" if ARGV.delete "header"

while str = gets
  puts row2html str.chomp
end

puts "
"


Calculating the value of e

Calculate the value of   ''e''.

(''e''   is also known as   ''Euler's number''   and   ''Napier's constant''.)

See details: Calculating the value of e

Solution:
fact = 1
e = 2
e0 = 0
n = 2

until (e - e0).abs < Float::EPSILON do
  e0 = e
  fact *= n
  n += 1
  e += 1.0 / fact
end

puts e


Calkin-Wilf sequence

The '''Calkin-Wilf sequence''' contains every nonnegative rational number exactly once.

It can be calculated recursively as follows:

        {{math|a1}}   =  {{math|1}}
 {{math|an+1}}  =  {{math|1/(2an+1-an)}} for n > 1

;Task part 1:
* Show on this page terms 1 through 20 of the Calkin-Wilf sequence.

To avoid floating point error, you may want to use a rational number data type.

It is also possible, given a non-negative rational number, to determine where it appears in the sequence without calculating the sequence. The procedure is to get the continued fraction representation of the rational and use it as the run-length encoding of the binary representation of the term number, beginning from the end of the continued fraction.
It only works if the number of terms in the continued fraction is odd- use either of the two equivalent representations to achieve this:

        {{math|[a0; a1, a2, ..., an]}}  =  {{math|[a0; a1, a2 ,..., an-1, 1]}}

;Example:
The fraction   '''9/4'''   has odd continued fraction representation      {{math|2; 3, 1}},     giving a binary representation of   '''100011''',
which means   '''9/4'''   appears as the   '''35th'''   term of the sequence.

;Task part 2:
* Find the position of the number   '''83116''''''/''''''51639'''   in the Calkin-Wilf sequence.

;See also:
* Wikipedia entry:  Calkin-Wilf tree
* [[Continued fraction]]
* [[Continued fraction/Arithmetic/Construct from rational number]]

Solution:
cw = Enumerator.new do |y|
  y << a = 1.to_r
  loop { y << a = 1/(2*a.floor + 1 - a) }
end

def term_num(rat)
  num, den, res, pwr, dig = rat.numerator, rat.denominator, 0, 0, 1
  while den > 0
    num, (digit, den) = den, num.divmod(den)
    digit.times do
      res |= dig << pwr
      pwr += 1
    end
    dig ^= 1
  end
  res
end

puts  cw.take(20).join(", ")
puts  term_num  (83116/51639r)


Call a function

Demonstrate the different syntax and semantics provided for calling a function.

This may include:
:*   Calling a function that requires no arguments
:*   Calling a function with a fixed number of arguments
:*   Calling a function with optional arguments
:*   Calling a function with a variable number of arguments
:*   Calling a function with named arguments
:*   Using a function in statement context
:*   Using a function in first-class context within an expression
:*   Obtaining the return value of a function
:*   Distinguishing built-in functions and user-defined functions
:*   Distinguishing subroutines and functions
;*   Stating whether arguments are passed by value or by reference
;*   Is partial application possible and how

This task is ''not'' about defining functions.

Solution:
#                                   return value        substance
i = 3
p 1 + i                         #=> 4                   1.+(i)
p i < 5                         #=> true                i.<(5)
p 2 ** i                        #=> 8                   2.**(i)
p -i                            #=> -3                  i.-@()
a = [1,2,3]
p a[0]                          #=> 1                   a.[](0)
a[2] = "0"                      #                       a.[]=(2,"0")
p a << 5                        #=> [1, 2, "0", 5]      a.<<(5)
p a & [4,2]                     #=> [2]                 a.&([4,2])
p "abcde"[1..3]                 #=> "bcd"               "abcde".[](1..3)
p "%2d %4s" % [1,"xyz"]         #=> " 1  xyz"           "%2d %4s".%([1,"xyz"])


Canonicalize CIDR

Implement a function or program that, given a range of IPv4 addresses in CIDR notation (dotted-decimal/network-bits), will return/output the same range in canonical form.

That is, the IP address portion of the output CIDR block must not contain any set (1) bits in the host part of the address.

;Example:
Given   '''87.70.141.1/22''',    your code should output    '''87.70.140.0/22'''

;Explanation:
An Internet Protocol version 4 address is a 32-bit value, conventionally represented as a number in base 256 using dotted-decimal notation, where each base-256 digit is given in decimal and the digits are separated by periods. Logically, this 32-bit value represents two components: the leftmost (most-significant) bits determine the network portion of the address, while the rightmost (least-significant) bits determine the host portion. Classless Internet Domain Routing block notation indicates where the boundary between these two components is for a given address by adding a slash followed by the number of bits in the network portion.

In general, CIDR blocks stand in for the entire set of IP addresses sharing the same network component, so it's common to see access control lists that specify individual IP addresses using /32 to indicate that only the one address is included. Software accepting this notation as input often expects it to be entered in canonical form, in which the host bits are all zeroes. But network admins sometimes skip this step and just enter the address of a specific host on the subnet with the network size, resulting in a non-canonical entry.

The example address, 87.70.141.1/22, represents binary 0101011101000110100011 / 0100000001, with the / indicating the network/host division. To canonicalize, clear all the bits to the right of the / and convert back to dotted decimal: 0101011101000110100011 / 0000000000 - 87.70.140.0.

;More examples for testing

        36.18.154.103/12    -  36.16.0.0/12
        62.62.197.11/29     -  62.62.197.8/29
        67.137.119.181/4    -  64.0.0.0/4
        161.214.74.21/24    -  161.214.74.0/24
        184.232.176.184/18  -  184.232.128.0/18

Solution:
#!/usr/bin/env ruby

# canonicalize a CIDR block: make sure none of the host bits are set
if ARGV.length == 0 then
    ARGV = $stdin.readlines.map(&:chomp)
end

ARGV.each do |cidr|

  # dotted-decimal / bits in network part
  dotted, size_str = cidr.split('/')
  size = size_str.to_i

  # get IP as binary string
  binary = dotted.split('.').map { |o| "%08b" % o }.join

  # Replace the host part with all zeroes
  binary[size .. -1] = '0' * (32 - size)

  # Convert back to dotted-decimal
  canon = binary.chars.each_slice(8).map { |a| a.join.to_i(2) }.join('.')

  # And output
  puts "#{canon}/#{size}"
end


Cantor set

Draw a Cantor set.

See details at this Wikipedia webpage:   Cantor set

Solution:
lines = 5

(0..lines).each do |exp|
  seg_size = 3**(lines-exp-1)
  chars = (3**exp).times.map{ |n| n.digits(3).any?(1) ? " " : "█"}
  puts chars.map{ |c| c * seg_size }.join
end


Cartesian product of two or more lists

Show one or more idiomatic ways of generating the Cartesian product of two arbitrary lists in your language.

Demonstrate that your function/method correctly returns:
::{1, 2} x {3, 4} = {(1, 3), (1, 4), (2, 3), (2, 4)}

and, in contrast:
::{3, 4} x {1, 2} = {(3, 1), (3, 2), (4, 1), (4, 2)}

Also demonstrate, using your function/method, that the product of an empty list with any other list is empty.
:: {1, 2} x {} = {}
:: {} x {1, 2} = {}

For extra credit, show or write a function returning the n-ary product of an arbitrary number of lists, each of arbitrary length. Your function might, for example, accept a single argument which is itself a list of lists, and return the n-ary product of those lists.

Use your n-ary Cartesian product function to show the following products:
:: {1776, 1789} x {7, 12} x {4, 14, 23} x {0, 1}
:: {1, 2, 3} x {30} x {500, 100}
:: {1, 2, 3} x {} x {500, 100}

Solution:
p [1, 2].product([3, 4])
p [3, 4].product([1, 2])
p [1, 2].product([])
p [].product([1, 2])
p [1776, 1789].product([7, 12], [4, 14, 23], [0, 1])
p [1, 2, 3].product([30], [500, 100])
p [1, 2, 3].product([], [500, 100])


Casting out nines

Task   (in three parts):

;Part 1
Write a procedure (say \mathit{co9}(x)) which implements Casting Out Nines as described by returning the checksum for x. Demonstrate the procedure using the examples given there, or others you may consider lucky.

Note that this function does nothing more than calculate the least positive residue, modulo 9. Many of the solutions omit Part 1 for this reason. Many languages have a modulo operator, of which this is a trivial application.

With that understanding, solutions to Part 1, if given, are encouraged to follow the naive pencil-and-paper or mental arithmetic of repeated digit addition understood to be "casting out nines", or some approach other than just reducing modulo 9 using a built-in operator. Solutions for part 2 and 3 are not required to make use of the function presented in part 1.

;Part 2
Notwithstanding past Intel microcode errors, checking computer calculations like this would not be sensible. To find a computer use for your procedure:
: Consider the statement "318682 is 101558 + 217124 and squared is 101558217124" (see: [[Kaprekar numbers#Casting Out Nines (fast)]]).
: note that 318682 has the same checksum as (101558 + 217124);
: note that 101558217124 has the same checksum as (101558 + 217124) because for a Kaprekar they are made up of the same digits (sometimes with extra zeroes);
: note that this implies that for Kaprekar numbers the checksum of k equals the checksum of k^2.

Demonstrate that your procedure can be used to generate or filter a range of numbers with the property \mathit{co9}(k) = \mathit{co9}(k^2) and show that this subset is a small proportion of the range and contains all the Kaprekar in the range.

;Part 3
Considering this MathWorld page, produce a efficient algorithm based on the more mathematical treatment of Casting Out Nines, and realizing:
: \mathit{co9}(x) is the residual of x mod 9;
: the procedure can be extended to bases other than 9.

Demonstrate your algorithm by generating or filtering a range of numbers with the property k%(\mathit{Base}-1) == (k^2)%(\mathit{Base}-1) and show that this subset is a small proportion of the range and contains all the Kaprekar in the range.

;related tasks
* [[First perfect square in base N with N unique digits]]
* [[Kaprekar numbers]]

Solution:
N = 2
base = 10
c1 = 0
c2 = 0

for k in 1 .. (base ** N) - 1
    c1 = c1 + 1
    if k % (base - 1) == (k * k) % (base - 1) then
        c2 = c2 + 1
        print "%d " % [k]
    end
end

puts
print "Trying %d numbers instead of %d numbers saves %f%%" % [c2, c1, 100.0 - 100.0 * c2 / c1]


Catalan numbers/Pascal's triangle

Print out the first   '''15'''   Catalan numbers by extracting them from Pascal's triangle.

;See:
*   Catalan Numbers and the Pascal Triangle.      This method enables calculation of Catalan Numbers using only addition and subtraction.

*   Catalan's Triangle for a Number Triangle that generates Catalan Numbers using only addition.
*   Sequence A000108 on OEIS has a lot of information on Catalan Numbers.

;Related Tasks:
[[Pascal's triangle]]

Solution:
def catalan(num)
  t = [0, 1] #grows as needed
  (1..num).map do |i|
    i.downto(1){|j| t[j] += t[j-1]}
    t[i+1] = t[i]
    (i+1).downto(1) {|j| t[j] += t[j-1]}
    t[i+1] - t[i]
  end
end

p catalan(15)


Catamorphism

''Reduce'' is a function or method that is used to take the values in an array or a list and apply a function to successive members of the list to produce (or reduce them to), a single value.

;Task:
Show how ''reduce'' (or ''foldl'' or ''foldr'' etc), work (or would be implemented) in your language.

;See also:
* Wikipedia article:   Fold
* Wikipedia article:   Catamorphism

Solution:
p row = [1]
10.times{p row = row.each_cons(2).inject([1,1]){|ar,(a,b)| ar.insert(-2, a+b)} }

# [1]
# [1, 1]
# [1, 2, 1]
# [1, 3, 3, 1]
# [1, 4, 6, 4, 1]
# [1, 5, 10, 10, 5, 1]
# [1, 6, 15, 20, 15, 6, 1]
# etc


Chaocipher

Description:
The Chaocipher was invented by J.F.Byrne in 1918 and, although simple by modern cryptographic standards, does not appear to have been broken until the algorithm was finally disclosed by his family in 2010.

The algorithm is described in this paper by M.Rubin in 2010 and there is a C# implementation here.

;Task:
Code the algorithm in your language and to test that it works with the plaintext 'WELLDONEISBETTERTHANWELLSAID' used in the paper itself.

Solution:
txt    = "WELLDONEISBETTERTHANWELLSAID"
@left  = "HXUCZVAMDSLKPEFJRIGTWOBNYQ".chars
@right = "PTLNBQDEOYSFAVZKGJRIHWXUMC".chars

def encrypt(char)
  coded_char = @left[@right.index(char)]

  @left.rotate!(@left.index(coded_char))
  part = @left.slice!(1,13).rotate
  @left.insert(1, *part)

  @right.rotate!(@right.index(char)+1)
  part = @right.slice!(2,12).rotate
  @right.insert(2, *part)

  @left[0]
end

puts txt.each_char.map{|c| encrypt(c) }.join


Check input device is a terminal

Demonstrate how to check whether the input device is a terminal or not.

;Related task:
*   [[Check output device is a terminal]]

Solution:
File.new("testfile").isatty   #=> false
File.new("/dev/tty").isatty   #=> true


Check output device is a terminal

Demonstrate how to check whether the output device is a terminal or not.

;Related task:
*   [[Check input device is a terminal]]

Solution:
f = File.open("test.txt")
p f.isatty          # => false
p STDOUT.isatty     # => true


Cheryl's birthday

Albert and Bernard just became friends with Cheryl, and they want to know when her birthday is.

Cheryl gave them a list of ten possible dates:
      May 15,     May 16,     May 19
      June 17,    June 18
      July 14,    July 16
      August 14,  August 15,  August 17

Cheryl then tells Albert the   ''month''   of birth,   and Bernard the   ''day''   (of the month)   of birth.
  1)  Albert:   I don't know when Cheryl's birthday is, but I know that Bernard does not know too.
  2)  Bernard:  At first I don't know when Cheryl's birthday is, but I know now.
  3)  Albert:   Then I also know when Cheryl's birthday is.

;Task
Write a computer program to deduce, by successive elimination, Cheryl's birthday.

;Related task:
* [[Sum and Product Puzzle]]

;References
* Wikipedia article of the same name.
* Tuple Relational Calculus

Solution:
dates = [
    ["May", 15],
    ["May", 16],
    ["May", 19],
    ["June", 17],
    ["June", 18],
    ["July", 14],
    ["July", 16],
    ["August", 14],
    ["August", 15],
    ["August", 17],
]

print dates.length, " remaining\n"

# the month cannot have a unique day
uniqueMonths = dates.group_by { |m,d| d }
                    .select { |k,v| v.size == 1 }
                    .map { |k,v| v.flatten }
                    .map { |m,d| m }
dates.delete_if { |m,d| uniqueMonths.include? m }
print dates.length, " remaining\n"

# the day must be unique
dates = dates   .group_by { |m,d| d }
                .select { |k,v| v.size == 1 }
                .map { |k,v| v.flatten }
print dates.length, " remaining\n"

# the month must now be unique
dates = dates   .group_by { |m,d| m }
                .select { |k,v| v.size == 1 }
                .map { |k,v| v }
                .flatten
print dates


Chinese remainder theorem

Suppose   n_1,   n_2,   \ldots,   n_k   are positive [[integer]]s that are pairwise co-prime.

Then, for any given sequence of integers   a_1,   a_2,   \dots,   a_k,   there exists an integer   x   solving the following system of simultaneous congruences:

::: \begin{align}
  x &\equiv a_1 \pmod{n_1} \\
  x &\equiv a_2 \pmod{n_2} \\
    &{}\  \  \vdots \\
  x &\equiv a_k \pmod{n_k}
\end{align}

Furthermore, all solutions   x   of this system are congruent modulo the product,    N=n_1n_2\ldots n_k.

;Task:
Write a program to solve a system of linear congruences by applying the   Chinese Remainder Theorem.

If the system of equations cannot be solved, your program must somehow indicate this.

(It may throw an exception or return a special false value.)

Since there are infinitely many solutions, the program should return the unique solution   s   where   0 \leq s \leq n_1n_2\ldots n_k.

''Show the functionality of this program'' by printing the result such that the   n's   are   [3,5,7]   and the   a's   are   [2,3,2].

'''Algorithm''':   The following algorithm only applies if the   n_i's   are pairwise co-prime.

Suppose, as above, that a solution is required for the system of congruences:

::: x \equiv a_i \pmod{n_i} \quad\mathrm{for}\; i = 1, \ldots, k

Again, to begin, the product   N = n_1n_2 \ldots n_k   is defined.

Then a solution   x   can be found as follows:

For each   i,   the integers   n_i   and   N/n_i   are co-prime.

Using the   Extended Euclidean algorithm,   we can find integers   r_i   and   s_i   such that   r_i n_i + s_i N/n_i = 1.

Then, one solution to the system of simultaneous congruences is:

::: x = \sum_{i=1}^k a_i s_i N/n_i

and the minimal solution,

::: x \pmod{N}.

Solution:
def extended_gcd(a, b)
  last_remainder, remainder = a.abs, b.abs
  x, last_x = 0, 1
  while remainder != 0
    last_remainder, (quotient, remainder) = remainder, last_remainder.divmod(remainder)
    x, last_x = last_x - quotient*x, x
  end
  return last_remainder, last_x * (a < 0 ? -1 : 1)
end

def invmod(e, et)
  g, x = extended_gcd(e, et)
  if g != 1
    raise 'Multiplicative inverse modulo does not exist!'
  end
  x % et
end

def chinese_remainder(mods, remainders)
  max = mods.inject( :* )  # product of all moduli
  series = remainders.zip(mods).map{ |r,m| (r * max * invmod(max/m, m) / m) }
  series.inject( :+ ) % max
end

p chinese_remainder([3,5,7], [2,3,2])     #=> 23
p chinese_remainder([17353461355013928499, 3882485124428619605195281, 13563122655762143587], [7631415079307304117, 1248561880341424820456626, 2756437267211517231]) #=> 937307771161836294247413550632295202816
p chinese_remainder([10,4,9], [11,22,19]) #=> nil


Chinese zodiac

Determine the Chinese zodiac sign and related associations for a given year.
Traditionally, the Chinese have counted years using two lists of labels, one of length 10 (the "celestial stems") and one of length 12 (the "terrestrial branches"). The labels do not really have any meaning outside their positions in the two lists; they're simply a traditional enumeration device, used much as Westerners use letters and numbers. They were historically used for months and days as well as years, and the stems are still sometimes used for school grades.

Years cycle through both lists concurrently, so that both stem and branch advance each year; if we used Roman letters for the stems and numbers for the branches, consecutive years would be labeled A1, B2, C3, etc. Since the two lists are different lengths, they cycle back to their beginning at different points: after J10 we get A11, and then after B12 we get C1. The result is a repeating 60-year pattern within which each pair of names occurs only once.

Mapping the branches to twelve traditional animal deities results in the well-known "Chinese zodiac", assigning each year to a given animal. For example, Sunday, January 22, 2023 CE (in the common Gregorian calendar) began the lunisolar Year of the Rabbit.

The celestial stems do not have a one-to-one mapping like that of the branches to animals; however, the five pairs of consecutive stems are each associated with one of the five traditional Chinese elements (Wood, Fire, Earth, Metal, and Water). Further, one of the two years within each element is assigned to yin, the other to yang.

Thus, the Chinese year beginning in 2023 CE is also the yin year of Water. Since 12 is an even number, the association between animals and yin/yang doesn't change; consecutive Years of the Rabbit will cycle through the five elements, but will always be yin.

;Task: Create a subroutine or program that will return or output the animal, yin/yang association, and element for the lunisolar year that begins in a given CE year.

You may optionally provide more information in the form of the year's numerical position within the 60-year cycle and/or its actual Chinese stem-branch name (in Han characters or Pinyin transliteration).

;Requisite information:
* The animal cycle runs in this order: Rat, Ox, Tiger, Rabbit, Dragon, Snake, Horse, Goat, Monkey, Rooster, Dog, Pig.
* The element cycle runs in this order: Wood, Fire, Earth, Metal, Water.
* Each element gets two consecutive years; a yang followed by a yin.
* The current 60-year cycle began in 1984; any multiple of 60 years from that point may be used to reckon from.

Thus, year 1 of a cycle is the year of the Wood Rat (yang), year 2 the Wood Ox (yin), and year 3 the Fire Tiger (yang). The year 2023 - which, as already noted, is the year of the Water Rabbit (yin) - is the 40th year of the current cycle.

;Information for optional task:
* The ten celestial stems are '''Jia ''' ''jia'', '''Yi ''' ''yi'', '''Bing ''' ''bing'', '''Ding ''' ''ding'', '''Wu ''' ''wu'', '''Ji ''' ''ji'', '''Geng ''' ''geng'', '''Xin ''' ''xin'', '''Ren ''' ''ren'', and '''Gui ''' ''gui''. With the ASCII version of Pinyin tones, the names are written "jia3", "yi3", "bing3", "ding1", "wu4", "ji3", "geng1", "xin1", "ren2", and "gui3".
* The twelve terrestrial branches are '''Zi ''' ''zi'', '''Chou ''' ''chou'', '''Yin ''' ''yin'', '''Mao ''' ''mao'', '''Chen ''' ''chen'', '''Si ''' ''si'', '''Wu ''' ''wu'', '''Wei ''' ''wei'', '''Shen ''' ''shen'', '''You ''' ''you'', '''Xu ''' ''xu'', '''Hai ''' ''hai''. In ASCII Pinyin, those are "zi3", "chou3", "yin2", "mao3", "chen2", "si4", "wu3", "wei4", "shen1", "you3", "xu1", and "hai4".

Therefore 1984 was '''Jia Zi ''' (''jia-zi'', or jia3-zi3).  2023 is '''Gui Mao ''' (''gui-mao'' or gui3-mao3).

Solution:
# encoding: utf-8
pinyin = {
  '甲' => 'jiă',
  '乙' => 'yĭ',
  '丙' => 'bĭng',
  '丁' => 'dīng',
  '戊' => 'wù',
  '己' => 'jĭ',
  '庚' => 'gēng',
  '辛' => 'xīn',
  '壬' => 'rén',
  '癸' => 'gŭi',

  '子' => 'zĭ',
  '丑' => 'chŏu',
  '寅' => 'yín',
  '卯' => 'măo',
  '辰' => 'chén',
  '巳' => 'sì',
  '午' => 'wŭ',
  '未' => 'wèi',
  '申' => 'shēn',
  '酉' => 'yŏu',
  '戌' => 'xū',
  '亥' => 'hài'
}
celestial     = %w(甲 乙 丙 丁 戊 己 庚 辛 壬 癸)
terrestrial   = %w(子 丑 寅 卯 辰 巳 午 未 申 酉 戌 亥)
animals       = %w(Rat   Ox   Tiger  Rabbit  Dragon Snake
                   Horse Goat Monkey Rooster Dog    Pig)
elements      = %w(Wood Fire Earth Metal Water)
aspects       = %w(yang yin)

BASE = 4

args = if !ARGV.empty?
         ARGV
       else
         [Time.new.year]
       end

args.each do |arg|
  ce_year = Integer(arg)
  print "#{ce_year}: " if ARGV.length > 1
  cycle_year     = ce_year - BASE

  stem_number    = cycle_year % 10
  stem_han       = celestial[stem_number]
  stem_pinyin    = pinyin[stem_han]

  element_number = stem_number / 2
  element        = elements[element_number]

  branch_number  = cycle_year % 12
  branch_han     = terrestrial[branch_number]
  branch_pinyin  = pinyin[branch_han]
  animal         = animals[branch_number]

  aspect_number = cycle_year % 2
  aspect        = aspects[aspect_number]

  index         = cycle_year % 60 + 1

  print stem_han, branch_han
  puts " (#{stem_pinyin}-#{branch_pinyin}, #{element} #{animal}; #{aspect} - year #{index} of the cycle)"
end


Church numerals

In the Church encoding of natural numbers, the number N is encoded by a function that applies its first argument N times to its second argument.

* '''Church zero''' always returns the identity function, regardless of its first argument. In other words, the first argument is not applied to the second argument at all.
* '''Church one''' applies its first argument f just once to its second argument x, yielding '''f(x)'''
* '''Church two''' applies its first argument f twice to its second argument x, yielding '''f(f(x))'''
* and each successive Church numeral applies its first argument one additional time to its second argument, '''f(f(f(x)))''', '''f(f(f(f(x))))''' ...  The Church numeral 4, for example, returns a quadruple composition of the function supplied as its first argument.

Arithmetic operations on natural numbers can be similarly represented as functions on Church numerals.

In your language define:

* Church Zero,
* a Church successor function (a function on a Church numeral which returns the next Church numeral in the series),
* functions for Addition, Multiplication and Exponentiation over Church numerals,
* a function to convert integers to corresponding Church numerals,
* and a function to convert Church numerals to corresponding integers.

You should:

* Derive Church numerals three and four in terms of Church zero and a Church successor function.
* use Church numeral arithmetic to obtain the the sum and the product of Church 3 and Church 4,
* similarly obtain 4^3 and 3^4 in terms of Church numerals, using a Church numeral exponentiation function,
* convert each result back to an integer, and return it or print it to the console.

Solution:
def zero(f)
  return lambda {|x| x}
end
Zero = lambda { |f| zero(f) }

def succ(n)
  return lambda { |f| lambda { |x| f.(n.(f).(x)) } }
end

Three = succ(succ(succ(Zero)))

def add(n, m)
  return lambda { |f| lambda { |x| m.(f).(n.(f).(x)) } }
end

def mult(n, m)
  return lambda { |f| lambda { |x| m.(n.(f)).(x) } }
end

def power(b, e)
  return e.(b)
end

def int_from_couch(f)
  countup = lambda { |i| i+1 }
  f.(countup).(0)
end

def couch_from_int(x)
  countdown = lambda { |i|
    case i
      when 0 then Zero
      else succ(countdown.(i-1))
    end
  }
  countdown.(x)
end

Four  = couch_from_int(4)

puts [ add(Three, Four),
       mult(Three, Four),
       power(Three, Four),
       power(Four, Three) ].map {|f| int_from_couch(f) }


Circles of given radius through two points

2 circles with a given radius through 2 points in 2D space.

Given two points on a plane and a radius, usually two circles of given radius can be drawn through the points.
;Exceptions:
# r==0.0 should be treated as never describing circles (except in the case where the points are coincident).
# If the points are coincident then an infinite number of circles with the point on their circumference can be drawn, unless r==0.0 as well which then collapses the circles to a point.
# If the points form a diameter then return two identical circles ''or'' return a single circle, according to which is the most natural mechanism for the implementation language.
# If the points are too far apart then no circles can be drawn.

;Task detail:
* Write a function/subroutine/method/... that takes two points and a radius and returns the two circles through those points, ''or some indication of special cases where two, possibly equal, circles cannot be returned''.
* Show here the output for the following inputs:

      p1                p2           r
0.1234, 0.9876    0.8765, 0.2345    2.0
0.0000, 2.0000    0.0000, 0.0000    1.0
0.1234, 0.9876    0.1234, 0.9876    2.0
0.1234, 0.9876    0.8765, 0.2345    0.5
0.1234, 0.9876    0.1234, 0.9876    0.0

;Related task:
*   [[Total circles area]].

;See also:
*   Finding the Center of a Circle from 2 Points and Radius from Math forum @ Drexel

Solution:
Pt     = Struct.new(:x, :y)
Circle = Struct.new(:x, :y, :r)

def circles_from(pt1, pt2, r)
  raise ArgumentError, "Infinite number of circles, points coincide." if pt1 == pt2 && r > 0
  # handle single point and r == 0
  return [Circle.new(pt1.x, pt1.y, r)] if pt1 == pt2 && r == 0
  dx, dy = pt2.x - pt1.x, pt2.y - pt1.y
  # distance between points
  q = Math.hypot(dx, dy)
  # Also catches pt1 != pt2 && r == 0
  raise ArgumentError, "Distance of points > diameter." if q > 2.0*r
  # halfway point
  x3, y3 = (pt1.x + pt2.x)/2.0, (pt1.y + pt2.y)/2.0
  d = (r**2 - (q/2)**2)**0.5
  [Circle.new(x3 - d*dy/q, y3 + d*dx/q, r),
   Circle.new(x3 + d*dy/q, y3 - d*dx/q, r)].uniq
end

# Demo:
ar = [[Pt.new(0.1234, 0.9876), Pt.new(0.8765, 0.2345), 2.0],
      [Pt.new(0.0000, 2.0000), Pt.new(0.0000, 0.0000), 1.0],
      [Pt.new(0.1234, 0.9876), Pt.new(0.1234, 0.9876), 2.0],
      [Pt.new(0.1234, 0.9876), Pt.new(0.8765, 0.2345), 0.5],
      [Pt.new(0.1234, 0.9876), Pt.new(0.1234, 0.9876), 0.0]]

ar.each do |p1, p2, r|
  print "Given points:\n  #{p1.values},\n  #{p2.values}\n  and radius #{r}\n"
  begin
    circles = circles_from(p1, p2, r)
    puts "You can construct the following circles:"
    circles.each{|c| puts "  #{c}"}
  rescue ArgumentError => e
    puts e
  end
  puts
end


Cistercian numerals

Cistercian numerals were used across Europe by Cistercian monks during the Late Medieval Period as an alternative to Roman numerals. They were used to represent base 10 integers from '''0''' to '''9999'''.

;How they work
All Cistercian numerals begin with a vertical line segment, which by itself represents the number '''0'''. Then, glyphs representing the digits '''1''' through '''9''' are optionally added to the four quadrants surrounding the vertical line segment. These glyphs are drawn with vertical and horizontal symmetry about the initial line segment. Each quadrant corresponds to a digit place in the number:

:* The '''upper-right''' quadrant represents the '''ones''' place.
:* The '''upper-left''' quadrant represents the '''tens''' place.
:* The '''lower-right''' quadrant represents the '''hundreds''' place.
:* The '''lower-left''' quadrant represents the '''thousands''' place.

Please consult the following image for examples of Cistercian numerals showing each glyph: [https://upload.wikimedia.org/wikipedia/commons/6/67/Cistercian_digits_%28vertical%29.svg]

;Task

:* Write a function/procedure/routine to display any given Cistercian numeral. This could be done by drawing to the display, creating an image, or even as text (as long as it is a reasonable facsimile).

:* Use the routine to show the following Cistercian numerals:

::* 0
::* 1
::* 20
::* 300
::* 4000
::* 5555
::* 6789
::* And a number of your choice!

;Notes
Due to the inability to upload images to Rosetta Code as of this task's creation, showing output here on this page is not required. However, it is welcomed -- especially for text output.

;See also

:* '''Numberphile - The Forgotten Number System'''
:* '''dcode.fr - Online Cistercian numeral converter'''

Solution:
def initN
    n = Array.new(15){Array.new(11, ' ')}
    for i in 1..15
        n[i - 1][5] = 'x'
    end
    return n
end

def horiz(n, c1, c2, r)
    for c in c1..c2
        n[r][c] = 'x'
    end
end

def verti(n, r1, r2, c)
    for r in r1..r2
        n[r][c] = 'x'
    end
end

def diagd(n, c1, c2, r)
    for c in c1..c2
        n[r+c-c1][c] = 'x'
    end
end

def diagu(n, c1, c2, r)
    for c in c1..c2
        n[r-c+c1][c] = 'x'
    end
end

def initDraw
    draw = []

    draw[1] = lambda do |n| horiz(n, 6, 10, 0) end
    draw[2] = lambda do |n| horiz(n, 6, 10, 4) end
    draw[3] = lambda do |n| diagd(n, 6, 10, 0) end
    draw[4] = lambda do |n| diagu(n, 6, 10, 4) end
    draw[5] = lambda do |n|
        draw[1].call(n)
        draw[4].call(n)
    end
    draw[6] = lambda do |n| verti(n, 0, 4, 10) end
    draw[7] = lambda do |n|
        draw[1].call(n)
        draw[6].call(n)
    end
    draw[8] = lambda do |n|
        draw[2].call(n)
        draw[6].call(n)
    end
    draw[9] = lambda do |n|
        draw[1].call(n)
        draw[8].call(n)
    end

    draw[10] = lambda do |n| horiz(n, 0, 4, 0) end
    draw[20] = lambda do |n| horiz(n, 0, 4, 4) end
    draw[30] = lambda do |n| diagu(n, 0, 4, 4) end
    draw[40] = lambda do |n| diagd(n, 0, 4, 0) end
    draw[50] = lambda do |n|
        draw[10].call(n)
        draw[40].call(n)
    end
    draw[60] = lambda do |n| verti(n, 0, 4, 0) end
    draw[70] = lambda do |n|
        draw[10].call(n)
        draw[60].call(n)
    end
    draw[80] = lambda do |n|
        draw[20].call(n)
        draw[60].call(n)
    end
    draw[90] = lambda do |n|
        draw[10].call(n)
        draw[80].call(n)
    end

    draw[100] = lambda do |n| horiz(n, 6, 10, 14) end
    draw[200] = lambda do |n| horiz(n, 6, 10, 10) end
    draw[300] = lambda do |n| diagu(n, 6, 10, 14) end
    draw[400] = lambda do |n| diagd(n, 6, 10, 10) end
    draw[500] = lambda do |n|
        draw[100].call(n)
        draw[400].call(n)
    end
    draw[600] = lambda do |n| verti(n, 10, 14, 10) end
    draw[700] = lambda do |n|
        draw[100].call(n)
        draw[600].call(n)
    end
    draw[800] = lambda do |n|
        draw[200].call(n)
        draw[600].call(n)
    end
    draw[900] = lambda do |n|
        draw[100].call(n)
        draw[800].call(n)
    end

    draw[1000] = lambda do |n| horiz(n, 0, 4, 14) end
    draw[2000] = lambda do |n| horiz(n, 0, 4, 10) end
    draw[3000] = lambda do |n| diagd(n, 0, 4, 10) end
    draw[4000] = lambda do |n| diagu(n, 0, 4, 14) end
    draw[5000] = lambda do |n|
        draw[1000].call(n)
        draw[4000].call(n)
    end
    draw[6000] = lambda do |n| verti(n, 10, 14, 0) end
    draw[7000] = lambda do |n|
        draw[1000].call(n)
        draw[6000].call(n)
    end
    draw[8000] = lambda do |n|
        draw[2000].call(n)
        draw[6000].call(n)
    end
    draw[9000] = lambda do |n|
        draw[1000].call(n)
        draw[8000].call(n)
    end

    return draw
end

def printNumeral(n)
    for a in n
        for b in a
            print b
        end
        print "\n"
    end
    print "\n"
end

draw = initDraw()
for number in [0, 1, 20, 300, 4000, 5555, 6789, 9999]
    n = initN()
    print number, ":\n"

    thousands = (number / 1000).floor
    number = number % 1000

    hundreds = (number / 100).floor
    number = number % 100

    tens = (number / 10).floor
    ones = number % 10

    if thousands > 0 then
        draw[thousands * 1000].call(n)
    end
    if hundreds > 0 then
        draw[hundreds * 100].call(n)
    end
    if tens > 0 then
        draw[tens * 10].call(n)
    end
    if ones > 0 then
        draw[ones].call(n)
    end
    printNumeral(n)
end


Closures/Value capture

Create a list of ten functions, in the simplest manner possible   (anonymous functions are encouraged),   such that the function at index   '' i ''    (you may choose to start    '' i ''    from either    '''0'''    or    '''1'''),     when run, should return the square of the index,   that is,    '' i '' 2.

Display the result of running any but the last function, to demonstrate that the function indeed remembers its value.

;Goal:
Demonstrate how to create a series of independent closures based on the same template but maintain separate copies of the variable closed over.

In imperative languages, one would generally use a loop with a mutable counter variable.

For each function to maintain the correct number, it has to capture the ''value'' of the variable at the time it was created, rather than just a reference to the variable, which would have a different value by the time the function was run.

See also: [[Multiple distinct objects]]

Solution:
procs = Array.new(10){|i| ->{i*i} } # -> creates a lambda
p procs[7].call # => 49


Colorful numbers

A '''colorful number''' is a non-negative base 10 integer where the product of every sub group of consecutive digits is unique.

;E.G.

24753 is a colorful number. 2, 4, 7, 5, 3, (2x4)8, (4x7)28, (7x5)35, (5x3)15, (2x4x7)56, (4x7x5)140, (7x5x3)105, (2x4x7x5)280, (4x7x5x3)420, (2x4x7x5x3)840

Every product is unique.

2346 is '''not''' a colorful number. 2, 3, 4, '''6''', (2x3)'''6''', (3x4)12, (4x6)24, (2x3x4)48, (3x4x6)72, (2x3x4x6)144

The product '''6''' is repeated.

Single digit numbers '''are''' considered to be colorful. A colorful number larger than 9 cannot contain a repeated digit, the digit 0 or the digit 1. As a consequence, there is a firm upper limit for colorful numbers; no colorful number can have more than 8 digits.

;Task

* Write a routine (subroutine, function, procedure, whatever it may be called in your language) to test if a number is a colorful number or not.
* Use that routine to find all of the colorful numbers less than 100.
* Use that routine to find the largest possible colorful number.

;Stretch

* Find and display the count of colorful numbers in each order of magnitude.
* Find and show the total count of '''all''' colorful numbers.

''Colorful numbers have no real number theory application. They are more a recreational math puzzle than a useful tool.''

Solution:
def colorful?(ar)
  products = []
  (1..ar.size).all? do |chunk_size|
    ar.each_cons(chunk_size) do |chunk|
      product = chunk.inject(&:*)
      return false if products.include?(product)
      products << product
    end
  end
end

below100 = (0..100).select{|n| colorful?(n.digits)}
puts "The colorful numbers less than 100 are:", below100.join(" "), ""
puts "Largest colorful number: #{(98765432.downto(1).detect{|n| colorful?(n.digits) })}", ""

total = 0
(1..8).each do |numdigs|
   digits = (numdigs == 1 ? (0..9).to_a : (2..9).to_a)
   count  = digits.permutation(numdigs).count{|perm| colorful?(perm)}
   puts "#{numdigs} digit colorful numbers count: #{count}"
   total += count
end

puts "\nTotal colorful numbers: #{total}"


Comma quibbling

Comma quibbling is a task originally set by Eric Lippert in his blog.

;Task:

Write a function to generate a string output which is the concatenation of input words from a list/sequence where:
# An input of no words produces the output string of just the two brace characters "{}".
# An input of just one word, e.g. ["ABC"], produces the output string of the word inside the two braces, e.g. "{ABC}".
# An input of two words, e.g. ["ABC", "DEF"], produces the output string of the two words inside the two braces with the words separated by the string " and ", e.g. "{ABC and DEF}".
# An input of three or more words, e.g. ["ABC", "DEF", "G", "H"], produces the output string of all but the last word separated by ", " with the last word separated by " and " and all within braces; e.g. "{ABC, DEF, G and H}".

Test your function with the following series of inputs showing your output here on this page:
* []                       # (No input words).
* ["ABC"]
* ["ABC", "DEF"]
* ["ABC", "DEF", "G", "H"]

Note: Assume words are non-empty strings of uppercase characters for this task.

Solution:
def comma_quibbling(a)
  %w<{ }>.join(a.length < 2 ? a.first :
               "#{a[0..-2].join(', ')} and #{a[-1]}")
end

[[], %w<ABC>, %w<ABC DEF>, %w<ABC DEF G H>].each do |a|
  puts comma_quibbling(a)
end


Compare a list of strings

Given a   list   of arbitrarily many strings, show how to:

*   test if they are all lexically '''equal'''
*   test if every string is lexically '''less than''' the one after it  ''(i.e. whether the list is in strict ascending order)''

Each of those two tests should result in a single true or false value, which could be used as the condition of an    if    statement or similar.

If the input list has less than two elements, the tests should always return true.

There is ''no'' need to provide a complete program and output.

Assume that the strings are already stored in an array/list/sequence/tuple variable (whatever is most idiomatic) with the name   strings,   and just show the expressions for performing those two tests on it (plus of course any includes and custom functions etc. that it needs),   with as little distractions as possible.

Try to write your solution in a way that does not modify the original list,   but if it does then please add a note to make that clear to readers.

If you need further guidance/clarification,   see [[#Perl]] and [[#Python]] for solutions that use implicit short-circuiting loops,   and [[#Raku]] for a solution that gets away with simply using a built-in language feature.

Solution:
strings.all?{|str| str == strings.first} # all equal?
strings.each_cons(2).all?{|str1, str2| str1 < str2} # ascending?


Composite numbers k with no single digit factors whose factors are all substrings of k

Find the composite numbers '''k''' in base 10, that have no single digit prime factors and whose prime factors are all a substring of '''k'''.

;Task

* Find and show here, on this page, the first ten elements of the sequence.

;Stretch

* Find and show the next ten elements.

Solution:
require 'prime'

generator2357 = Enumerator.new do |y|
  gen23 = Prime::Generator23.new
  gen23.each {|n| y << n unless (n%5 == 0 || n%7 == 0) }
end

res = generator2357.lazy.select do |n|
  primes, exp = n.prime_division.transpose
  next if exp.sum < 2 #exclude primes
  s = n.to_s
  primes.all?{|pr| s.match?(-pr.to_s) }
end

res.take(10).each{|n| puts n}


Conjugate transpose

Suppose that a conjugate transpose of M is a matrix M^H containing the [[complex conjugate]]s of the [[matrix transposition]] of M.

::: (M^H)_{ji} = \overline{M_{ij}}

This means that   row j, column i of the conjugate transpose equals the
complex conjugate of row i, column j of the original matrix.

In the next list, M must also be a square matrix.

* A Hermitian matrix equals its own conjugate transpose: M^H = M.
* A multiplication with its conjugate transpose: M^HM = MM^H.
* A iff M^HM = I_n and iff MM^H = I_n, where I_n is the identity matrix.

;Task:
Given some matrix of complex numbers, find its conjugate transpose.

Also determine if the matrix is a:
::* Hermitian matrix,
::* normal matrix,  or
::* unitary matrix.

;See also:
* MathWorld entry: conjugate transpose
* MathWorld entry: Hermitian matrix
* MathWorld entry: normal matrix
* MathWorld entry: unitary matrix

Solution:
require 'matrix'

# Start with some matrix.
i = Complex::I
matrix = Matrix[[i, 0, 0],
                [0, i, 0],
                [0, 0, i]]

# Find the conjugate transpose.
#   Matrix#conjugate appeared in Ruby 1.9.2.
conjt = matrix.conj.t           # aliases for matrix.conjugate.tranpose
print 'conjugate tranpose: '; puts conjt

if matrix.square?
  # These predicates appeared in Ruby 1.9.3.
  print 'Hermitian? '; puts matrix.hermitian?
  print '   normal? '; puts matrix.normal?
  print '  unitary? '; puts matrix.unitary?
else
  # Matrix is not square. These predicates would
  # raise ExceptionForMatrix::ErrDimensionMismatch.
  print 'Hermitian? false'
  print '   normal? false'
  print '  unitary? false'
end


Continued fraction

A number may be represented as a continued fraction (see Mathworld for more information) as follows:
:a_0 + \cfrac{b_1}{a_1 + \cfrac{b_2}{a_2 + \cfrac{b_3}{a_3 + \ddots}}}

The task is to write a program which generates such a number and prints a real representation of it. The code should be tested by calculating and printing the square root of 2, Napier's Constant, and Pi, using the following coefficients:

For the square root of 2, use a_0 = 1 then a_N = 2. b_N is always 1.

:\sqrt{2} = 1 + \cfrac{1}{2 + \cfrac{1}{2 + \cfrac{1}{2 + \ddots}}}

For Napier's Constant, use a_0 = 2, then a_N = N. b_1 = 1 then b_N = N-1.

:e = 2 + \cfrac{1}{1 + \cfrac{1}{2 + \cfrac{2}{3 + \cfrac{3}{4 + \ddots}}}}

For Pi, use a_0 = 3 then a_N = 6. b_N = (2N-1)^2.

:\pi = 3 + \cfrac{1}{6 + \cfrac{9}{6 + \cfrac{25}{6 + \ddots}}}

;See also:
:*   [[Continued fraction/Arithmetic]] for tasks that do arithmetic over continued fractions.

Solution:
require 'bigdecimal'

# square root of 2
sqrt2 = Object.new
def sqrt2.a(n); n == 1 ? 1 : 2; end
def sqrt2.b(n); 1; end

# Napier's constant
napier = Object.new
def napier.a(n); n == 1 ? 2 : n - 1; end
def napier.b(n); n == 1 ? 1 : n - 1; end

pi = Object.new
def pi.a(n); n == 1 ? 3 : 6; end
def pi.b(n); (2*n - 1)**2; end

# Estimates the value of a continued fraction _cfrac_, to _prec_
# decimal digits of precision. Returns a BigDecimal. _cfrac_ must
# respond to _cfrac.a(n)_ and _cfrac.b(n)_ for integer _n_ >= 1.
def estimate(cfrac, prec)
  last_result = nil
  terms = prec

  loop do
    # Estimate continued fraction for _n_ from 1 to _terms_.
    result = cfrac.a(terms)
    (terms - 1).downto(1) do |n|
      a = BigDecimal cfrac.a(n)
      b = BigDecimal cfrac.b(n)
      digits = [b.div(result, 1).exponent + prec, 1].max
      result = a + b.div(result, digits)
    end
    result = result.round(prec)

    if result == last_result
      return result
    else
      # Double _terms_ and try again.
      last_result = result
      terms *= 2
    end
  end
end

puts estimate(sqrt2, 50).to_s('F')
puts estimate(napier, 50).to_s('F')
puts estimate(pi, 10).to_s('F')


Continued fraction/Arithmetic/Construct from rational number

To understand this task in context please see [[Continued fraction arithmetic]]
The purpose of this task is to write a function \mathit{r2cf}(\mathrm{int} N_1, \mathrm{int} N_2), or \mathit{r2cf}(\mathrm{Fraction} N), which will output a continued fraction assuming:
:N_1 is the numerator
:N_2 is the denominator

The function should output its results one digit at a time each time it is called, in a manner sometimes described as lazy evaluation.

To achieve this it must determine: the integer part; and remainder part, of N_1 divided by N_2. It then sets N_1 to N_2 and N_2 to the determined remainder part. It then outputs the determined integer part. It does this until \mathrm{abs}(N_2) is zero.

Demonstrate the function by outputing the continued fraction for:
: 1/2
: 3
: 23/8
: 13/11
: 22/7
: -151/77
\sqrt 2 should approach [1; 2, 2, 2, 2, \ldots] try ever closer rational approximations until boredom gets the better of you:
: 14142,10000
: 141421,100000
: 1414214,1000000
: 14142136,10000000

Try :
: 31,10
: 314,100
: 3142,1000
: 31428,10000
: 314285,100000
: 3142857,1000000
: 31428571,10000000
: 314285714,100000000

Observe how this rational number behaves differently to \sqrt 2 and convince yourself that, in the same way as 3.7 may be represented as 3.70 when an extra decimal place is required, [3;7] may be represented as [3;7,\infty] when an extra term is required.

Solution:
[[1,2], [3,1], [23,8], [13,11], [22,7], [-151,77]].each do |n1,n2|
  print "%10s : " % "#{n1} / #{n2}"
  r2cf(n1,n2) {|n| print "#{n} "}
  puts
end


Continued fraction/Arithmetic/G(matrix ng, continued fraction n)

This task investigates mathmatical operations that can be performed on a single continued fraction. This requires only a baby version of NG:
: \begin{bmatrix}
  a_1 & a \\
  b_1 & b
\end{bmatrix}
I may perform perform the following operations:
:Input the next term of N1
:Output a term of the continued fraction resulting from the operation.

I output a term if the integer parts of \frac{a}{b} and \frac{a_1}{b_1} are equal. Otherwise I input a term from N. If I need a term from N but N has no more terms I inject \infty.

When I input a term t my internal state: \begin{bmatrix}
  a_1 & a \\
  b_1 & b
\end{bmatrix} is transposed thus \begin{bmatrix} a + a_1 * t & a_1  \\
  b + b_1 * t & b_1
\end{bmatrix}

When I output a term t my internal state: \begin{bmatrix}
  a_1 & a \\
  b_1 & b
\end{bmatrix} is transposed thus \begin{bmatrix} b_1 & b  \\
  a_1 - b_1 * t & a - b * t
\end{bmatrix}

When I need a term t but there are no more my internal state: \begin{bmatrix}
  a_1 & a \\
  b_1 & b
\end{bmatrix} is transposed thus \begin{bmatrix} a_1 & a_1 \\
  b_1 & b_1
\end{bmatrix}

I am done when b1 and b are zero.

Demonstrate your solution by calculating:
:[1;5,2] + 1/2
:[3;7] + 1/2
:[3;7] divided by 4
Using a generator for \sqrt{2} (e.g., from [[Continued fraction]]) calculate \frac{1}{\sqrt{2}}. You are now at the starting line for using Continued Fractions to implement [[Arithmetic-geometric mean]] without ulps and epsilons.

The first step in implementing [[Arithmetic-geometric mean]] is to calculate \frac{1 + \frac{1}{\sqrt{2}}}{2} do this now to cross the starting line and begin the race.

Solution:
# I define a class to implement baby NG
class NG
  def initialize(a1, a, b1, b)
    @a1, @a, @b1, @b = a1, a, b1, b
  end
  def ingress(n)
    @a, @a1 = @a1, @a + @a1 * n
    @b, @b1 = @b1, @b + @b1 * n
  end
  def needterm?
    return true if @b == 0 or @b1 == 0
    return true unless @a/@b == @a1/@b1
    false
  end
  def egress
    n = @a / @b
    @a,  @b  = @b,  @a  - @b  * n
    @a1, @b1 = @b1, @a1 - @b1 * n
    n
  end
  def egress_done
    @a, @b = @a1, @b1 if needterm?
    egress
  end
  def done?
    @b == 0 and @b1 == 0
  end
end


Convert decimal number to rational

The task is to write a program to transform a decimal number into a fraction in lowest terms.

It is not always possible to do this exactly. For instance, while rational numbers can be converted to decimal representation, some of them need an infinite number of digits to be represented exactly in decimal form. Namely, repeating decimals such as 1/3 = 0.333...

Because of this, the following fractions cannot be obtained (reliably) unless the language has some way of representing repeating decimals:
* 67 / 74 = 0.9(054) = 0.9054054...
* 14 / 27 = 0.(518)  = 0.518518...

Acceptable output:

* 0.9054054 - 4527027 / 5000000
* 0.518518  - 259259 / 500000

Finite decimals are of course no problem:

* 0.75      - 3 / 4

Solution:
> '0.9054054 0.518518 0.75'.split.each { |d| puts "%s %s" % [d, Rational(d)] }
0.9054054 4527027/5000000
0.518518 259259/500000
0.75 3/4
=> ["0.9054054", "0.518518", "0.75"]


Convert decimal number to rational

Solution:
A suffix for integer and float literals was introduced:

2.1.0p0 :001 > 0.9054054r
 => (4527027/5000000)
2.1.0p0 :002 > 0.518518r
 => (259259/500000)
2.1.0p0 :003 > 0.75r
 => (3/4)


Convert seconds to compound duration

Write a function or program which:
*   takes a positive integer representing a duration in seconds as input (e.g., 100), and
*   returns a string which shows the same duration decomposed into:
:::*   weeks,
:::*   days,
:::*   hours,
:::*   minutes,   and
:::*   seconds.

This is detailed below (e.g., "2 hr, 59 sec").

Demonstrate that it passes the following three test-cases:

'''''Test Cases'''''

:::::{| class="wikitable"
|-
! input number
! output string
|-
| 7259
| 2 hr, 59 sec
|-
| 86400
| 1 d
|-
| 6000000
| 9 wk, 6 d, 10 hr, 40 min
|}

'''''Details'''''

The following five units should be used:
:::::{| class="wikitable"
|-
! unit
! suffix used in output
! conversion
|-
| week
| wk
| 1 week = 7 days
|-
| day
| d
| 1 day = 24 hours
|-
| hour
| hr
| 1 hour = 60 minutes
|-
| minute
| min
| 1 minute = 60 seconds
|-
| second
| sec
|
|}

However, '''only''' include quantities with non-zero values in the output (e.g., return "1 d" and not "0 wk, 1 d, 0 hr, 0 min, 0 sec").

Give larger units precedence over smaller ones as much as possible (e.g., return 2 min, 10 sec and not 1 min, 70 sec or 130 sec)

Mimic the formatting shown in the test-cases (quantities sorted from largest unit to smallest and separated by comma+space; value and unit of each quantity separated by space).

Solution:
MINUTE = 60
HOUR   = MINUTE*60
DAY    = HOUR*24
WEEK   = DAY*7

def sec_to_str(sec)
  w, rem = sec.divmod(WEEK)
  d, rem = rem.divmod(DAY)
  h, rem = rem.divmod(HOUR)
  m, s   = rem.divmod(MINUTE)
  units  = ["#{w} wk", "#{d} d", "#{h} h", "#{m} min", "#{s} sec"]
  units.reject{|str| str.start_with?("0")}.join(", ")
end

[7259, 86400, 6000000].each{|t| puts "#{t}\t: #{sec_to_str(t)}"}


Count the coins

There are four types of common coins in   US   currency:
:::#   quarters   (25 cents)
:::#   dimes   (10 cents)
:::#   nickels   (5 cents),   and
:::#   pennies   (1 cent)

There are six ways to make change for 15 cents:
:::#   A dime and a nickel
:::#   A dime and 5 pennies
:::#   3 nickels
:::#   2 nickels and 5 pennies
:::#   A nickel and 10 pennies
:::#   15 pennies

;Task:
How many ways are there to make change for a dollar using these common coins?     (1 dollar = 100 cents).

;Optional:
Less common are dollar coins (100 cents);   and very rare are half dollars (50 cents).   With the addition of these two coins, how many ways are there to make change for $1000?

(Note:   the answer is larger than   232).

;References:
* an algorithm from the book ''Structure and Interpretation of Computer Programs''.
* an article in the algorithmist.
* Change-making problem on Wikipedia.

Solution:
def make_change(amount, coins)
  @cache = Array.new(amount+1){|i| Array.new(coins.size, i.zero? ? 1 : nil)}
  @coins = coins
  do_count(amount, @coins.length - 1)
end

def do_count(n, m)
  if n < 0 || m < 0
    0
  elsif @cache[n][m]
    @cache[n][m]
  else
    @cache[n][m] = do_count(n-@coins[m], m) + do_count(n, m-1)
  end
end

p make_change(   1_00, [1,5,10,25])
p make_change(1000_00, [1,5,10,25,50,100])


Create an HTML table

Create an HTML table.
* The table body should have at least three rows of three columns.
* Each of these three columns should be labelled "X", "Y", and "Z".
* An extra column should be added at either the extreme left or the extreme right of the table that has no heading, but is filled with sequential row numbers.
* The rows of the "X", "Y", and "Z" columns should be filled with random or sequential integers having 4 digits or less.
* The numbers should be aligned in the same fashion for all columns.

Solution:
def r
  rand(10000)
end

STDOUT << "".tap do |html|
  html << "
"
  [
    ['X', 'Y', 'Z'],
    [r ,r ,r],
    [r ,r ,r],
    [r ,r ,r],
    [r ,r ,r]

  ].each_with_index do |row, index|
    html << "
"
    html << "#{index > 0 ? index : nil }	"
    html << row.map { |e| "#{e}	"}.join
    html << "
"
  end

  html << "
"
end


Cullen and Woodall numbers

A Cullen number is a number of the form '''n x 2n + 1''' where '''n''' is a natural number.

A Woodall number is very similar. It is a number of the form '''n x 2n - 1''' where '''n''' is a natural number.

So for each '''n''' the associated Cullen number and Woodall number differ by 2.

''Woodall numbers are sometimes referred to as Riesel numbers or Cullen numbers of the second kind.''

'''Cullen primes''' are Cullen numbers that are prime. Similarly, '''Woodall primes''' are Woodall numbers that are prime.

It is common to list the Cullen and Woodall primes by the value of '''n''' rather than the full evaluated expression. They tend to get very large very quickly. For example, the third Cullen prime, '''n''' == 4713, has 1423 digits when evaluated.

;Task

* Write procedures to find Cullen numbers and Woodall numbers.

* Use those procedures to find and show here, on this page the first 20 of each.

;Stretch

* Find and show the first '''5''' '''Cullen primes''' in terms of '''n'''.

* Find and show the first '''12''' '''Woodall primes''' in terms of '''n'''.

;See also

* OEIS:A002064 - Cullen numbers: a(n) = n*2^n + 1

* OEIS:A003261 - Woodall (or Riesel) numbers: n*2^n - 1

* OEIS:A005849 - Indices of prime Cullen numbers: numbers k such that k*2^k + 1 is prime

* OEIS:A002234 - Numbers k such that the Woodall number k*2^k - 1 is prime

Solution:
require 'openssl'

cullen  = Enumerator.new{|y| (1..).each{|n| y << (n*(1<<n) + 1)} }
woodall = Enumerator.new{|y| (1..).each{|n| y << (n*(1<<n) - 1)} }
cullen_primes  = Enumerator.new{|y| (1..).each {|i|y << i if OpenSSL::BN.new(cullen.next).prime?}}
woodall_primes = Enumerator.new{|y| (1..).each{|i|y << i if OpenSSL::BN.new(woodall.next).prime?}}

num = 20
puts "First #{num} Cullen numbers:\n#{cullen.first(num).join(" ")}"
puts "First #{num} Woodal numbers:\n#{woodall.first(num).join(" ")}"
puts "First 5 Cullen primes:\n#{cullen_primes.first(5).join(", ")}"
puts "First 12 Woodall primes:\n#{woodall_primes.first(12).join(", ")}"


Currency

Show how to represent currency in a simple example, using a data type that represent exact values of dollars and cents.

;Note:
The '''IEEE 754''' binary floating point representations of numbers like   '''2.86'''   and   '''.0765'''   are not exact.

For this example, data will be two items with prices in dollars and cents, a quantity for each, and a tax rate.

Use the values:
::* 4000000000000000 hamburgers at $5.50 each       (four quadrillion burgers)
::* 2 milkshakes at $2.86 each, and
::* a tax rate of 7.65%.

(That number of hamburgers is a 4 with 15 zeros after it.    The number is contrived to exclude naive task solutions using 64 bit floating point types.)

Compute and output (show results on this page):
::* the total price before tax
::* the tax
::* the total with tax

The tax value must be computed by rounding to the nearest whole cent and this exact value must be added to the total price before tax.

The output must show dollars and cents with a decimal point.

The three results displayed should be:
::* 22000000000000005.72
::* 1683000000000000.44
::* 23683000000000006.16

Dollar signs and thousands separators are optional.

Solution:
require 'bigdecimal/util'

before_tax = 4000000000000000 * 5.50.to_d + 2 * 2.86.to_d
tax        = (before_tax * 0.0765.to_d).round(2)
total      = before_tax + tax

puts "Before tax: $#{before_tax.to_s('F')}
Tax: $#{tax.to_s('F')}
Total: $#{total.to_s('F')}"


Currying

{{Wikipedia|Currying}}

;Task:
Create a simple demonstrative example of Currying in a specific language.

Add any historic details as to how the feature made its way into the language.

Solution:
b = proc {|x, y, z| (x||0) + (y||0) + (z||0) }
p b.curry[1][2][3]           #=> 6
p b.curry[1, 2][3, 4]        #=> 6
p b.curry(5)[1][2][3][4][5]  #=> 6
p b.curry(5)[1, 2][3, 4][5]  #=> 6
p b.curry(1)[1]              #=> 1

b = proc {|x, y, z, *w| (x||0) + (y||0) + (z||0) + w.inject(0, &:+) }
p b.curry[1][2][3]           #=> 6
p b.curry[1, 2][3, 4]        #=> 10
p b.curry(5)[1][2][3][4][5]  #=> 15
p b.curry(5)[1, 2][3, 4][5]  #=> 15
p b.curry(1)[1]              #=> 1


Curzon numbers

A '''Curzon number''' is defined to be a positive integer '''n''' for which '''2n + 1''' is evenly divisible by  '''2 x n + 1'''.

'''Generalized Curzon numbers''' are those where the positive integer '''n''', using a base integer '''k''', satisfy the condition that '''kn + 1''' is evenly divisible by  '''k x n + 1'''.

''Base here does not imply the radix of the counting system; rather the integer the equation is based on. All calculations should be done in base 10.''

Generalized Curzon numbers only exist for even base integers.

;Task

* Find and show the first '''50 Generalized Curzon numbers''' for even base integers from '''2''' through '''10'''.

;Stretch

* Find and show the '''one thousandth'''.

;See also

;* Numbers Aplenty - Curzon numbers
;* OEIS:A224486 - Numbers k such that 2*k+1 divides 2^k+1 (Curzon numbers)

''and even though it is not specifically mentioned that they are Curzon numbers:''

;* OEIS:A230076 - (A007521(n)-1)/4 (Generalized Curzon numbers with a base 4)

Solution:
def curzons(k)
  Enumerator.new do |y|
    (1..).each do |n|
      r = k * n
      y << n if k.pow(n, r + 1) == r
    end
  end
end

[2,4,6,8,10].each do |base|
  puts "Curzon numbers with k = #{base}:"
  puts curzons(base).take(50).join(", ")
  puts "Thousandth Curzon with k = #{base}: #{curzons(base).find.each.with_index(1){|_,i| i == 1000} }",""
end


Cut a rectangle

A given rectangle is made from ''m'' x ''n'' squares. If ''m'' and ''n'' are not both odd, then it is possible to cut a path through the rectangle along the square edges such that the rectangle splits into two connected pieces with the same shape (after rotating one of the pieces by 180deg). All such paths for 2 x 2 and 4 x 3 rectangles are shown below.

[[file:rect-cut.svg]]

Write a program that calculates the number of different ways to cut an ''m'' x ''n'' rectangle.  Optionally, show each of the cuts.

Possibly related task: [[Maze generation]] for depth-first search.

Solution:
def cut_it(h, w)
  if h.odd?
    return 0  if w.odd?
    h, w = w, h
  end
  return 1  if w == 1

  nxt = [[w+1, 1, 0], [-w-1, -1, 0], [-1, 0, -1], [1, 0, 1]]  # [next,dy,dx]
  blen = (h + 1) * (w + 1) - 1
  grid = [false] * (blen + 1)

  walk = lambda do |y, x, count=0|
    return count+1  if y==0 or y==h or x==0 or x==w
    t = y * (w + 1) + x
    grid[t] = grid[blen - t] = true
    nxt.each do |nt, dy, dx|
      count += walk[y + dy, x + dx]  unless grid[t + nt]
    end
    grid[t] = grid[blen - t] = false
    count
  end

  t = h / 2 * (w + 1) + w / 2
  if w.odd?
    grid[t] = grid[t + 1] = true
    count = walk[h / 2, w / 2 - 1]
    count + walk[h / 2 - 1, w / 2] * 2
  else
    grid[t] = true
    count = walk[h / 2, w / 2 - 1]
    return count * 2  if h == w
    count + walk[h / 2 - 1, w / 2]
  end
end

for w in 1..9
  for h in 1..w
    puts "%d x %d: %d" % [w, h, cut_it(w, h)]  if (w * h).even?
  end
end


Damm algorithm

The '''Damm''' algorithm is a checksum algorithm which detects all single digit errors and adjacent transposition errors.

The algorithm is named after H. Michael Damm.

;Task:
Verify the checksum, stored as last digit of an input.

Solution:
TABLE = [
    [0,3,1,7,5,9,8,6,4,2], [7,0,9,2,1,5,4,8,6,3],
    [4,2,0,6,8,7,1,3,5,9], [1,7,5,0,9,8,3,4,2,6],
    [6,1,2,3,0,4,5,9,7,8], [3,6,7,4,2,0,9,5,8,1],
    [5,8,6,9,7,2,0,1,3,4], [8,9,4,5,3,6,2,0,1,7],
    [9,4,3,8,6,1,7,2,0,5], [2,5,8,1,4,3,6,7,9,0]
]

def damm_valid?(n) = n.digits.reverse.inject(0){|idx, a| TABLE[idx][a] } == 0

[5724, 5727, 112946].each{|n| puts "#{n}: #{damm_valid?(n) ? "" : "in"}valid"}


De Bruijn sequences

{{DISPLAYTITLE:de Bruijn sequences}}
The sequences are named after the Dutch mathematician   Nicolaas Govert de Bruijn.

A note on Dutch capitalization:   Nicolaas' last name is   '''de Bruijn''',   the   '''de'''   isn't normally capitalized
unless it's the first word in a sentence.   Rosetta Code (more or less by default or by fiat) requires the first word in the task name to be
capitalized.

In combinatorial mathematics,   a   '''de Bruijn sequence'''   of order    ''n''    on
a    size-''k''    alphabet (computer science)    ''A''    is a cyclic sequence in which every
possible    length-''n''    string (computer science, formal theory)   on    ''A''    occurs
exactly once as a contiguous substring.

Such a sequence is denoted by    ''B''(''k'', ''n'')    and has
length   ''k''''n'',   which is also the number of distinct substrings of
length   ''n''   on   ''A'';
de Bruijn sequences are therefore optimally short.

There are:
                          (k!)k(n-1)   /   kn
distinct de Bruijn sequences    ''B''(''k'', ''n'').

;Task:
For this Rosetta Code task,   a   '''de Bruijn'''   sequence is to be generated that can be used to shorten a brute-force attack on
a   PIN-like   code lock that does not have an "enter"
key and accepts the last    ''n''    digits entered.

Note:   automated teller machines (ATMs)   used to work like
this,   but their software has been updated to not allow a brute-force attack.

;Example:
A   digital door lock   with a 4-digit code would
have ''B'' (10, 4) solutions,   with a length of   '''10,000'''   (digits).

Therefore, only at most     '''10,000 + 3'''     (as the solutions are cyclic or ''wrap-around'')   presses are needed to
open the lock.

Trying all 4-digit codes separately would require   '''4 x 10,000'''   or   '''40,000'''   presses.

;Task requirements:
:*   Generate a de Bruijn sequence for a 4-digit (decimal) PIN code.
:::*   Show the length of the generated de Bruijn sequence.
:::*   (There are many possible de Bruijn sequences that solve this task,   one solution is shown on the ''discussion'' page).
:::*   Show the first and last   '''130'''   digits of the de Bruijn sequence.
:*   Verify that all four-digit (decimal)   '''1,000'''   PIN codes are contained within the de Bruijn sequence.
:::*   0000, 0001, 0002, 0003,   ...   9996, 9997, 9998, 9999   (note the leading zeros).
:*   Reverse the de Bruijn sequence.
:*   Again, perform the (above) verification test.
:*   Replace the 4,444th digit with a period (.) in the original de Bruijn sequence.
:::*   Perform the verification test (again).   There should be four PIN codes missing.

(The last requirement is to ensure that the verification tests performs correctly.   The verification processes should list
any and all missing PIN codes.)

Show all output here, on this page.

;References:
:*   Wikipedia           entry:   de Bruijn sequence.
:*   MathWorld           entry:   de Bruijn sequence.
:*   An  OEIS  entry:   A166315 lexicographically earliest binary de Bruijn sequences, B(2,n)     --- Not B(10,4),   but possibly relevant.

Solution:
def deBruijn(k, n)
    alphabet = "0123456789"
    @a = Array.new(k * n, 0)
    @seq = []

    def db(k, n, t, p)
        if t > n then
            if n % p == 0 then
                temp = @a[1 .. p]
                @seq.concat temp
            end
        else
            @a[t] = @a[t - p]
            db(k, n, t + 1, p)
            j = @a[t - p] + 1
            while j < k do
                @a[t] = j # & 0xFF
                db(k, n, t + 1, t)
                j = j + 1
            end
        end
    end
    db(k, n, 1, 1)

    buf = ""
    for i in @seq
        buf <<= alphabet[i]
    end
    return buf + buf[0 .. n-2]
end

def validate(db)
    le = db.length
    found = Array.new(10000, 0)
    errs = []
    # Check all strings of 4 consecutive digits within 'db'
    # to see if all 10,000 combinations occur without duplication.
    for i in 0 .. le-4
        s = db[i .. i+3]
        if s.scan(/\D/).empty? then
            found[s.to_i] += 1
        end
    end
    for i in 0 .. found.length - 1
        if found[i] == 0 then
            errs <<= ("    PIN number %04d missing" % [i])
        elsif found[i] > 1 then
            errs <<= ("    PIN number %04d occurs %d times" % [i, found[i]])
        end
    end
    if errs.length == 0 then
        print "  No errors found\n"
    else
        pl = (errs.length == 1) ? "" : "s"
        print "  ", errs.length, " error", pl, " found:\n"
        for err in errs
            print err, "\n"
        end
    end
end

db = deBruijn(10, 4)
print "The length of the de Bruijn sequence is ", db.length, "\n\n"
print "The first 130 digits of the de Bruijn sequence are: ", db[0 .. 129], "\n\n"
print "The last 130 digits of the de Bruijn sequence are: ", db[-130 .. db.length], "\n\n"

print "Validating the de Bruijn sequence:\n"
validate(db)
print "\n"

db[4443] = '.'
print "Validating the overlaid de Bruijn sequence:\n"
validate(db)


Deceptive numbers

Repunits are numbers that consist entirely of repetitions of the digit one (unity).  The notation '''Rn''' symbolizes the repunit made up of '''n''' ones.

Every prime '''p''' larger than 5, evenly divides the repunit '''Rp-1'''.

;E.G.

The repunit '''R6''' is evenly divisible by '''7'''.

111111 / 7 = 15873

The repunit '''R42''' is evenly divisible by '''43'''.

111111111111111111111111111111111111111111 / 43 = 2583979328165374677002583979328165374677

And so on.

There are composite numbers that also have this same property. They are often referred to as ''deceptive non-primes'' or ''deceptive numbers''.

The repunit '''R90''' is evenly divisible by the composite number '''91''' (=7*13).

111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111 / 91 = 1221001221001221001221001221001221001221001221001221001221001221001221001221001221001221

;Task

* Find and show at least the first '''10 deceptive numbers'''; composite numbers '''n''' that evenly divide the repunit '''Rn-1'''

;See also

;* Numbers Aplenty - Deceptive numbers
;* OEIS:A000864 - Deceptive nonprimes: composite numbers k that divide the repunit R_{k-1}

Solution:
require 'prime'

deceptives = Enumerator.new do |y|
  10.step(by: 10) do |n|
    [1,3,7,9].each do |digit|
      cand = n + digit
      next if cand % 3 == 0 || cand.prime?
      repunit = ("1"*(cand-1)).to_i
      y << cand if (repunit % cand) == 0
    end
  end
end

p deceptives.take(25).to_a


Deepcopy

Demonstrate how to copy data structures containing complex heterogeneous and cyclic semantics.

This is often referred to as deep copying, and is normally required where structures are mutable and to ensure that independent copies can be manipulated without side-effects.

If this facility is not built into the language, it is permissible to use functions from a common library, or a coded procedure.

The task should show:

* Relevant semantics of structures, such as their homogeneous or heterogeneous properties, or containment of (self- or mutual-reference) cycles.

* Any limitations of the method.

* That the structure and its copy are different.

* Suitable links to external documentation for common libraries.

Solution:
# _orig_ is a Hash that contains an Array.
orig = { :num => 1, :ary => [2, 3] }
orig[:cycle] = orig	# _orig_ also contains itself.

# _copy_ becomes a deep copy of _orig_.
copy = Marshal.load(Marshal.dump orig)

# These changes to _orig_ never affect _copy_,
# because _orig_ and _copy_ are disjoint structures.
orig[:ary] << 4
orig[:rng] = (5..6)

# Because of deep copy, orig[:ary] and copy[:ary]
# refer to different Arrays.
p orig	# => {:num=>1, :ary=>[2, 3, 4], :cycle=>{...}, :rng=>5..6}
p copy	# => {:num=>1, :ary=>[2, 3], :cycle=>{...}}

# The original contains itself, and the copy contains itself,
# but the original and the copy are not the same object.
p [(orig.equal? orig[:cycle]),
   (copy.equal? copy[:cycle]),
   (not orig.equal? copy)]	# => [true, true, true]


Deming's funnel

W Edwards Deming was an American statistician and management guru who used physical demonstrations to illuminate his teachings.  In one demonstration Deming repeatedly dropped marbles through a funnel at a target, marking where they landed, and observing the resulting pattern.  He applied a sequence of "rules" to try to improve performance.  In each case the experiment begins with the funnel positioned directly over the target.

* '''Rule 1''': The funnel remains directly above the target.
* '''Rule 2''': Adjust the funnel position by shifting the target to compensate after each drop.  E.g. If the last drop missed 1 cm east, move the funnel 1 cm to the west of its current position.
* '''Rule 3''': As rule 2, but first move the funnel back over the target, before making the adjustment.  E.g. If the funnel is 2 cm north, and the marble lands 3 cm north, move the funnel 3 cm south of the target.
* '''Rule 4''': The funnel is moved directly over the last place a marble landed.

Apply the four rules to the set of 50 pseudorandom displacements provided (e.g in the Racket solution) for the dxs and dys.  '''Output''': calculate the mean and standard-deviations of the resulting x and y values for each rule.

Note that rules 2, 3, and 4 give successively worse results.  Trying to deterministically compensate for a random process is counter-productive, but -- according to Deming -- quite a popular pastime: see the Further Information, below for examples.

'''Stretch goal 1''': Generate fresh pseudorandom data.  The radial displacement of the drop from the funnel position is given by a Gaussian distribution (standard deviation is 1.0) and the angle of displacement is uniformly distributed.

'''Stretch goal 2''': Show scatter plots of all four results.

;Further information:
* Further explanation and interpretation
* Video demonstration of the funnel experiment at the Mayo Clinic.

Solution:
def funnel(dxs, &rule)
  x, rxs = 0, []
  for dx in dxs
    rxs << (x + dx)
    x = rule[x, dx]
  end
  rxs
end

def mean(xs) xs.inject(:+) / xs.size end

def stddev(xs)
  m = mean(xs)
  Math.sqrt(xs.inject(0.0){|sum,x| sum + (x-m)**2} / xs.size)
end

def experiment(label, dxs, dys, &rule)
  rxs, rys = funnel(dxs, &rule), funnel(dys, &rule)
  puts label
  puts 'Mean x, y    : %7.4f, %7.4f' % [mean(rxs), mean(rys)]
  puts 'Std dev x, y : %7.4f, %7.4f' % [stddev(rxs), stddev(rys)]
  puts
end

dxs = [ -0.533,  0.270,  0.859, -0.043, -0.205, -0.127, -0.071,  0.275,
         1.251, -0.231, -0.401,  0.269,  0.491,  0.951,  1.150,  0.001,
        -0.382,  0.161,  0.915,  2.080, -2.337,  0.034, -0.126,  0.014,
         0.709,  0.129, -1.093, -0.483, -1.193,  0.020, -0.051,  0.047,
        -0.095,  0.695,  0.340, -0.182,  0.287,  0.213, -0.423, -0.021,
        -0.134,  1.798,  0.021, -1.099, -0.361,  1.636, -1.134,  1.315,
         0.201,  0.034,  0.097, -0.170,  0.054, -0.553, -0.024, -0.181,
        -0.700, -0.361, -0.789,  0.279, -0.174, -0.009, -0.323, -0.658,
         0.348, -0.528,  0.881,  0.021, -0.853,  0.157,  0.648,  1.774,
        -1.043,  0.051,  0.021,  0.247, -0.310,  0.171,  0.000,  0.106,
         0.024, -0.386,  0.962,  0.765, -0.125, -0.289,  0.521,  0.017,
         0.281, -0.749, -0.149, -2.436, -0.909,  0.394, -0.113, -0.598,
         0.443, -0.521, -0.799,  0.087]

dys = [  0.136,  0.717,  0.459, -0.225,  1.392,  0.385,  0.121, -0.395,
         0.490, -0.682, -0.065,  0.242, -0.288,  0.658,  0.459,  0.000,
         0.426,  0.205, -0.765, -2.188, -0.742, -0.010,  0.089,  0.208,
         0.585,  0.633, -0.444, -0.351, -1.087,  0.199,  0.701,  0.096,
        -0.025, -0.868,  1.051,  0.157,  0.216,  0.162,  0.249, -0.007,
         0.009,  0.508, -0.790,  0.723,  0.881, -0.508,  0.393, -0.226,
         0.710,  0.038, -0.217,  0.831,  0.480,  0.407,  0.447, -0.295,
         1.126,  0.380,  0.549, -0.445, -0.046,  0.428, -0.074,  0.217,
        -0.822,  0.491,  1.347, -0.141,  1.230, -0.044,  0.079,  0.219,
         0.698,  0.275,  0.056,  0.031,  0.421,  0.064,  0.721,  0.104,
        -0.729,  0.650, -1.103,  0.154, -1.720,  0.051, -0.385,  0.477,
         1.537, -0.901,  0.939, -0.411,  0.341, -0.411,  0.106,  0.224,
        -0.947, -1.424, -0.542, -1.032]

experiment('Rule 1:', dxs, dys) {|z, dz| 0}
experiment('Rule 2:', dxs, dys) {|z, dz| -dz}
experiment('Rule 3:', dxs, dys) {|z, dz| -(z+dz)}
experiment('Rule 4:', dxs, dys) {|z, dz| z+dz}


Department numbers

There is a highly organized city that has decided to assign a number to each of their departments:
::*   police department
::*   sanitation department
::*   fire department

Each department can have a number between   '''1'''   and   '''7'''   (inclusive).

The three department numbers are to be unique (different from each other) and must add up to   '''12'''.

The Chief of the Police doesn't like odd numbers and wants to have an even number for his department.

;Task:
Write a computer program which outputs all valid combinations.

Possible output   (for the 1st and 14th solutions):

  --police--  --sanitation--  --fire--
      2             3            7
      6             5            1

Solution: (1..7).to_a.permutation(3){|p| puts p.join if p.first.even? && p.sum == 12 }


Descending primes

Generate and show all primes with strictly descending decimal digits.

;See also
;* OEIS:A052014 - Primes with distinct digits in descending order

;Related:
*[[Ascending primes]]

Solution:
require 'prime'

digits = [9,8,7,6,5,4,3,2,1].to_a
res = 1.upto(digits.size).flat_map do |n|
   digits.combination(n).filter_map do |set|
      candidate = set.join.to_i
      candidate if candidate.prime?
   end.reverse
 end

 puts res.join(",")


Detect division by zero

Write a function to detect a   ''divide by zero error''   without checking if the denominator is zero.

Solution:
def div_check(x, y)
  begin
    x / y
  rescue ZeroDivisionError
    true
  else
    false
  end
end


Detect division by zero

Solution:
def div_check(x, y)
  begin
    x.div y
  rescue ZeroDivisionError
    true
  else
    false
  end
end


Determinant and permanent

permanent of the matrix.

The determinant is given by
:: \det(A) = \sum_\sigma\sgn(\sigma)\prod_{i=1}^n M_{i,\sigma_i}
while the permanent is given by
::  \operatorname{perm}(A)=\sum_\sigma\prod_{i=1}^n M_{i,\sigma_i}
In both cases the sum is over the permutations \sigma of the permutations of 1, 2, ..., ''n''. (A permutation's sign is 1 if there are an even number of inversions and -1 otherwise; see parity of a permutation.)

More efficient algorithms for the determinant are known: [[LU decomposition]], see for example [[wp:LU decomposition#Computing the determinant]]. Efficient methods for calculating the permanent are not known.

;Related task:
* [[Permutations by swapping]]

Solution:
require 'matrix'

class Matrix
  # Add "permanent" method to Matrix class
  def permanent
    r = (0...row_count).to_a # [0,1] (first example), [0,1,2,3] (second example)
    r.permutation.inject(0) do |sum, sigma|
       sum += sigma.zip(r).inject(1){|prod, (row, col)| prod *= self[row, col] }
    end
  end
end

m1 = Matrix[[1,2],[3,4]] # testcases from Python version

m2 = Matrix[[1, 2, 3, 4], [4, 5, 6, 7], [7, 8, 9, 10], [10, 11, 12, 13]]

m3 = Matrix[[0, 1, 2, 3, 4],
            [5, 6, 7, 8, 9],
            [10, 11, 12, 13, 14],
            [15, 16, 17, 18, 19],
            [20, 21, 22, 23, 24]]

[m1, m2, m3].each do |m|
  puts "determinant:\t #{m.determinant}", "permanent:\t #{m.permanent}"
  puts
end


Determine if a string has all the same characters

Given a character string   (which may be empty, or have a length of zero characters):
::*   create a function/procedure/routine to:
::::*    determine if all the characters in the string are the same
::::*    indicate if or which character is different from the previous character
::*   display each string and its length   (as the strings are being examined)
::*   a zero-length (empty) string shall be considered as all the same character(s)
::*   process the strings from left-to-right
::*   if       all the same character,   display a message saying such
::*   if                  not all the same character,   then:
::::*    display a message saying such
::::*    display what character is different
::::*    only the 1st different character need be displayed
::::*    display where the different character is in the string
::::*    the above messages can be part of a single message
::::*    display the hexadecimal value of the different character

Use (at least) these seven test values   (strings):
:::*   a string of length   0   (an empty string)
:::*   a string of length   3   which contains three blanks
:::*   a string of length   1   which contains:   '''2'''
:::*   a string of length   3   which contains:   '''333'''
:::*   a string of length   3   which contains:   '''.55'''
:::*   a string of length   6   which contains:   '''tttTTT'''
:::*   a string of length   9   with a blank in the middle:   '''4444   444k'''

Show all output here on this page.

Solution:
strings = ["", "   ", "2", "333", ".55", "tttTTT", "4444   444k", "pépé", "🐶🐶🐺🐶", "🎄🎄🎄🎄"]

strings.each do |str|
  pos = str.empty? ? nil : str =~ /[^#{str[0]}]/
  print "#{str.inspect}  (size #{str.size}): "
  puts pos ? "first different char #{str[pos].inspect} (#{'%#x' % str[pos].ord}) at position #{pos}." : "all the same."
end


Determine if a string has all unique characters

Given a character string   (which may be empty, or have a length of zero characters):
::*   create a function/procedure/routine to:
::::*    determine if all the characters in the string are unique
::::*    indicate if or which character is duplicated and where
::*   display each string and its length   (as the strings are being examined)
::*   a zero-length (empty) string shall be considered as unique
::*   process the strings from left-to-right
::*   if       unique,   display a message saying such
::*   if                  not unique,   then:
::::*    display a message saying such
::::*    display what character is duplicated
::::*    only the 1st non-unique character need be displayed
::::*    display where "both" duplicated characters are in the string
::::*    the above messages can be part of a single message
::::*    display the hexadecimal value of the duplicated character

Use (at least) these five test values   (strings):
:::*   a string of length     0   (an empty string)
:::*   a string of length     1   which is a single period   ('''.''')
:::*   a string of length     6   which contains:   '''abcABC'''
:::*   a string of length     7   which contains a blank in the middle:   '''XYZ  ZYX'''
:::*   a string of length         36   which   ''doesn't''   contain the letter "oh":
::::::::  '''1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ'''

Show all output here on this page.

Solution:
strings = ["",
        ".",
        "abcABC",
        "XYZ ZYX",
        "1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ",
        "01234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ0X",
        "hétérogénéité",
        "🎆🎃🎇🎈",
        "😍😀🙌💃😍🙌",
        "🐠🐟🐡🦈🐬🐳🐋🐡",]

strings.each do |str|
  seen = {}
  print "#{str.inspect} (size #{str.size}) "
  res = "has no duplicates." #may change
  str.chars.each_with_index do |c,i|
    if seen[c].nil?
      seen[c] = i
    else
      res =  "has duplicate char #{c} (#{'%#x' % c.ord}) on #{seen[c]} and #{i}."
      break
    end
  end
  puts res
end