class Guess < String
  def self.play
    nums = Array.new(4){rand(1..9)}
    loop do
      result = get(nums).evaluate!
      break if result == 24.0
      puts "Try again! That gives #{result}!"
    end
    puts "You win!"
  end

  def self.get(nums)
    loop do
      print "\nEnter a guess using #{nums}: "
      input = gets.chomp
      return new(input) if validate(input, nums)
    end
  end

  def self.validate(guess, nums)
    name, error =
      {
        invalid_character:  ->(str){ !str.scan(%r{[^\d\s()+*/-]}).empty? },
        wrong_number:       ->(str){ str.scan(/\d/).map(&:to_i).sort != nums.sort },
        multi_digit_number: ->(str){ str.match(/\d\d/) }
      }
        .find {|name, validator| validator[guess] }

    error ? puts("Invalid input of a(n) #{name.to_s.tr('_',' ')}!") : true
  end

  def evaluate!
    as_rat = gsub(/(\d)/, '\1r')        # r : Rational suffix
    eval "(#{as_rat}).to_f"
  rescue SyntaxError
    "[syntax error]"
  end
end

Guess.play

"Generate a game that randomly selects four digits and prompts the user to create an arithmetic expression with these digits that equals 24. The code checks and evaluates the user's expression, allowing for addition, subtraction, multiplication, and division operations. The code does not allow the formation of multiple digit numbers from the given digits."


# run_encode("aaabbbbc") #=> [["a", 3], ["b", 4], ["c", 1]]
def run_encode(string)
  string
    .chars
    .chunk{|i| i}
    .map {|kind, array| [kind, array.length]}
end

# run_decode([["a", 3], ["b", 4], ["c", 1]]) #=> "aaabbbbc"
def run_decode(char_counts)
  char_counts
    .map{|char, count| char * count}
    .join
end
def encode(string)
  string.scan(/(.)(\1*)/).collect do |char, repeat|
    [1 + repeat.length, char]
  end.join
end

def decode(string)
  string.scan(/(\d+)(\D)/).collect {|length, char| char * length.to_i}.join
end

def encode(string)
  string.scan(/(.)(\1*)/).inject("") do |encoding, (char, repeat)|
    encoding << (1 + repeat.length).to_s << char
  end
end

def decode(string)
  string.scan(/(\d+)(\D)/).inject("") do |decoding, (length, char)|
    decoding << char * length.to_i
  end
end

def encode(str)
    str.gsub(/(.)\1*/) {$&.length.to_s + $1}
end

def decode(str)
    str.gsub(/(\d+)(\D)/) {$2 * $1.to_i}
end

orig = "WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW"
p enc = encode(orig)
p dec = decode(enc)
puts "success!" if dec == orig

The code implements a run-length encoding algorithm for a string containing uppercase characters (A-Z). It compresses repeated characters by storing the length of the run. It also provides a function to reverse the compression. The output can be used to recreate the original input. The code also includes a built-in Ruby method for run-length encoding and a regular expression method for encoding and decoding.


s = "hello"

puts "#{s} template"       #=> "hello template"
# Variable s is intact
puts s                     #=> "hello"

puts s + " literal"        #=> "hello literal"
# Variable s is still the same
puts s                     #=> "hello"

# Mutating s variable:

s += " literal"
puts s                     #=> "hello literal"
s << " another" # append to s, use only when string literals are not frozen
puts s                     #=> "hello literal another"

s = "hello"
puts s.concat(" literal")  #=> "hello literal"
puts s                     #=> "hello literal"
puts s.prepend("Alice said: ")  #=> "Alice said: hello literal"
puts s                     #=> "Alice said: hello literal"

Initializes two string variables, one with a text value and the other as a concatenation of the first variable and a string literal, then displays their content.


require 'cgi'
puts CGI.escape("http://foo bar/").gsub("+", "%20")
# => "http%3A%2F%2Ffoo%20bar%2F"

Works with: Ruby version 1.9.2
require 'uri'
puts URI.encode_www_form_component("http://foo bar/").gsub("+", "%20")
# => "http%3A%2F%2Ffoo%20bar%2F"

The code provides a function to convert a given string into URL encoding representation. It transforms special, control, and extended characters into a percent symbol followed by a two-digit hexadecimal code. It primarily converts characters except 0-9, A-Z, and a-z, including various ASCII control codes and symbols, and extended characters with codes of 128 and above. The code also supports lowercase escapes and different encoding standards like RFC 3986 and HTML 5. An optional feature allows the use of an exception string to preserve certain symbols. The code avoids using URI.escape due to its obsoleteness and potential encoding failures.


generates a common sorted list with unique elements from multiple integer arrays.


items = [ [:beef   , 3.8, 36],
          [:pork   , 5.4, 43],
          [:ham    , 3.6, 90],
          [:greaves, 2.4, 45],
          [:flitch , 4.0, 30],
          [:brawn  , 2.5, 56],
          [:welt   , 3.7, 67],
          [:salami , 3.0, 95],
          [:sausage, 5.9, 98] ].sort_by{|item, weight, price| -price / weight}
maxW, value = 15.0, 0
items.each do |item, weight, price|
  if (maxW -= weight) > 0
    puts "Take all #{item}"
    value += price
  else
    puts "Take %gkg of %s" % [t=weight+maxW, item], "",
         "Total value of swag is %g" % (value+(price/weight)*t)
    break
  end
end

determine the optimal combination of items a thief can steal from a butcher's shop without exceeding a total weight of 15 kg in his knapsack, with the possibility of cutting items proportionally to their original price, in order to maximize the total value.


require 'open-uri'

anagram = Hash.new {|hash, key| hash[key] = []} # map sorted chars to anagrams

URI.open('http://wiki.puzzlers.org/pub/wordlists/unixdict.txt') do |f|
  words = f.read.split
  for word in words
    anagram[word.split('').sort] << word
  end
end

count = anagram.values.map {|ana| ana.length}.max
anagram.each_value do |ana|
  if ana.length >= count
    p ana
  end
end

"Find the largest sets of anagrams from a given word list, with results ordered lexically."


def sierpinski_carpet(n)
  carpet = ["#"]
  n.times do
    carpet = carpet.collect {|x| x + x + x} +
             carpet.collect {|x| x + x.tr("#"," ") + x} +
             carpet.collect {|x| x + x + x}
  end
  carpet
end

4.times{|i| puts "\nN=#{i}", sierpinski_carpet(i)}

generate a graphical or ASCII-art representation of a Sierpinski carpet of a given order N. The representation uses specific placement of whitespace and non-whitespace characters, with the non-whitespace characters not necessarily needing to be the '#' character. The code also includes a related task of generating a Sierpinski triangle and a graphical version using JRubyArt.


Uses a Library: RubyGems package PriorityQueue
require 'priority_queue'

def huffman_encoding(str)
  char_count = Hash.new(0)
  str.each_char {|c| char_count[c] += 1}

  pq = CPriorityQueue.new
  # chars with fewest count have highest priority
  char_count.each {|char, count| pq.push(char, count)}

  while pq.length > 1
    key1, prio1 = pq.delete_min
    key2, prio2 = pq.delete_min
    pq.push([key1, key2], prio1 + prio2)
  end

  Hash[*generate_encoding(pq.min_key)]
end

def generate_encoding(ary, prefix="")
  case ary
  when Array
    generate_encoding(ary[0], "#{prefix}0") + generate_encoding(ary[1], "#{prefix}1")
  else
    [ary, prefix]
  end
end

def encode(str, encoding)
  str.each_char.collect {|char| encoding[char]}.join
end

def decode(encoded, encoding)
  rev_enc = encoding.invert
  decoded = ""
  pos = 0
  while pos < encoded.length
    key = ""
    while rev_enc[key].nil?
      key << encoded[pos]
      pos += 1
    end
    decoded << rev_enc[key]
  end
  decoded
end

str = "this is an example for huffman encoding"
encoding = huffman_encoding(str)
encoding.to_a.sort.each {|x| p x}

enc = encode(str, encoding)
dec = decode(enc, encoding)
puts "success!" if str == dec

[" ", "111"]
["a", "1011"]
["c", "00001"]
["d", "00000"]
["e", "1101"]
["f", "1100"]
["g", "00100"]
["h", "1000"]
["i", "1001"]
["l", "01110"]
["m", "10101"]
["n", "010"]
["o", "0001"]
["p", "00101"]
["r", "00111"]
["s", "0110"]
["t", "00110"]
["u", "01111"]
["x", "10100"]
success!

The code generates a Huffman encoding for each character in the given string "this is an example for huffman encoding". It first creates a tree of nodes based on the frequency of each character. Then, it traverses the tree from root to leaves, assigning '0' for one branch and '1' for the other at each node. The accumulated zeros and ones at each leaf constitute a Huffman encoding for those characters. The output is a table of Huffman encodings for each character.


Library: Ruby/Tk
require 'tk'
str = TkVariable.new("no clicks yet")
count = 0
root = TkRoot.new
TkLabel.new(root, "textvariable" => str).pack
TkButton.new(root) do
  text "click me"
  command {str.value = count += 1}
  pack
end
Tk.mainloop

Library: Shoes
Shoes.app do
  stack do
    @count = 0
    @label = para "no clicks yet"
    button "click me" do
      @count += 1
      @label.text = "click: #@count"
    end
  end
end

Implement a windowed application with a label and a button. The label initially displays "There have been no clicks yet". The button, labelled "click me", updates the label to show the number of times it has been clicked when interacted with.


require 'pstore'
require 'set'

Address = Struct.new :id, :street, :city, :state, :zip

db = PStore.new("addresses.pstore")
db.transaction do
  db[:next] ||= 0       # Next available Address#id
  db[:ids] ||= Set[]    # Set of all ids in db
end

db.transaction do
  id = (db[:next] += 1)
  db[id] = Address.new(id,
                       "1600 Pennsylvania Avenue NW",
                       "Washington", "DC", 20500)
  db[:ids].add id
end
Library: sqlite3-ruby
require 'sqlite3'

db = SQLite3::Database.new(':memory:')
db.execute("
    CREATE TABLE address (
        addrID     INTEGER PRIMARY KEY AUTOINCREMENT,
        addrStreet TEXT NOT NULL,
        addrCity   TEXT NOT NULL,
        addrState  TEXT NOT NULL,
        addrZIP    TEXT NOT NULL
    )
")

"Create a table in a database to store US postal addresses, including fields for unique identifier, street address, city, state code, and zipcode. The code also demonstrates how to open a database connection in non-database languages and insert an address into the created table using a NoSQL database, PStore."


The code performs a countdown from 10 to 0 using a downward for loop.


module VigenereCipher

  BASE = 'A'.ord
  SIZE = 'Z'.ord - BASE + 1

  def encrypt(text, key)
    crypt(text, key, :+)
  end

  def decrypt(text, key)
    crypt(text, key, :-)
  end

  def crypt(text, key, dir)
    text = text.upcase.gsub(/[^A-Z]/, '')
    key_iterator = key.upcase.gsub(/[^A-Z]/, '').chars.map{|c| c.ord - BASE}.cycle
    text.each_char.inject('') do |ciphertext, char|
      offset = key_iterator.next
      ciphertext << ((char.ord - BASE).send(dir, offset) % SIZE + BASE).chr
    end
  end

end

include VigenereCipher

plaintext = 'Beware the Jabberwock, my son! The jaws that bite, the claws that catch!'
key = 'Vigenere cipher'
ciphertext = VigenereCipher.encrypt(plaintext, key)
recovered  = VigenereCipher.decrypt(ciphertext, key)

puts "Original: #{plaintext}"
puts "Encrypted: #{ciphertext}"
puts "Decrypted: #{recovered}"

Implement and demonstrate a Vigenère cipher for both encryption and decryption. The code handles keys and text of unequal length, capitalizes all characters, and discards non-alphabetic characters. If non-alphabetic characters are handled differently, it is noted.


2.step(8,2) {|n| print "#{n}, "}
puts "who do we appreciate?"

(2..8).step(2) {|n| print "#{n}, "}
puts "who do we appreciate?"

for n in (2..8).step(2)
  print "#{n}, "
end
puts "who do we appreciate?"

for n in 2.step(by: 2, to: 8)
  print "#{n}, "
end
puts "who do we appreciate?"

demonstrate a for-loop with a step-value greater than one.


implement Jensen's Device, a programming technique devised by Jørn Jensen. The technique involves call by name and is illustrated through a program that computes the 100th harmonic number. The program exploits call by name to produce the correct result, relying on the re-evaluation of an expression passed as an actual parameter in the caller's context every time the corresponding formal parameter's value is required. The first parameter to the sum function, representing the "bound" variable of the summation, is also passed by name to ensure changes to it are visible in the caller's context. The global variable does not need to use the same identifier as the formal parameter. The code also includes a comparison to the Man or Boy Test proposed by Donald Knuth.


Sample output from Ruby program
load 'raster_graphics.rb'

class Pixmap
  def self.xor_pattern(width, height, rgb1, rgb2)
    # create colour table
    size = 256
    colours = Array.new(size) do |i|
      RGBColour.new(
        (rgb1.red + (rgb2.red - rgb1.red) * i / size),
        (rgb1.green + (rgb2.green - rgb1.green) * i / size),
        (rgb1.blue + (rgb2.blue - rgb1.blue) * i / size),
      )
    end

    # create the image
    pixmap = new(width, height)
    pixmap.each_pixel do |x, y|
      pixmap[x,y] = colours[(x^y)%size]
    end
    pixmap
  end
end

img = Pixmap.xor_pattern(384, 384, RGBColour::RED, RGBColour::YELLOW)
img.save_as_png('xorpattern.png')

"Generates a graphical pattern using Ruby and raster graphics operations, where each pixel's color is determined by the 'x xor y' value from a given color table."


class Maze
  DIRECTIONS = [ [1, 0], [-1, 0], [0, 1], [0, -1] ]

  def initialize(width, height)
    @width   = width
    @height  = height
    @start_x = rand(width)
    @start_y = 0
    @end_x   = rand(width)
    @end_y   = height - 1

    # Which walls do exist? Default to "true". Both arrays are
    # one element bigger than they need to be. For example, the
    # @vertical_walls[x][y] is true if there is a wall between
    # (x,y) and (x+1,y). The additional entry makes printing easier.
    @vertical_walls   = Array.new(width) { Array.new(height, true) }
    @horizontal_walls = Array.new(width) { Array.new(height, true) }
    # Path for the solved maze.
    @path             = Array.new(width) { Array.new(height) }

    # "Hack" to print the exit.
    @horizontal_walls[@end_x][@end_y] = false

    # Generate the maze.
    generate
  end

  # Print a nice ASCII maze.
  def print
    # Special handling: print the top line.
    puts @width.times.inject("+") {|str, x| str << (x == @start_x ? "   +" : "---+")}

    # For each cell, print the right and bottom wall, if it exists.
    @height.times do |y|
      line = @width.times.inject("|") do |str, x|
        str << (@path[x][y] ? " * " : "   ") << (@vertical_walls[x][y] ? "|" : " ")
      end
      puts line

      puts @width.times.inject("+") {|str, x| str << (@horizontal_walls[x][y] ? "---+" : "   +")}
    end
  end

  private

  # Reset the VISITED state of all cells.
  def reset_visiting_state
    @visited = Array.new(@width) { Array.new(@height) }
  end

  # Is the given coordinate valid and the cell not yet visited?
  def move_valid?(x, y)
    (0...@width).cover?(x) && (0...@height).cover?(y) && !@visited[x][y]
  end

  # Generate the maze.
  def generate
    reset_visiting_state
    generate_visit_cell(@start_x, @start_y)
  end

  # Depth-first maze generation.
  def generate_visit_cell(x, y)
    # Mark cell as visited.
    @visited[x][y] = true

    # Randomly get coordinates of surrounding cells (may be outside
    # of the maze range, will be sorted out later).
    coordinates = DIRECTIONS.shuffle.map { |dx, dy| [x + dx, y + dy] }

    for new_x, new_y in coordinates
      next unless move_valid?(new_x, new_y)

      # Recurse if it was possible to connect the current and
      # the cell (this recursion is the "depth-first" part).
      connect_cells(x, y, new_x, new_y)
      generate_visit_cell(new_x, new_y)
    end
  end

  # Try to connect two cells. Returns whether it was valid to do so.
  def connect_cells(x1, y1, x2, y2)
    if x1 == x2
      # Cells must be above each other, remove a horizontal wall.
      @horizontal_walls[x1][ [y1, y2].min ] = false
    else
      # Cells must be next to each other, remove a vertical wall.
      @vertical_walls[ [x1, x2].min ][y1] = false
    end
  end
end

# Demonstration:
maze = Maze.new 20, 10
maze.print

generate and display a maze using the Depth-first search algorithm. It starts from a random cell, marks it as visited, and gets a list of its neighbors. For each unvisited neighbor, it removes the wall between the current cell and the neighbor, and then recursively continues the process with the neighbor as the current cell.


pi_digits = Enumerator.new do |y|
  q, r, t, k, n, l = 1, 0, 1, 1, 3, 3
  loop do
    if 4*q+r-t < n*t
      y << n
      nr = 10*(r-n*t)
      n = ((10*(3*q+r)) / t) - 10*n
      q *= 10
      r = nr
    else
      nr = (2*q+r) * l
      nn = (q*(7*k+2)+r*l) / (t*l)
      q *= k
      t *= l
      l += 2
      k += 1
      n = nn
      r = nr
    end
  end
end

print pi_digits.next, "."
loop { print pi_digits.next }

are designed to continuously calculate and output the next decimal digit of Pi, starting from 3.14159265, until the user aborts the operation. The calculation of Pi is not based on any built-in constants or functions.


"Function to compare two numerical lists lexicographically and return true if the first list should be ordered before the second, false otherwise."


def ack(m, n)
  if m == 0
    n + 1
  elsif n == 0
    ack(m-1, 1)
  else
    ack(m-1, ack(m, n-1))
  end
end

(0..3).each do |m|
  puts (0..6).map { |n| ack(m, n) }.join(' ')
end

implement the Ackermann function, a non-primitive recursive function that takes two non-negative arguments and returns a rapidly growing value. The function should ideally support arbitrary precision due to the rapid growth of the function's output.


implement the Gamma function using either the Lanczos or Stirling's approximation. The codes also compare the results of the custom implementation with the built-in/library function if available. The Gamma function is computed through numerical integration.


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

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

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

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

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

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

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

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

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

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

"Code implements a solution to the N-queens problem, including the eight queens puzzle. It uses heuristics from Wikipedia to return one solution or all solutions if not specified. It also provides the number of solutions for small values of N."


demonstrate how to concatenate two arrays using either the Array#+ method, the Array#concat method, or the flatten(1) method in the given programming language.


KnapsackItem = Struct.new(:name, :weight, :value)
potential_items = [
  KnapsackItem['map', 9, 150],              KnapsackItem['compass', 13, 35],
  KnapsackItem['water', 153, 200],          KnapsackItem['sandwich', 50, 160],
  KnapsackItem['glucose', 15, 60],          KnapsackItem['tin', 68, 45],
  KnapsackItem['banana', 27, 60],           KnapsackItem['apple', 39, 40],
  KnapsackItem['cheese', 23, 30],           KnapsackItem['beer', 52, 10],
  KnapsackItem['suntan cream', 11, 70],     KnapsackItem['camera', 32, 30],
  KnapsackItem['t-shirt', 24, 15],          KnapsackItem['trousers', 48, 10],
  KnapsackItem['umbrella', 73, 40],         KnapsackItem['waterproof trousers', 42, 70],
  KnapsackItem['waterproof overclothes', 43, 75], KnapsackItem['note-case', 22, 80],
  KnapsackItem['sunglasses', 7, 20],        KnapsackItem['towel', 18, 12],
  KnapsackItem['socks', 4, 50],             KnapsackItem['book', 30, 10],
]
knapsack_capacity = 400

class Array
  # do something for each element of the array's power set
  def power_set
    yield [] if block_given?
    self.inject([[]]) do |ps, elem|
      ps.each_with_object([]) do |i,r|
        r << i
        new_subset = i + [elem]
        yield new_subset if block_given?
        r << new_subset
      end
    end
  end
end

maxval, solutions = potential_items.power_set.group_by {|subset|
  weight = subset.inject(0) {|w, elem| w + elem.weight}
  weight>knapsack_capacity ? 0 : subset.inject(0){|v, elem| v + elem.value}
}.max

puts "value: #{maxval}"
solutions.each do |set|
  wt, items = 0, []
  set.each {|elem| wt += elem.weight; items << elem.name}
  puts "weight: #{wt}"
  puts "items: #{items.join(',')}"
end

The code determines the optimal combination of items a tourist can carry in his knapsack, given a maximum weight limit of 4kg, to maximize the total value of the items. The items cannot be divided and only one of each item is available. The items, their weights, and their values are provided in a list.


class Person
  def initialize(name)
    @name = name
    @fiance = nil
    @preferences = []
    @proposals = []
  end
  attr_reader :name, :proposals
  attr_accessor :fiance, :preferences

  def to_s
    @name
  end

  def free
    @fiance = nil
  end

  def single?
    @fiance == nil
  end

  def engage(person)
    self.fiance = person
    person.fiance = self
  end

  def better_choice?(person)
    @preferences.index(person) < @preferences.index(@fiance)
  end

  def propose_to(person)
    puts "#{self} proposes to #{person}" if $DEBUG
    @proposals << person
    person.respond_to_proposal_from(self)
  end

  def respond_to_proposal_from(person)
    if single?
      puts "#{self} accepts proposal from #{person}" if $DEBUG
      engage(person)
    elsif better_choice?(person)
      puts "#{self} dumps #{@fiance} for #{person}" if $DEBUG
      @fiance.free
      engage(person)
    else
      puts "#{self} rejects proposal from #{person}" if $DEBUG
    end
  end
end

########################################################################
# initialize data

prefs = {
  'abe'  => %w[abi eve cath ivy jan dee fay bea hope gay],
  'bob'  => %w[cath hope abi dee eve fay bea jan ivy gay],
  'col'  => %w[hope eve abi dee bea fay ivy gay cath jan],
  'dan'  => %w[ivy fay dee gay hope eve jan bea cath abi],
  'ed'   => %w[jan dee bea cath fay eve abi ivy hope gay],
  'fred' => %w[bea abi dee gay eve ivy cath jan hope fay],
  'gav'  => %w[gay eve ivy bea cath abi dee hope jan fay],
  'hal'  => %w[abi eve hope fay ivy cath jan bea gay dee],
  'ian'  => %w[hope cath dee gay bea abi fay ivy jan eve],
  'jon'  => %w[abi fay jan gay eve bea dee cath ivy hope],
  'abi'  => %w[bob fred jon gav ian abe dan ed col hal],
  'bea'  => %w[bob abe col fred gav dan ian ed jon hal],
  'cath' => %w[fred bob ed gav hal col ian abe dan jon],
  'dee'  => %w[fred jon col abe ian hal gav dan bob ed],
  'eve'  => %w[jon hal fred dan abe gav col ed ian bob],
  'fay'  => %w[bob abe ed ian jon dan fred gav col hal],
  'gay'  => %w[jon gav hal fred bob abe col ed dan ian],
  'hope' => %w[gav jon bob abe ian dan hal ed col fred],
  'ivy'  => %w[ian col hal gav fred bob abe ed jon dan],
  'jan'  => %w[ed hal gav abe bob jon col ian fred dan],
}

@men = Hash[
  %w[abe bob col dan ed fred gav hal ian jon].collect do |name|
    [name, Person.new(name)]
  end
]

@women = Hash[
  %w[abi bea cath dee eve fay gay hope ivy jan].collect do |name|
    [name, Person.new(name)]
  end
]

@men.each {|name, man| man.preferences = @women.values_at(*prefs[name])}
@women.each {|name, woman| woman.preferences = @men.values_at(*prefs[name])}

########################################################################
# perform the matching

def match_couples(men, women)
  men.each_value {|man| man.free}
  women.each_value {|woman| woman.free}

  while m = men.values.find {|man| man.single?} do
    puts "considering single man #{m}" if $DEBUG
    w = m.preferences.find {|woman| not m.proposals.include?(woman)}
    m.propose_to(w)
  end
end

match_couples @men, @women

@men.each_value.collect {|man| puts "#{man} + #{man.fiance}"}

########################################################################
# check for stability

class Person
  def more_preferable_people
    ( @preferences.partition {|p| better_choice?(p)} ).first
  end
end

require 'set'

def stability(men)
  unstable = Set.new
  men.each_value do |man|
    woman = man.fiance
    puts "considering #{man} and #{woman}" if $DEBUG

    man.more_preferable_people.each do |other_woman|
      if other_woman.more_preferable_people.include?(man)
        puts "an unstable pairing: #{man} and #{other_woman}" if $DEBUG
        unstable << [man, other_woman]
      end
    end
    woman.more_preferable_people.each do |other_man|
      if other_man.more_preferable_people.include?(woman)
        puts "an unstable pairing: #{woman} and #{other_man}" if $DEBUG
        unstable << [other_man, woman]
      end
    end
  end

  if unstable.empty?
    puts "these couples are stable"
  else
    puts "uh oh"
    unstable.each do |a,b|
      puts "#{a} is engaged to #{a.fiance} but would prefer #{b}, and #{b} is engaged to #{b.fiance} but would prefer #{a}"
    end
  end
end

stability @men

########################################################################
# perturb

puts "\nwhat if abe and bob swap..."

def swap(m1, m2)
  w1 = m1.fiance
  w2 = m2.fiance
  m1.fiance = w2
  w1.fiance = m2
  m2.fiance = w1
  w2.fiance = m1
end

swap *@men.values_at('abe','bob')

@men.each_value.collect {|man| puts "#{man} + #{man.fiance}"}
stability @men

The code implements the Gale-Shapley algorithm to solve the Stable Marriage problem. It takes as input the preferences of ten men and ten women for each other, and generates a stable set of engagements. The code then perturbs this set to create an unstable set of engagements, and checks the stability of this new set.


def a( bool )
  puts "a( #{bool} ) called"
  bool
end

def b( bool )
  puts "b( #{bool} ) called"
  bool
end

 [true, false].each do |a_val|
   [true, false].each do |b_val|
     puts "a( #{a_val} ) and b( #{b_val} ) is #{a( a_val ) and b( b_val )}."
     puts
     puts "a( #{a_val} ) or b( #{b_val} ) is #{a( a_val)  or b( b_val )}."
     puts
   end
 end

The code defines two functions, a and b, which take a boolean value as input, return the same value, and print their names when called. The code then calculates the values of two equations, x = a(i) and b(j) and y = a(i) or b(j), using short-circuit evaluation to ensure that function b is only called when necessary. If the programming language does not support short-circuit evaluation, this is achieved using nested if statements.


<output> convert a given string into audible Morse code and send it to an audio device such as a PC speaker. It either ignores unknown characters or indicates them with a different pitch. </output>


words = %w(A BaRK BOoK tREaT COmMOn SqUAD CoNfuSE) << ""

words.each do |word|
  blocks = "BO XK DQ CP NA GT RE TG QD FS JW HU VI AN OB ER FS LY PC ZM"
  res = word.each_char.all?{|c| blocks.sub!(/\w?#{c}\w?/i, "")}  #regexps can be interpolated like strings
  puts "#{word.inspect}: #{res}"
end

The code defines a function that checks if a given word can be spelled using a specific collection of ABC blocks. Each block contains two letters and can only be used once. The function is case-insensitive. It tests the function with seven example words and displays the results.


require 'digest'
Digest::MD5.hexdigest("The quick brown fox jumped over the lazy dog's back")
# => "e38ca1d920c4b8b8d3946b2c72f01680"

implement an MD5 encoding for a given string. The codes also include an optional validation using test values from IETF RFC (1321) for MD5. However, due to known weaknesses of MD5, alternatives like SHA-256 or SHA-3 are recommended for production-grade cryptography. If the solution is a library, refer to MD5/Implementation for a scratch implementation.


sort a list of Object Identifiers (OIDs). The OIDs are strings used to identify objects in network data and are composed of one or more non-negative integers in base 10, separated by dots. The sorting is done lexicographically with regard to the dot-separated fields, using numeric comparison between fields.


require 'socket'
sock = TCPSocket.open("localhost", 256)
sock.write("hello socket world")
sock.close

opens a socket to localhost on port 256, sends the message "hello socket world", and then closes the socket.


Uses the Library: RubyGems gems TMail which allows us to manipulate email objects conveniently, and mime-types which guesses a file's mime type based on its filename.
require 'base64'
require 'net/smtp'
require 'tmail'
require 'mime/types'

class Email
  def initialize(from, to, subject, body, options={})
    @opts = {:attachments => [], :server => 'localhost'}.update(options)
    @msg = TMail::Mail.new
    @msg.from    = from
    @msg.to      = to
    @msg.subject = subject
    @msg.cc      = @opts[:cc]  if @opts[:cc]
    @msg.bcc     = @opts[:bcc] if @opts[:bcc]

    if @opts[:attachments].empty?
      # just specify the body
      @msg.body = body
    else
      # attach attachments, including the body
      @msg.body = "This is a multi-part message in MIME format.\n"

      msg_body = TMail::Mail.new
      msg_body.body = body
      msg_body.set_content_type("text","plain", {:charset => "ISO-8859-1"})
      @msg.parts << msg_body

      octet_stream = MIME::Types['application/octet-stream'].first

      @opts[:attachments].select {|file| File.readable?(file)}.each do |file|
        mime_type = MIME::Types.type_for(file).first || octet_stream
        @msg.parts << create_attachment(file, mime_type)
      end
    end
  end
  attr_reader :msg

  def create_attachment(file, mime_type)
    attach = TMail::Mail.new
    if mime_type.binary?
      attach.body = Base64.encode64(File.read(file))
      attach.transfer_encoding = 'base64'
    else
      attach.body = File.read(file)
    end
    attach.set_disposition("attachment", {:filename => file})
    attach.set_content_type(mime_type.media_type, mime_type.sub_type, {:name=>file})
    attach
  end

  # instance method to send an Email object
  def send
    args = @opts.values_at(:server, :port, :helo, :username, :password, :authtype)
    Net::SMTP.start(*args) do |smtp|
      smtp.send_message(@msg.to_s, @msg.from[0], @msg.to)
    end
  end

  # class method to construct an Email object and send it
  def self.send(*args)
    self.new(*args).send
  end
end

Email.send(
  'sender@sender.invalid',
  %w{ recip1@recipient.invalid recip2@example.com },
  'the subject',
  "the body\nhas lines",
  {
    :attachments => %w{ file1 file2 file3 },
    :server => 'mail.example.com',
    :helo => 'sender.invalid',
    :username => 'user',
    :password => 'secret'
  }
)

Implement a function to send an email with parameters for From, To, Cc addresses, Subject, message text, and optional server name and login details. The code also provides notifications for any issues or success, and uses libraries or external programs for execution. It ensures portability across different operating systems. Sensitive data used in examples is obfuscated.


n = 0
loop do
  puts "%o" % n
  n += 1
end

# or
for n in (0..)
  puts n.to_s(8)
end

# or
0.upto(1/0.0) do |n|
  printf "%o\n", n
end

# version 2.1 later
0.step do |n|
  puts format("%o", n)
end

generate a sequential count in octal, starting from zero and incrementing by one on each line until the program is terminated or the maximum numeric type value is reached.


a, b = b, a

def swap(a, b)
    return b, a
end

x = 42
y = "string"
x, y = swap x, y
puts x  # prints string
puts y  # prints 42

implements a generic swap function or operator that exchanges the values of two variables or storage places, regardless of their types. The function is designed to work with statically typed languages and dynamically typed languages. It ensures that the two variables have a mutually compatible type to avoid type violation. However, the function does not destructively swap two variables. Instead, it returns a new array with the swapped values. The original variables can be assigned with the return value.


def palindrome?(s)
  s == s.reverse
end

def r_palindrome?(s)
  if s.length <= 1
    true
  elsif s[0] != s[-1]
    false
  else
    r_palindrome?(s[1..-2])
  end
end

str = "A man, a plan, a caret, [...2110 chars deleted...] a canal--Panama.".downcase.delete('^a-z')
puts palindrome?(str)    # => true
puts r_palindrome?(str)  # => true

require 'benchmark'
Benchmark.bm do |b|
  b.report('iterative') {10000.times {palindrome?(str)}}
  b.report('recursive') {10000.times {r_palindrome?(str)}}
end

The code is a function that checks if a given sequence of characters is a palindrome. It supports Unicode characters and has an additional function to detect inexact palindromes, ignoring white-space, punctuation, and case. The code uses both non-recursive and recursive methods, with the recursive method being slower.


demonstrate how to retrieve a specific environment variable from a process using the ENV hash, which maps variable names to their values. Common Unix environment variables include PATH, HOME, and USER.


def sudan(n, x, y)
  return x + y if n == 0
  return x if y == 0

  sudan(n - 1, sudan(n, x, y - 1), sudan(n, x, y - 1) + y)
end

puts sudan(1, 3, 3)
> 35

Implement the Sudan function, a non-primitive recursive function. The function takes two parameters x and y, and returns the value of F(x, y) based on the defined rules of the Sudan function.


stack = {}
table.insert(stack,3)
print(table.remove(stack)) --> 3

implement a stack data structure that supports basic operations such as push (adding an element to the top of the stack), pop (removing the topmost element from the stack and returning it), and empty (checking if the stack is empty).


--calculates the nth fibonacci number. Breaks for negative or non-integer n.
function fibs(n)
  return n < 2 and n or fibs(n - 1) + fibs(n - 2)
end
Pedantic --more pedantic version, returns 0 for non-integer n
function pfibs(n)
  if n ~= math.floor(n) then return 0
  elseif n < 0 then return pfibs(n + 2) - pfibs(n + 1)
  elseif n < 2 then return n
  else return pfibs(n - 1) + pfibs(n - 2)
  end
end
Tail function a(n,u,s) if n<2 then return u+s end return a(n-1,u+s,u) end
function trfib(i) return a(i-1,1,0) end
Table fib_n = setmetatable({1, 1}, {__index = function(z,n) return n<=0 and 0 or z[n-1] + z[n-2] end})
-- table recursive done properly (values are actually saved into table;
-- also the first element of Fibonacci sequence is 0, so the initial table should be {0, 1}).
fib_n = setmetatable({0, 1}, {
  __index = function(t,n)
    if n <= 0 then return 0 end
    t[n] = t[n-1] + t[n-2]
    return t[n]
  end
})
function ifibs(n)
  local p0,p1=0,1
  for _=1,n do p0,p1 = p1,p0+p1 end
  return p0
end

generate the nth Fibonacci number, using either an iterative or recursive approach. The function also has an optional feature to support negative Fibonacci sequences.


function filter(t, func)
  local ret = {}
  for i, v in ipairs(t) do
    ret[#ret+1] = func(v) and v or nil
  end
  return ret
end

function even(a) return a % 2 == 0 end

print(unpack(filter({1, 2, 3, 4 ,5, 6, 7, 8, 9, 10}, even)))

function filter(t, func)
  for i, v in ipairs(t) do
    if not func(v) then table.remove(t, i) end
  end
end

function even(a) return a % 2 == 0 end

local values = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
filter(values, even)
print(unpack(values))

select certain elements from an array into a new array in a generic way, specifically all even numbers. Optionally, it also provides a destructive version that modifies the original array instead of creating a new one.


str = "abcdefghijklmnopqrstuvwxyz"
n, m = 5, 15

print( string.sub( str, n, m ) )    -- efghijklmno
print( string.sub( str, n, -1 ) )   -- efghijklmnopqrstuvwxyz
print( string.sub( str, 1, -2 ) )   -- abcdefghijklmnopqrstuvwxy

pos = string.find( str, "i" )
if pos ~= nil then print( string.sub( str, pos, pos+m ) ) end -- ijklmnopqrstuvwx

pos = string.find( str, "ijk" )
if pos ~= nil then print( string.sub( str, pos, pos+m ) ) end-- ijklmnopqrstuvwx

-- Alternative (more modern) notation

print ( str:sub(n,m) )         -- efghijklmno
print ( str:sub(n) )           -- efghijklmnopqrstuvwxyz
print ( str:sub(1,-2) )        -- abcdefghijklmnopqrstuvwxy

pos = str:find "i"
if pos then print (str:sub(pos,pos+m)) end -- ijklmnopqrstuvwx

pos = str:find "ijk"
if pos then print (str:sub(pos,pos+m)) end d-- ijklmnopqrstuvwx

- Extracts a substring starting from the nth character of a specific length m.
- Extracts a substring starting from the nth character up to the end of the string.
- Returns the entire string excluding the last character.
- Extracts a substring starting from a known character within the string of length m.
- Extracts a substring starting from a known substring within the string of length m.
- Supports any valid Unicode code point, including those in the Basic Multilingual Plane or above it.
- References logical characters (code points), not 8-bit code units for UTF-8 or 16-bit code units for UTF-16.
- Does not necessarily support all Unicode characters for other encodings like 8-bit ASCII, or EUC-JP.


example = 'asdf'
string.reverse(example) -- fdsa
example:reverse() -- fdsa

"Reverses a given string while preserving the order of Unicode combining characters. Note: Lua's built-in string.reverse() function is not used due to lack of Unicode support."


-- Graph definition
local edges = {
    a = {b = 7, c = 9, f = 14},
    b = {c = 10, d = 15},
    c = {d = 11, f = 2},
    d = {e = 6},
    e = {f = 9}
}

-- Fill in paths in the opposite direction to the stated edges
function complete (graph)
    for node, edges in pairs(graph) do
        for edge, distance in pairs(edges) do
            if not graph[edge] then graph[edge] = {} end
            graph[edge][node] = distance
        end
    end
end

-- Create path string from table of previous nodes
function follow (trail, destination)
    local path, nextStep = destination, trail[destination]
    while nextStep do
        path = nextStep .. " " .. path
        nextStep = trail[nextStep]
    end
    return path
end

-- Find the shortest path between the current and destination nodes
function dijkstra (graph, current, destination, directed)
    if not directed then complete(graph) end
    local unvisited, distanceTo, trail = {}, {}, {}
    local nearest, nextNode, tentative
    for node, edgeDists in pairs(graph) do
        if node == current then
            distanceTo[node] = 0
            trail[current] = false
        else
            distanceTo[node] = math.huge
            unvisited[node] = true
        end
    end
    repeat
        nearest = math.huge
        for neighbour, pathDist in pairs(graph[current]) do
            if unvisited[neighbour] then
                tentative = distanceTo[current] + pathDist
                if tentative < distanceTo[neighbour] then
                    distanceTo[neighbour] = tentative
                    trail[neighbour] = current
                end
                if tentative < nearest then
                    nearest = tentative
                    nextNode = neighbour
                end
            end
        end
        unvisited[current] = false
        current = nextNode
    until unvisited[destination] == false or nearest == math.huge
    return distanceTo[destination], follow(trail, destination)
end

-- Main procedure
print("Directed:", dijkstra(edges, "a", "e", true))
print("Undirected:", dijkstra(edges, "a", "e", false))

Implement Dijkstra's algorithm to find the shortest path from a given source node to all other nodes in a directed, weighted graph. The graph is represented by an adjacency matrix or list, and a start node. The algorithm outputs a set of edges representing the shortest path to each reachable node from the source. The code also includes functionality to interpret the output and display the shortest path from the source node to specific nodes.


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

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

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

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

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

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

-- output functions

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

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

-- test

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

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

implement an AVL tree, a self-balancing binary search tree where the heights of the two child subtrees of any node differ by at most one. The code ensures this by rebalancing the tree after each insertion or deletion. The operations of lookup, insertion, and deletion all take O(log n) time. The code does not allow duplicate node keys. The AVL tree implemented can be compared with red-black trees for its efficiency in lookup-intensive applications.


function distance(p1, p2)
    local dx = (p1.x-p2.x)
    local dy = (p1.y-p2.y)
    return math.sqrt(dx*dx + dy*dy)
end

function findCircles(p1, p2, radius)
    local seperation = distance(p1, p2)
    if seperation == 0.0 then
        if radius == 0.0 then
            print("No circles can be drawn through ("..p1.x..", "..p1.y..")")
        else
            print("Infinitely many circles can be drawn through ("..p1.x..", "..p1.y..")")
        end
    elseif seperation == 2*radius then
        local cx = (p1.x+p2.x)/2
        local cy = (p1.y+p2.y)/2
        print("Given points are opposite ends of a diameter of the circle with center ("..cx..", "..cy..") and radius "..radius)
    elseif seperation > 2*radius then
        print("Given points are further away from each other than a diameter of a circle with radius "..radius)
    else
        local mirrorDistance = math.sqrt(math.pow(radius,2) - math.pow(seperation/2,2))
        local dx = p2.x - p1.x
        local dy = p1.y - p2.y
        local ax = (p1.x + p2.x) / 2
        local ay = (p1.y + p2.y) / 2
        local mx = mirrorDistance * dx / seperation
        local my = mirrorDistance * dy / seperation
        c1 = {x=ax+my, y=ay+mx}
        c2 = {x=ax-my, y=ay-mx}

        print("Two circles are possible.")
        print("Circle C1 with center ("..c1.x..", "..c1.y.."), radius "..radius)
        print("Circle C2 with center ("..c2.x..", "..c2.y.."), radius "..radius)
    end
    print()
end

cases = {
    {x=0.1234, y=0.9876},   {x=0.8765, y=0.2345},
    {x=0.0000, y=2.0000},   {x=0.0000, y=0.0000},
    {x=0.1234, y=0.9876},   {x=0.1234, y=0.9876},
    {x=0.1234, y=0.9876},   {x=0.8765, y=0.2345},
    {x=0.1234, y=0.9876},   {x=0.1234, y=0.9876}
}
radii = { 2.0, 1.0, 2.0, 0.5, 0.0 }
for i=1, #radii do
    print("Case "..i)
    findCircles(cases[i*2-1], cases[i*2], radii[i])
end

"Function to calculate two possible circles given two points and a radius in 2D space. The function handles special cases such as when radius is zero, points are coincident, points form a diameter, or points are too distant. The function returns the circles or a special indication when two equal or distinct circles cannot be returned."


repeat
  k = math.random(19)
  print(k)
  if k == 10 then break end
  print(math.random(19)
until false

generate and print random numbers from 0 to 19. If the generated number is 10, the loop stops. If the number is not 10, a second random number is generated and printed before the loop restarts. If 10 is never generated, the loop runs indefinitely.


require 'lxp'
data = [[<inventory title="OmniCorp Store #45x10^3">

    <item upc="123456789" stock="12">
      <name>Invisibility Cream</name>
      <price>14.50</price>
      <description>Makes you invisible</description>
    </item>
    <item upc="445322344" stock="18">
      <name>Levitation Salve</name>
      <price>23.99</price>
      <description>Levitate yourself for up to 3 hours per application</description>
    </item>

    <item upc="485672034" stock="653">
      <name>Blork and Freen Instameal</name>
      <price>4.95</price>
      <description>A tasty meal in a tablet; just add water</description>
    </item>
    <item upc="132957764" stock="44">
      <name>Grob winglets</name>
      <price>3.56</price>
      <description>Tender winglets of Grob. Just add water</description>
    </item>

</inventory>]]
local first = true
local names, prices = {}, {}
p = lxp.new({StartElement = function (parser, name)
	local a, b, c = parser:pos() --line, offset, pos
	if name == 'item' and first then
		print(data:match('.-</item>', c - b + 1))
		first = false
	end
	if name == 'name' then names[#names+1] = data:match('>(.-)<', c) end
	if name == 'price' then prices[#prices+1] = data:match('>(.-)<', c) end
end})

p:parse(data)
p:close()

print('Name: ', table.concat(names, ', '))
print('Price: ', table.concat(prices, ', '))

The code retrieves the first "item" element, prints out each "price" element, and gathers an array of all the "name" elements from a given XML document using XPath queries. The XML document represents an inventory of a store. LuaExpat is required for XML parsing.


Works with: lua version 5.1
function emptySet()         return { }  end
function insert(set, item)  set[item] = true  end
function remove(set, item)  set[item] = nil  end
function member(set, item)  return set[item]  end
function size(set)
	local result = 0
	for _ in pairs(set) do result = result + 1 end
	return result
end
function fromTable(tbl) -- ignore the keys of tbl
	local result = { }
	for _, val in pairs(tbl) do
		result[val] = true
	end
	return result
end
function toArray(set)
	local result = { }
	for key in pairs(set) do
		table.insert(result, key)
	end
	return result
end
function printSet(set)
	print(table.concat(toArray(set), ", "))
end
function union(setA, setB)
	local result = { }
	for key, _ in pairs(setA) do
		result[key] = true
	end
	for key, _ in pairs(setB) do
		result[key] = true
	end
	return result
end
function intersection(setA, setB)
	local result = { }
	for key, _ in pairs(setA) do
		if setB[key] then
			result[key] = true
		end
	end
	return result
end
function difference(setA, setB)
	local result = { }
	for key, _ in pairs(setA) do
		if not setB[key] then
			result[key] = true
		end
	end
	return result
end
function subset(setA, setB)
	for key, _ in pairs(setA) do
		if not setB[key] then
			return false
		end
	end
	return true
end
function properSubset(setA, setB)
	return subset(setA, setB) and (size(setA) ~= size(setB))
end
function equals(setA, setB)
	return subset(setA, setB) and (size(setA) == size(setB))
end

Works with: lua version 5.3

local function new(_, ...)
  local r = {}
  local s = setmetatable({}, {
    -- API operations
    __index = {

      -- single value insertion
      insert = function(s, v)
        if not r[v] then
          table.insert(s, v)
          r[v] = #s
        end
        return s
      end,

      -- single value removal
      remove = function(s, v)
        local i = r[v]
        if i then
          r[v] = nil
          local t = table.remove(s)
          if t ~= v then
            r[t] = i
            s[i] = t
          end
        end
        return s
      end,

      -- multi-value insertion
      batch_insert = function(s, ...)
        for _,v in pairs {...} do
          s:insert(v)
        end
        return s
      end,

      -- multi-value removal
      batch_remove = function(s, ...)
        for _,v in pairs {...} do
          s:remove(v)
        end
        return s
      end,

      -- membership test
      has = function(s, e)
        return r[e] ~= nil
      end
    },

    -- set manipulation operators

    -- union
    __add = function(s1, s2)
      r = set()
      r:batch_insert(table.unpack(s1))
      r:batch_insert(table.unpack(s2))
      return r
    end,

    -- subtraction
    __sub = function(s1, s2)
      r = set()
      r:batch_insert(table.unpack(s1))
      r:batch_remove(table.unpack(s2))
      return r
    end,

    -- intersection
    __mul = function(s1, s2)
      r = set()
      for _,v in ipairs(s1) do
        if s2:has(v) then
          r:insert(v)
        end
      end
      return r
    end,

    -- equality
    __eq = function(s1, s2)
      if #s1 ~= #s2 then return false end
      for _,v in ipairs(s1) do
        if not s2:has(v) then return false end
      end
      return true
    end,

    -- proper subset
    __lt = function(s1, s2)
      if s1 == s2 then return false end
      for _,v in ipairs(s1) do
        if not s2:has(v) then return false end
      end
      return true
    end,

    -- subset
    __lte = function(s1, s2)
      return (s1 == s2) or (s1 < s2)
    end,

    -- metatable type tag
    __type__ = 'set'
  })
  s:batch_insert(...)
  return s
end

return setmetatable({}, { __call = new })

implement a mutable set type with various operations. These operations include set creation, testing if an element is in a set, union, intersection, and difference of two sets, checking if a set is a subset or equal to another set. Additional operations may include modifications to the mutable set and other set operations. The set can be implemented using an associative array, a binary search tree, a hash table, or an ordered array of binary bits. The code is designed to be used as a module.


require("date")

for year=2008,2121 do
   if date(year, 12, 25):getweekday() == 1 then
      print(year)
   end
end

The code calculates the years between 2008 and 2121 when Christmas (25th December) falls on a Sunday using LuaDate library. It also compares the results with other programming languages to identify any discrepancies in date handling, potentially caused by issues like overflow in date/time representation.


items = {1,2,3,4,1,2,3,4,"bird","cat","dog","dog","bird"}
flags = {}
io.write('Unique items are:')
for i=1,#items do
   if not flags[items[i]] then
      io.write(' ' .. items[i])
      flags[items[i]] = true
   end
end
io.write('\n')

removes duplicate elements from an array using three possible methods: 1) Using a hash table, 2) Sorting the elements and removing consecutive duplicates, 3) Iterating through the list and discarding any repeated elements. It also handles exceptions for Lua 5.3 where Not-a-Number (NaN) and nil are not accepted as table keys.


NOTE: If you want to use quicksort in a Lua script, you don't need to implement it yourself. Just do: table.sort(tableName)
--in-place quicksort
function quicksort(t, start, endi)
  start, endi = start or 1, endi or #t
  --partition w.r.t. first element
  if(endi - start < 1) then return t end
  local pivot = start
  for i = start + 1, endi do
    if t[i] <= t[pivot] then
      if i == pivot + 1 then
        t[pivot],t[pivot+1] = t[pivot+1],t[pivot]
      else
        t[pivot],t[pivot+1],t[i] = t[i],t[pivot],t[pivot+1]
      end
      pivot = pivot + 1
    end
  end
  t = quicksort(t, start, pivot - 1)
  return quicksort(t, pivot + 1, endi)
end

--example
print(unpack(quicksort{5, 2, 7, 3, 4, 7, 1}))

non function quicksort(t)
  if #t<2 then return t end
  local pivot=t[1]
  local a,b,c={},{},{}
  for _,v in ipairs(t) do
    if     v<pivot then a[#a+1]=v
    elseif v>pivot then c[#c+1]=v
    else                b[#b+1]=v
    end
  end
  a=quicksort(a)
  c=quicksort(c)
  for _,v in ipairs(b) do a[#a+1]=v end
  for _,v in ipairs(c) do a[#a+1]=v end
  return a
end

implement the Quicksort algorithm to sort an array or list of elements. The algorithm works by choosing a pivot element and dividing the rest of the elements into two partitions - one with elements less than the pivot and the other with elements greater than the pivot. It then recursively sorts these partitions and joins them with the pivot to get the sorted array. The codes also include an optimized version of Quicksort that works in place by swapping elements within the array to avoid memory allocation of more arrays. The pivot selection method is not specified.


print( os.date( "%Y-%m-%d" ) )
print( os.date( "%A, %B %d, %Y" ) )

display the current date in two formats: "2007-11-23" and "Friday, November 23, 2007".


--returns the powerset of s, out of order.
function powerset(s, start)
  start = start or 1
  if(start > #s) then return {{}} end
  local ret = powerset(s, start + 1)
  for i = 1, #ret do
    ret[#ret + 1] = {s[start], unpack(ret[i])}
  end
  return ret
end

--non-recurse implementation
function powerset(s)
   local t = {{}}
   for i = 1, #s do
      for j = 1, #t do
         t[#t+1] = {s[i],unpack(t[j])}
      end
   end
   return t
end

--alternative, copied from the Python implementation
function powerset2(s)
  local ret = {{}}
  for i = 1, #s do
    local k = #ret
    for j = 1, k do
      ret[k + j] = {s[i], unpack(ret[j])}
    end
  end
  return ret
end

implement a function that takes a set as input and returns its power set. The power set includes all subsets of the input set, including the empty set and the set itself. The function also demonstrates the handling of edge cases where the input set is empty or contains only the empty set.


create a function that converts a positive integer into its equivalent Roman numeral representation.


l = {}
l[1] = 1      -- Index starts with 1, not 0.
l[0] = 'zero' -- But you can use 0 if you want
l[10] = 2     -- Indexes need not be continuous
l.a = 3       -- Treated as l['a']. Any object can be used as index
l[l] = l      -- Again, any object can be used as an index. Even other tables
for i,v in next,l do print (i,v) end

demonstrate the basic syntax of arrays in a specific programming language. It includes the creation of an array, assigning a value to it, and retrieving an element from it. It also showcases the use of both fixed-length and dynamic arrays, and how to push a value into them. In the context of Lua, it explains how to emulate different types of containers using its table structure.


inFile  = io.open("input.txt", "r")
data = inFile:read("*all") -- may be abbreviated to "*a";
                           -- other options are "*line",
                           -- or the number of characters to read.
inFile:close()

outFile = io.open("output.txt", "w")
outfile:write(data)
outfile:close()

-- Oneliner version:
io.open("output.txt", "w"):write(io.open("input.txt", "r"):read("*a"))

demonstrate reading the contents of "input.txt" file into a variable and then writing this variable's contents into a new file called "output.txt".


str = "alphaBETA"

print( string.upper(str) ) -- ALPHABETA
print( string.lower(str) ) -- alphabeta

print ( str:upper() ) -- ALPHABETA
print ( str:lower() ) -- alphabeta

print ( string.upper("ação") ) -- returns AçãO instead of AÇÃO
print ( string.upper("ĥåçýджк") ) -- returns ĥåçýджк instead of ĤÅÇÝДЖК

The code takes the input string "alphaBETA", and demonstrates conversion to both upper-case and lower-case using the default string literal encoding or ASCII. It also showcases additional case conversion functions such as swapping case, capitalizing the first letter, etc. available in the language's library. The code works properly for ASCII and extended ASCII ranges but not for Unicode.


collection = {0, '1'}
print(collection[1]) -- prints 0

collection = {["foo"] = 0, ["bar"] = '1'} -- a collection of key/value pairs
print(collection["foo"]) -- prints 0
print(collection.foo) -- syntactic sugar, also prints 0

collection = {0, '1', ["foo"] = 0, ["bar"] = '1'}

create a collection in Lua using the table data structure, add a few values to it, and represent a Set data structure with a table of keys set to true. The table features both traditional arrays and hash maps, with numeric indices starting at 1.


items = {   ["panaea"] = { ["value"] = 3000, ["weight"] = 0.3, ["volume"] = 0.025 },
            ["ichor"]  = { ["value"] = 1800, ["weight"] = 0.2, ["volume"] = 0.015 },
            ["gold"]   = { ["value"] = 2500, ["weight"] = 2.0, ["volume"] = 0.002 }
        }

max_weight = 25
max_volume = 0.25

max_num_items = {}
for i in pairs( items ) do
   max_num_items[i] = math.floor( math.min( max_weight / items[i].weight, max_volume / items[i].volume ) )
end

best = { ["value"] = 0.0, ["weight"] = 0.0, ["volume"] = 0.0 }
best_amounts = {}

for i = 1, max_num_items["panaea"] do
    for j = 1, max_num_items["ichor"] do
        for k = 1, max_num_items["gold"] do
            current = { ["value"]  = i*items["panaea"]["value"] + j*items["ichor"]["value"] + k*items["gold"]["value"],
                        ["weight"] = i*items["panaea"]["weight"] + j*items["ichor"]["weight"] + k*items["gold"]["weight"],
                        ["volume"] = i*items["panaea"]["volume"] + j*items["ichor"]["volume"] + k*items["gold"]["volume"]
                      }

            if current.value > best.value and current.weight <= max_weight and current.volume <= max_volume then
                best = { ["value"] = current.value, ["weight"] = current.weight, ["volume"] = current.volume }
                best_amounts = { ["panaea"] = i, ["ichor"] = j, ["gold"] = k }
            end
        end
    end
end

print( "Maximum value:", best.value )
for k, v in pairs( best_amounts ) do
    print( k, v )
end

determine the maximum value of items that a traveler can carry in his knapsack, given the weight and volume constraints. The items include vials of panacea, ampules of ichor, and bars of gold. The code calculates the optimal quantity of each item to maximize the total value, considering that only whole units of any item can be taken.


for i = 1, 10 do
  io.write(i)
  if i == 10 then break end
  io.write", "
end

generates a comma-separated list of numbers from 1 to 10, using separate output statements for the number and the comma within a loop. The loop is designed to execute only part of its body in the last iteration.


s1 = "string"
s2 = "str"
s3 = "ing"
s4 = "xyz"

print( "s1 starts with s2: ", string.find( s1, s2 ) == 1 )
print( "s1 starts with s3: ", string.find( s1, s3 ) == 1, "\n" )

print( "s1 contains s3: ", string.find( s1, s3 ) ~= nil )
print( "s1 contains s3: ", string.find( s1, s4 ) ~= nil, "\n" )

print( "s1 ends with s2: ", select( 2, string.find( s1, s2 ) ) == string.len( s1 ) )
print( "s1 ends with s3: ", select( 2, string.find( s1, s3 ) ) == string.len( s1 ) )

The code checks if a given string starts with, contains, or ends with a second string. It also prints the location of the match and handles multiple occurrences of the second string within the first string.


function valid(unique,needle,haystack)
    if unique then
        for _,value in pairs(haystack) do
            if needle == value then
                return false
            end
        end
    end
    return true
end

function fourSquare(low,high,unique,prnt)
    count = 0
    if prnt then
        print("a", "b", "c", "d", "e", "f", "g")
    end
    for a=low,high do
        for b=low,high do
            if valid(unique, a, {b}) then
                fp = a + b
                for c=low,high do
                    if valid(unique, c, {a, b}) then
                        for d=low,high do
                            if valid(unique, d, {a, b, c}) and fp == b + c + d then
                                for e=low,high do
                                    if valid(unique, e, {a, b, c, d}) then
                                        for f=low,high do
                                            if valid(unique, f, {a, b, c, d, e}) and fp == d + e + f then
                                                for g=low,high do
                                                    if valid(unique, g, {a, b, c, d, e, f}) and fp == f + g then
                                                        count = count + 1
                                                        if prnt then
                                                            print(a, b, c, d, e, f, g)
                                                        end
                                                    end
                                                end
                                            end
                                        end
                                    end
                                end
                            end
                        end
                    end
                end
            end
        end
    end
    if unique then
        print(string.format("There are %d unique solutions in [%d, %d]", count, low, high))
    else
        print(string.format("There are %d non-unique solutions in [%d, %d]", count, low, high))
    end
end

fourSquare(1,7,true,true)
fourSquare(3,9,true,true)
fourSquare(0,9,false,false)

The code finds all possible solutions for a 4-squares puzzle where each square sums up to the same total. It operates under two conditions: each letter representing a unique value between 1-7 and 3-9, and each letter representing a non-unique value between 0-9. The code also counts the number of non-unique solutions.


create a visual representation of a time-keeping device that updates every second, in sync with the system clock, using efficient system or language events instead of constant polling. The code is kept simple and clear, avoiding unnecessary complexity.


FUNCTION PRINT_CAL(YEAR)
  LOCAL MONTHS={"JANUARY","FEBRUARY","MARCH","APRIL","MAY","JUNE",
                "JULY","AUGUST","SEPTEMBER","OCTOBER","NOVEMBER","DECEMBER"}
  LOCAL DAYSTITLE="MO TU WE TH FR SA SU"
  LOCAL DAYSPERMONTH={31,28,31,30,31,30,31,31,30,31,30,31}
  LOCAL STARTDAY=((YEAR-1)*365+MATH.FLOOR((YEAR-1)/4)-MATH.FLOOR((YEAR-1)/100)+MATH.FLOOR((YEAR-1)/400))%7
  IF YEAR%4==0 AND YEAR%100~=0 OR YEAR%400==0 THEN
    DAYSPERMONTH[2]=29
  END
  LOCAL SEP=5
  LOCAL MONTHWIDTH=DAYSTITLE:LEN()
  LOCAL CALWIDTH=3*MONTHWIDTH+2*SEP

  FUNCTION CENTER(STR, WIDTH)
    LOCAL FILL1=MATH.FLOOR((WIDTH-STR:LEN())/2)
    LOCAL FILL2=WIDTH-STR:LEN()-FILL1
    RETURN STRING.REP(" ",FILL1)..STR..STRING.REP(" ",FILL2)
  END

  FUNCTION MAKEMONTH(NAME, SKIP,DAYS)
    LOCAL CAL={
      CENTER(NAME,MONTHWIDTH),
      DAYSTITLE
    }
    LOCAL CURDAY=1-SKIP
    WHILE #CAL<9 DO
      LINE={}
      FOR I=1,7 DO
        IF CURDAY<1 OR CURDAY>DAYS THEN
          LINE[I]="  "
        ELSE
          LINE[I]=STRING.FORMAT("%2D",CURDAY)
        END
        CURDAY=CURDAY+1
      END
      CAL[#CAL+1]=TABLE.CONCAT(LINE," ")
    END
    RETURN CAL
  END

  LOCAL CALENDAR={}
  FOR I,MONTH IN IPAIRS(MONTHS) DO
    LOCAL DPM=DAYSPERMONTH[I]
    CALENDAR[I]=MAKEMONTH(MONTH, STARTDAY, DPM)
    STARTDAY=(STARTDAY+DPM)%7
  END

  PRINT(CENTER("[SNOOPY]",CALWIDTH):UPPER(),"\N")
  PRINT(CENTER("--- "..YEAR.." ---",CALWIDTH):UPPER(),"\N")

  FOR Q=0,3 DO
    FOR L=1,9 DO
      LINE={}
      FOR M=1,3 DO
        LINE[M]=CALENDAR[Q*3+M][L]
      END
      PRINT(TABLE.CONCAT(LINE,STRING.REP(" ",SEP)):UPPER())
    END
  END
END

PRINT_CAL(1969)

do io.input( arg[ 1 ] ); local s = io.read( "*a" ):lower(); io.close(); assert( load( s ) )() end

The code provides an algorithm for a calendar task, formatted to fit a page that is 132 characters wide. The entire code is written in uppercase, inspired by the 1969 era line printers and the article "Real programmers think in UPPERCASE". The code does not include Snoopy generation but outputs a placeholder instead. The code is tested with Lua 5.3.2 and uses a pre-processor to execute the upper-cased source.


Library: IUPLua
local iup = require "iuplua"

iup.dialog{
  title = "Window";
  iup.vbox{
    margin = "10x10";
    iup.label{title = "A window"}
  }
}:show()

iup.MainLoop()

"Creates an empty GUI window that can respond to close requests."


-- Return entire contents of named file
function readFile (filename)
  local file = assert(io.open(filename, "r"))
  local contents = file:read("*all")
  file:close()
  return contents
end

-- Return a closure to keep track of letter counts
function tally ()
  local t = {}

  -- Add x to tally if supplied, return tally list otherwise
  local function count (x)
    if x then
      if t[x] then
        t[x] = t[x] + 1
      else
        t[x] = 1
      end
    else
      return t
    end
  end

  return count
end

-- Main procedure
local letterCount = tally()
for letter in readFile(arg[1] or arg[0]):gmatch("%a") do
  letterCount(letter)
end
for k, v in pairs(letterCount()) do
  print(k, v)
end

i       24
f       16
R       2
v       2
c       19
k       4
M       1
s       14
d       17
l       40
e       61
t       54
m       4
r       34
u       18
C       3
o       32
A       1
g       3
x       7
F       2
y       4
w       1
n       42
h       4
a       25
p       7

open a text file and count the frequency of each letter. It only counts letters A-Z and treats upper and lower case letters as distinct. The functionality can be modified to count all characters or to ignore case sensitivity.


g, angle = love.graphics, 26 * math.pi / 180
wid, hei = g.getWidth(), g.getHeight()
function rotate( x, y, a )
  local s, c = math.sin( a ), math.cos( a )
  local a, b = x * c - y * s, x * s + y * c
  return a, b
end
function branches( a, b, len, ang, dir )
  len = len * .76
  if len < 5 then return end
  g.setColor( len * 16, 255 - 2 * len , 0 )
  if dir > 0 then ang = ang - angle
  else ang = ang + angle
  end
  local vx, vy = rotate( 0, len, ang )
  vx = a + vx; vy = b - vy
  g.line( a, b, vx, vy )
  branches( vx, vy, len, ang, 1 )
  branches( vx, vy, len, ang, 0 )
end
function createTree()
  local lineLen = 127
  local a, b = wid / 2, hei - lineLen
  g.setColor( 160, 40 , 0 )
  g.line( wid / 2, hei, a, b )
  branches( a, b, lineLen, 0, 1 )
  branches( a, b, lineLen, 0, 0 )
end
function love.load()
  canvas = g.newCanvas( wid, hei )
  g.setCanvas( canvas )
  createTree()
  g.setCanvas()
end
function love.draw()
  g.draw( canvas )
end

function Bitmap:tree(x, y, angle, depth, forkfn, lengfn)
  if depth <= 0 then return end
  local fork, leng = forkfn(), lengfn()
  local x2 = x + depth * leng * math.cos(angle)
  local y2 = y - depth * leng * math.sin(angle)
  self:line(math.floor(x), math.floor(y), math.floor(x2), math.floor(y2))
  self:tree(x2, y2, angle+fork, depth-1, forkfn, lengfn)
  self:tree(x2, y2, angle-fork, depth-1, forkfn, lengfn)
end

bitmap = Bitmap(128*3,128)
bitmap:tree( 64, 120, math.pi/2, 8, function() return 0.3 end, function() return 3 end)
bitmap:tree(192, 120, math.pi/2, 8, function() return 0.6 end, function() return 2.5 end)
bitmap:tree(320, 120, math.pi/2, 8, function() return 0.2+math.random()*0.3 end, function() return 2.0+math.random()*2.0 end)
bitmap:render({[0x000000]='.', [0xFFFFFFFF]='█'})

Generates and draws a fractal tree using LÖVE 2D Engine and Bitmap class with text renderer, by drawing a trunk, splitting it at the end by a certain angle into two branches, and repeating this process until a desired level of branching is achieved. The final output is displayed at 25% scale.


function Factors( n )
    local f = {}

    for i = 1, n/2 do
        if n % i == 0 then
            f[#f+1] = i
        end
    end
    f[#f+1] = n

    return f
end

compute the factors of a given positive integer, excluding zero and negative numbers. The factors are the positive integers that can divide the input number to yield a positive integer. For prime numbers, the factors are 1 and the number itself.


Works with: Lua version 5.1
local tWord = {}        -- word table
local tColLen = {}      -- maximum word length in a column
local rowCount = 0      -- row counter
--store maximum column lengths at 'tColLen'; save words into 'tWord' table
local function readInput(pStr)
    for line in pStr:gmatch("([^\n]+)[\n]-") do  -- read until '\n' character
        rowCount = rowCount + 1
        tWord[rowCount] = {}                     -- create new row
        local colCount = 0
        for word in line:gmatch("[^$]+") do      -- read non '$' character
            colCount = colCount + 1
            tColLen[colCount] = math.max((tColLen[colCount] or 0), #word)   -- store column length
            tWord[rowCount][colCount] = word                                -- store words
        end--for word
    end--for line
end--readInput
--repeat space to align the words in the same column
local align = {
    ["left"] = function (pWord, pColLen)
        local n = (pColLen or 0) - #pWord + 1
        return pWord .. (" "):rep(n)
    end;--["left"]
    ["right"] = function (pWord, pColLen)
        local n = (pColLen or 0) - #pWord + 1
        return (" "):rep(n) .. pWord
    end;--["right"]
    ["center"] = function (pWord, pColLen)
        local n = (pColLen or 0) - #pWord + 1
        local n1 = math.floor(n/2)
        return (" "):rep(n1) .. pWord .. (" "):rep(n-n1)
    end;--["center"]
}
--word table padder
local function padWordTable(pAlignment)
    local alignFunc = align[pAlignment]                         -- selecting the spacer function
    for rowCount, tRow in ipairs(tWord) do
        for colCount, word in ipairs(tRow) do
            tRow[colCount] = alignFunc(word, tColLen[colCount]) -- save the padded words into the word table
        end--for colCount, word
    end--for rowCount, tRow
end--padWordTable
--main interface
--------------------------------------------------[]
function alignColumn(pStr, pAlignment, pFileName)
--------------------------------------------------[]
    readInput(pStr)                           -- store column lengths and words
    padWordTable(pAlignment or "left")        -- pad the stored words
    local output = ""
    for rowCount, tRow in ipairs(tWord) do
        local line = table.concat(tRow)       -- concatenate words in one row
        print(line)                           -- print the line
        output = output .. line .. "\n"       -- concatenate the line for output, add line break
    end--for rowCount, tRow
    if (type(pFileName) == "string") then
        local file = io.open(pFileName, "w+")
        file:write(output)                    -- write output to file
        file:close()
    end--if type(pFileName)
    return output
end--alignColumn

input =
[[Given$a$text$file$of$many$lines,$where$fields$within$a$line$
are$delineated$by$a$single$'dollar'$character,$write$a$program
that$aligns$each$column$of$fields$by$ensuring$that$words$in$each$
column$are$separated$by$at$least$one$space.
Further,$allow$for$each$word$in$a$column$to$be$either$left$
justified,$right$justified,$or$center$justified$within$its$column.]]

outputLeft = alignColumn(input)
outputRight = alignColumn(input, "right")
alignColumn(input, "center", "output.txt")

The code reads a text file where fields within a line are separated by a dollar character. It aligns each column by ensuring at least one space between words in each column. The words in a column can be left justified, right justified, or center justified. The code also handles trailing dollar characters, shared alignment across columns, and insignificant consecutive spaces at the end of lines. The minimum space between columns is computed from the text and not hard-coded. The code does not add separating characters between or around columns.


-- needed for actual task
cube.scale = function(self, sx, sy, sz)
  for i,v in ipairs(self.verts) do
    v[1], v[2], v[3] = v[1]*sx, v[2]*sy, v[3]*sz
  end
end
-- only needed for output
-- (to size it for screen, given a limited camera)
cube.translate = function(self, tx, ty, tz)
  for i,v in ipairs(self.verts) do
    v[1], v[2], v[3] = v[1]+tx, v[2]+ty, v[3]+tz
  end
end

--
bitmap:init(40,40)
cube:scale(2,3,4)
cube:rotate(-pi/4, -pi/6)
cube:translate(0,0,10)
bitmap:clear("··")
renderer:render(cube, camera, bitmap)
screen:clear()
bitmap:render()

generate a graphical or ASCII art representation of a cuboid with dimensions 2x3x4, showing three visible faces. The cuboid can be either static or rotating, extending from the Draw_a_rotating_cube task.


function rot13(s)
	local a = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
	local b = "NOPQRSTUVWXYZABCDEFGHIJKLMnopqrstuvwxyzabcdefghijklm"
	return (s:gsub("%a", function(c) return b:sub(a:find(c)) end))
end

function rot13(s)
  return (s:gsub("%a", function(c) c=c:byte() return string.char(c+(c%32<14 and 13 or -13)) end))
end

implement a rot-13 function that replaces every letter of the ASCII alphabet with the letter which is "rotated" 13 characters around the 26 letter alphabet. The function should work on both upper and lower case letters, preserve case, and pass all non-alphabetic characters without alteration. Optionally, the function can be wrapped in a utility program that performs rot-13 encoding line-by-line for every line of input in each file listed on its command line or acts as a filter on its standard input.


function sorting( a, b )
    return a[1] < b[1]
end

tab = { {"C++", 1979}, {"Ada", 1983}, {"Ruby", 1995}, {"Eiffel", 1985} }

table.sort( tab, sorting )
for _, v in ipairs( tab ) do
    print( unpack(v) )
end

sort an array of composite structures, specifically name-value pairs, by the key name using a custom comparator.


for i=1,5 do
  for j=1,i do
    io.write("*")
  end
  io.write("\n")
end

for i = 1, 5 do
  print(string.rep("*", i))
end

for i = 1, 5 do
  print(("*"):rep(i))
end

Code summarization: The code demonstrates the use of nested "for" loops, where the number of iterations of the inner loop is controlled by the outer loop. It prints a pattern of asterisks, with each line containing one more asterisk than the previous line.


create an associative array (dictionary, map, or hash) in Lua where unknown keys return nil.


Works with: Lua version 5.3

local RNG = {
  new = function(class, a, c, m, rand)
    local self = setmetatable({}, class)
    local state = 0
    self.rnd = function()
      state = (a * state + c) % m
      return rand and rand(state) or state
    end
    self.seed = function(new_seed)
      state = new_seed % m
    end
    return self
  end
}

bsd = RNG:new(1103515245, 12345, 1<<31)
ms = RNG:new(214013, 2531011, 1<<31, function(s) return s>>16 end)

print"BSD:"
for _ = 1,10 do
  print(("\t%10d"):format(bsd.rnd()))
end
print"Microsoft:"
for _ = 1,10 do
  print(("\t%10d"):format(ms.rnd()))
end

The code replicates two historic random number generators: the rand() function from BSD libc and the rand() function from the Microsoft C Runtime (MSCVRT.DLL). It uses the Linear Congruential Generator (LCG) formula to generate a sequence of random numbers. The code is designed to produce the same sequence of integers as the original generators when starting from the same seed. It requires Lua 5.3 or later due to the need for large integers and integral arithmetic operations.


function halve(a)
    return a/2
end

function double(a)
    return a*2
end

function isEven(a)
    return a%2 == 0
end

function ethiopian(x, y)
    local result = 0

    while (x >= 1) do
        if not isEven(x) then
            result = result + y
        end

        x = math.floor(halve(x))
        y = double(y)
    end

    return result;
end

print(ethiopian(17, 34))

The code defines three functions for halving an integer, doubling an integer, and checking if an integer is even. These functions are used to implement Ethiopian multiplication, a method of multiplying integers using addition, doubling, and halving. The multiplication process involves creating a table, discarding rows with even numbers in the left column, and summing the remaining values in the right column.


local SIZE = #arg[1]
local GOAL = tonumber(arg[2]) or 24

local input = {}
for v in arg[1]:gmatch("%d") do
	table.insert(input, v)
end
assert(#input == SIZE, 'Invalid input')

local operations = {'+', '-', '*', '/'}

local function BinaryTrees(vert)
	if vert == 0 then
		return {false}
	else
		local buf = {}
		for leften = 0, vert - 1 do
			local righten = vert - leften - 1
			for _, left in pairs(BinaryTrees(leften)) do
				for _, right in pairs(BinaryTrees(righten)) do
					table.insert(buf, {left, right})
				end
			end
		end
		return buf
	end
end
local trees = BinaryTrees(SIZE-1)
local c, opc, oper, str
local max = math.pow(#operations, SIZE-1)
local function op(a,b)
	opc = opc + 1
	local i = math.floor(oper/math.pow(#operations, opc-1))%#operations+1
	return '('.. a .. operations[i] .. b ..')'
end

local function EvalTree(tree)
	if tree == false then
		c = c + 1
		return input[c-1]
	else
		return op(EvalTree(tree[1]), EvalTree(tree[2]))
	end
end

local function printResult()
	for _, v in ipairs(trees) do
		for i = 0, max do
			c, opc, oper = 1, 0, i
			str = EvalTree(v)
			loadstring('res='..str)()
			if(res == GOAL) then print(str, '=', res) end
		end
	end
end

local uniq = {}
local function permgen (a, n)
	if n == 0 then
		local str = table.concat(a)
		if not uniq[str] then
			printResult()
			uniq[str] = true
		end
	else
		for i = 1, n do
			a[n], a[i] = a[i], a[n]
			permgen(a, n - 1)
			a[n], a[i] = a[i], a[n]
		end
	end
end

permgen(input, SIZE)

The code takes four digits as input, either user-provided or randomly generated, and calculates arithmetic expressions based on the rules of the 24 game. It also displays examples of solutions it generates. Additionally, it includes a generic solver that accepts a card of any size as the first argument and the target number as the second.


function fact(n)
  return n > 0 and n * fact(n-1) or 1
end
Tail function fact(n, acc)
  acc = acc or 1
  if n == 0 then
    return acc
  end
  return fact(n-1, n*acc)
end

fact = setmetatable({[0] = 1}, {
  __call = function(t,n)
    if n < 0 then return 0 end
    if not t[n] then t[n] = n * t(n-1) end
    return t[n]
  end
})

The code calculates and returns the factorial of a given number, either through an iterative or recursive method. It optionally handles negative input errors. The factorial function multiplies a sequence of descending positive integers from the input number to 1. The code also features memoization, storing previously calculated factorials for efficient retrieval.


function ShuffleArray(array)
   for i=1,#array-1 do
      local t = math.random(i, #array)
      array[i], array[t] = array[t], array[i]
   end
end

function GenerateNumber()
   local digits = {1,2,3,4,5,6,7,8,9}

   ShuffleArray(digits)

   return digits[1] * 1000 +
          digits[2] *  100 +
          digits[3] *   10 +
          digits[4]
end

function IsMalformed(input)
   local malformed = false

   if #input == 4 then
      local already_used = {}
      for i=1,4 do
         local digit = input:byte(i) - string.byte('0')
         if digit < 1 or digit > 9 or already_used[digit] then
            malformed = true
            break
         end
         already_used[digit] = true
      end
   else
      malformed = true
   end

   return malformed
end

math.randomseed(os.time())
math.randomseed(math.random(2^31-1)) -- since os.time() only returns seconds

print("\nWelcome to Bulls and Cows!")
print("")
print("The object of this game is to guess the random 4-digit number that the")
print("computer has chosen. The number is generated using only the digits 1-9,")
print("with no repeated digits. Each time you enter a guess, you will score one")
print("\"bull\" for each digit in your guess that matches the corresponding digit")
print("in the computer-generated number, and you will score one \"cow\" for each")
print("digit in your guess that appears in the computer-generated number, but is")
print("in the wrong position. Use this information to refine your guesses. When")
print("you guess the correct number, you win.");
print("")

quit = false

repeat
   magic_number = GenerateNumber()
   magic_string = tostring(magic_number) -- Easier to do scoring with a string
   repeat
      io.write("\nEnter your guess (or 'Q' to quit): ")
      user_input = io.read()
      if user_input == 'Q' or user_input == 'q' then
         quit = true
         break
      end

      if not IsMalformed(user_input) then
         if user_input == magic_string then
            print("YOU WIN!!!")
         else
            local bulls, cows = 0, 0
            for i=1,#user_input do
               local find_result = magic_string:find(user_input:sub(i,i))

               if find_result and find_result == i then
                  bulls = bulls + 1
               elseif find_result then
                  cows = cows + 1
               end
            end
            print(string.format("You scored %d bulls, %d cows", bulls, cows))
         end
      else
         print("Malformed input. You must enter a 4-digit number with")
         print("no repeated digits, using only the digits 1-9.")
      end

   until user_input == magic_string

   if not quit then
      io.write("\nPress <Enter> to play again or 'Q' to quit: ")
      user_input = io.read()
      if user_input == 'Q' or user_input == 'q' then
         quit = true
      end
   end

   if quit then
      print("\nGoodbye!")
   end
until quit

function createNewNumber ()
	math.randomseed(os.time())
	local numbers = {1, 2, 3, 4, 5, 6, 7, 8, 9}
	local tNumb = {} -- list of numbers
	for i = 1, 4 do
		table.insert(tNumb, math.random(#tNumb+1), table.remove(numbers, math.random(#numbers)))
	end
	return tNumb
end

TNumber = createNewNumber ()
print ('(right number: ' .. table.concat (TNumber) .. ')')

function isValueInList (value, list)
	for i, v in ipairs (list) do
		if v == value then return true end
	end
	return false
end

local nGuesses = 0

while not GameOver do
	nGuesses = nGuesses + 1
	print("Enter your guess (or 'q' to quit): ")
	local input
	while not input do
		input = io.read()
	end
	if input == "q" then
		GameOver = true
		return
	end
	local tInput = {}
	for i=1, string.len(input) do
		local number = tonumber(string.sub(input,i,i))
		if number and not isValueInList (number, tInput) then
			table.insert (tInput, number)
		end
	end
	local malformed = false
	if not (string.len(input) == 4) or not (#tInput == 4) then
		print (nGuesses, 'bad input: too short or too long')
		malformed = true
	end

	if not malformed then
		print (nGuesses, 'parsed input:', table.concat(tInput, ', '))
		local nBulls, nCows = 0, 0
		for i, number in ipairs (tInput) do
			if TNumber[i] == number then
				nBulls = nBulls + 1
			elseif isValueInList (number, TNumber) then
				nCows = nCows + 1
			end
		end
		print (nGuesses, 'Bulls: '.. nBulls .. ' Cows: ' .. nCows)
		if nBulls == 4 then
			print (nGuesses, 'Win!')
			GameOver = true
		end
	end
end

"Generates a four-digit random number without duplication from 1 to 9. The program prompts the user for guesses, rejects malformed guesses, and prints the score for each guess. The score is calculated based on the number of 'bulls' and 'cows', where a 'bull' is a correctly guessed digit in the correct position and a 'cow' is a correctly guessed digit in the wrong position. The game ends when the user's guess matches the randomly generated number."


local list = {}
for i = 1, 1000 do
  list[i] = 1 + math.sqrt(-2 * math.log(math.random())) * math.cos(2 * math.pi * math.random()) / 2
end

generate a collection of 1000 normally distributed pseudo-random numbers with a mean of 1.0 and a standard deviation of 0.5.


function dotprod(a, b)
  local ret = 0
  for i = 1, #a do
    ret = ret + a[i] * b[i]
  end
  return ret
end

print(dotprod({1, 3, -5}, {4, -2, 1}))

Implement a function to calculate the dot product of two vectors of arbitrary length. The function multiplies corresponding elements from each vector and sums the products. The vectors must be of the same length. Example vectors used are [1, 3, -5] and [4, -2, -1].


lines = {}
str = io.read()
while str do
    table.insert(lines,str)
    str = io.read()
end

lines = {}

for line in io.lines() do
    table.insert(lines, line) -- add the line to the list of lines
end

The code reads data from a text stream, either word-by-word or line-by-line, until there's no data left. It uses an iterator to read line-by-line from stdin, but can be modified to read from a file by substituting io.lines() with io.open(filename, "r"):lines().


require("LuaXML")
local dom = xml.new("root")
local element = xml.new("element")
table.insert(element, "Some text here")
dom:append(element)
dom:save("dom.xml")

<?xml version="1.0"?>
<!-- file "dom.xml", generated by LuaXML -->

<root>
  <element>Some text here</element>
</root>

The code creates a simple DOM using the 'LuaXML' module and serializes it into the specified XML format, with the resulting contents stored in 'dom.xml'.


the system time in a specified unit. This can be used for debugging, network information, random number seeds, or program performance. The time is retrieved either by a system command or a built-in language function. It is related to the task of date formatting and retrieving system time.


Works with: Lua version 5.1.4
require ("math")

shades = {'.', ':', '!', '*', 'o', 'e', '&', '#', '%', '@'}

function normalize (vec)
    len = math.sqrt(vec[1]^2 + vec[2]^2 + vec[3]^2)
    return {vec[1]/len, vec[2]/len, vec[3]/len}
end

light = normalize{30, 30, -50}

function dot (vec1, vec2)
    d = vec1[1]*vec2[1] + vec1[2]*vec2[2] + vec1[3]*vec2[3]
    return d < 0 and -d or 0
end

function draw_sphere (radius, k, ambient)
    for i = math.floor(-radius),-math.floor(-radius) do
        x = i + .5
        local line = ''
        for j = math.floor(-2*radius),-math.floor(-2*radius) do
            y = j / 2 + .5
            if x^2 + y^2 <= radius^2 then
                vec = normalize{x, y, math.sqrt(radius^2 - x^2 - y^2)}
                b = dot(light,vec) ^ k + ambient
                intensity = math.floor ((1 - b) * #shades)
                line = line .. (shades[intensity] or shades[1])
            else
                line = line .. ' '
            end
        end
        print (line)
    end
end

draw_sphere (20, 4, 0.1)
draw_sphere (10, 2, 0.4)

"Generates a graphical or ASCII art representation of a sphere, with either static or rotational projection."


function getSuffix (n)
    local lastTwo, lastOne = n % 100, n % 10
    if lastTwo > 3 and lastTwo < 21 then return "th" end
    if lastOne == 1 then return "st" end
    if lastOne == 2 then return "nd" end
    if lastOne == 3 then return "rd" end
    return "th"
end

function Nth (n) return n .. "'" .. getSuffix(n) end

for i = 0, 25 do print(Nth(i), Nth(i + 250), Nth(i + 1000)) end

The code defines a function that takes an integer input greater than or equal to zero and returns a string representation of the number with its ordinal suffix. The function is tested with integer ranges 0..25, 250..265, and 1000..1025. The use of apostrophes in the output is optional.


function stripchars(str, chrs)
  local s = str:gsub("["..chrs:gsub("%W","%%%1").."]", '')
  return s
end

print( stripchars( "She was a soul stripper. She took my heart!", "aei" ) )
--> Sh ws  soul strppr. Sh took my hrt!
print( stripchars( "She was a soul stripper. She took my heart!", "a-z" ) )
--> She ws  soul stripper. She took my hert!

"Function to remove specific characters from a given string"


function genFizz (param)
  local response
  print("\n")
  for n = 1, param.limit do
    response = ""
    for i = 1, 3 do
      if n % param.factor[i] == 0 then
        response = response .. param.word[i]
      end
    end
    if response == "" then print(n) else print(response) end
  end
end

local param = {factor = {}, word = {}}
param.limit = io.read()
for i = 1, 3 do
  param.factor[i], param.word[i] = io.read("*number", "*line")
end
genFizz(param)
local function fizzbuzz(n, mods)
  local res = {}

  for i = 1, #mods, 2 do
    local mod, name = mods[i], mods[i+1]
    for i = mod, n, mod do
      res[i] = (res[i] or '') .. name
    end
  end

  for i = 1, n do
    res[i] = res[i] or i
  end

  return table.concat(res, '\n')
end

do
  local n = tonumber(io.read())     -- number of lines, eg. 100
  local mods = {}

  local n_mods = 0
  while n_mods ~= 3 do              -- for reading until EOF, change 3 to -1
    local line = io.read()
    if not line then break end
    local s, e = line:find(' ')
    local num  = tonumber(line:sub(1, s-1))
    local name = line:sub(e+1)
    mods[#mods+1] = num
    mods[#mods+1] = name
    n_mods = n_mods + 1
  end

  print(fizzbuzz(n, mods))
end

implement a generalized version of FizzBuzz that takes a maximum number and a list of factor-word pairs as inputs from the user. The code prints numbers from 1 to the maximum number, replacing multiples of each factor with the corresponding word. For numbers that are multiples of multiple factors, the associated words are printed in ascending order of their factors.


- Initializes a string variable with any text value
- Prepends another string literal to the initialized string variable
- Includes idiomatic solutions for the operation if supported by the language, without referring to the variable twice in one expression
- Displays the content of the variable after the operation
- Illustrates the operation through concatenation, string formatting, and list joining.


Works with: Lua version 5.1.4

function dragon()
    local l = "l"
    local r = "r"
    local inverse = {l = r, r = l}
    local field = {r}
    local num = 1
    local loop_limit = 6 --increase this number to render a bigger curve
    for discard=1,loop_limit do
        field[num+1] = r
        for i=1,num do
            field[i+num+1] = inverse[field[num-i+1]]
        end
        num = num*2+1
    end
    return field
end

function render(field, w, h, l)
    local x = 0
    local y = 0
    local points = {}
    local highest_x = 0
    local highest_y = 0
    local lowest_x = 0
    local lowest_y = 0
    local l = "l"
    local r = "r"
    local u = "u"
    local d = "d"
    local heading = u
    local turn = {r = {r = d, d = l, l = u, u = r}, l = {r = u, u = l, l = d, d = r}}
    for k, v in ipairs(field) do
        heading = turn[v][heading]
        for i=1,3 do
            points[#points+1] = {x, y}
            if heading == l then
                x = x-w
            elseif heading == r then
                x = x+w
            elseif heading == u then
                y = y-h
            elseif heading == d then
                y = y+h
            end
            if x > highest_x then
                highest_x = x
            elseif x < lowest_x then
                lowest_x = x
            end
            if y > highest_y then
                highest_y = y
            elseif y < lowest_y then
                lowest_y = y
            end
        end
    end
    points[#points+1] = {x, y}
    highest_x = highest_x - lowest_x + 1
    highest_y = highest_y - lowest_y + 1
    for k, v in ipairs(points) do
        v[1] = v[1] - lowest_x + 1
        v[2] = v[2] - lowest_y + 1
    end
    return highest_x, highest_y, points
end

function render_text_mode()
    local width, height, points = render(dragon(), 1, 1, 1)
    local rows = {}
    for i=1,height do
        rows[i] = {}
        for j=1,width do
            rows[i][j] = ' '
        end
    end
    for k, v in ipairs(points) do
        rows[v[2]][v[1]] = "*"
    end

    for i=1,height do
        print(table.concat(rows[i], ""))
    end
end

function dump_points()
    local width, height, points = render(dragon(), 4, 4, 1)
    for k, v in ipairs(points) do
        print(unpack(v))
    end
end

--replace this line with dump_points() to output a list of coordinates:
render_text_mode()

      ****  ****
      *  *  *  *
      *  *  *  *
   ****  *******
   *        *
   *        *
   ****     ****  ****
               *  *  *
               *  *  *
            **********
            *  *  *
            *  *  *
            *******
               *
               *
      ****  ****
      *  *  *
      *  *  *
      **********  ****
         *  *  *  *  *
         *  *  *  *  *
****  ****************
*  *  *  *  *  *  *
*  *  *  *  *  *  *
*******************
   *  *  *  *  *
   *  *  *  *  *
*******  *******              ****
*  *        *                    *
*  *        *                    *
*******     ****  ****           ****
   *  *        *  *  *              *
   *  *        *  *  *              *
   ****     **********           ****
            *  *  *              *
            *  *  *              *
            **********  ****  *******
               *  *  *  *  *  *  *  *
               *  *  *  *  *  *  *  *
            *******  **********  ****
            *  *        *  *
            *  *        *  *
            *******     *******
               *  *        *  *
               *  *        *  *
               ****        ****

The code generates a dragon curve fractal, which can be displayed directly or written to an image file. It uses various algorithms, including recursive, successive approximation, iterative, absolute direction, absolute coordinates, predicate test, and Lindenmayer system methods. The code also offers two rendering modes: text mode and a mode for external rendering applications. It is designed for speed and can be used to draw other curves defined by L-systems.


math.randomseed( os.time() )
n = math.random( 1, 10 )

print( "I'm thinking of a number between 1 and 10. Try to guess it: " )

repeat
    x = tonumber( io.read() )

    if x == n then
	print "Well guessed!"
    else
	print "Guess again: "
    end
until x == n

"Implement a number guessing game where the computer selects a number between 1 and 10. The player is repeatedly prompted to guess the number until the correct number is guessed, upon which a 'Well guessed!' message is displayed and the program terminates. A conditional loop is used to facilitate repeated guessing."


function getAlphabet ()
    local letters = {}
    for ascii = 97, 122 do table.insert(letters, string.char(ascii)) end
    return letters
end

local alpha = getAlphabet()
print(alpha[25] .. alpha[1] .. alpha[25])

generate a sequence of all lower case ASCII characters from a to z. This is done in a reliable coding style suitable for large programs, using strong typing if available. The code avoids manual enumeration of characters to prevent bugs. It also demonstrates how to access a similar sequence from the standard library if it exists.


function dec2bin(n)
    local bin = ""
    while n > 1 do
        bin = n % 2 .. bin
        n = math.floor(n / 2)
    end
    return n .. bin
end

print(dec2bin(5))
print(dec2bin(50))
print(dec2bin(9000))

generate a sequence of binary digits for a given non-negative integer. The output displays only the binary digits of each number, followed by a newline, without any whitespace, radix, sign markers, or leading zeros. The conversion can be achieved using built-in radix functions or a user-defined function.


local SDL = require "SDL"

local ret = SDL.init { SDL.flags.Video }
local window = SDL.createWindow {
	title	= "Pixel",
	height	= 320,
	width	= 240
}

local renderer = SDL.createRenderer(window, 0, 0)

renderer:clear()
renderer:setDrawColor(0xFF0000)
renderer:drawPoint({x = 100,y = 100})
renderer:present()

SDL.delay(5000)

Creates a 320x240 window using the luasdl2 library and draws a red pixel at the position (100,100).