Family Day update

This commit is contained in:
Ingy döt Net 2020-02-17 23:21:07 -08:00
parent aac6731f2c
commit 9ad63ea473
2442 changed files with 39761 additions and 8255 deletions

View file

@ -3,29 +3,18 @@ namespace ConsoleApplication1
using System;
class Program
{
static void Main()
static void Main(string[] args)
{
//The o variable stores the number of the next OPEN door.
int o = 1;
int f = 1;
int l = 5;
Random r = new Random();
o = r.Next(f, l);
//Perform the operation.
bool[] doors = new bool[100];
int n = 0;
int d;
while ((d = (++n * n)) <= 100)
doors[d - 1] = true;
//The d variable determines the door to be output next.
for (int d = 1; d <= 100; d++)
{
Console.Write("Door #{0}: ", d);
if (d == o)
{
Console.WriteLine("Open");
f = f + 5;
l = l + 5;
o = r.Next(f, l);
}
else
Console.WriteLine("Closed");
}
//Perform the presentation.
for (d = 0; d < doors.Length; d++)
Console.WriteLine("Door #{0}: {1}", d + 1, doors[d] ? "Open" : "Closed");
Console.ReadKey(true);
}
}

View file

@ -3,17 +3,15 @@ namespace ConsoleApplication1
using System;
class Program
{
static void Main(string[] args)
static void Main()
{
//Perform the operation.
bool[] doors = new bool[100];
int n = 0;
int d;
while ((d = (++n * n)) <= 100)
doors[d - 1] = true;
//Perform the presentation.
for (d = 0; d < doors.Length; d++)
//The number of passes can be 1-based, but the number of doors must be 0-based.
for (int p = 1; p <= 100; p++)
for (int d = p - 1; d < 100; d += p)
doors[d] = !doors[d];
for (int d = 0; d < 100; d++)
Console.WriteLine("Door #{0}: {1}", d + 1, doors[d] ? "Open" : "Closed");
Console.ReadKey(true);
}

View file

@ -5,14 +5,11 @@ namespace ConsoleApplication1
{
static void Main()
{
bool[] doors = new bool[100];
double n;
//The number of passes can be 1-based, but the number of doors must be 0-based.
for (int p = 1; p <= 100; p++)
for (int d = p - 1; d < 100; d += p)
doors[d] = !doors[d];
for (int d = 0; d < 100; d++)
Console.WriteLine("Door #{0}: {1}", d + 1, doors[d] ? "Open" : "Closed");
//If the current door number is the perfect square of an integer, say it is open, else say it is closed.
for (int d = 1; d <= 100; d++)
Console.WriteLine("Door #{0}: {1}", d, (n = Math.Sqrt(d)) == (int)n ? "Open" : "Closed");
Console.ReadKey(true);
}
}

View file

@ -0,0 +1,115 @@
[Hundred doors problem from Rosetta Code website]
[EDSAC program, Initial Orders 2]
[Library subroutine M3. Prints header and is then overwritten.
Here, the last character sets the teleprinter to figures.]
PFGKIFAFRDLFUFOFE@A6FG@E8FEZPF
@&*THE!OPEN!DOORS!ARE@&#
..PZ [blank tape, needed to mark end of header text]
[Library subroutine P6. Prints strictly positive integer.
32 locations; working locations 1, 4, 5]
T56K [define load address for subroutine]
GKA3FT25@H29@VFT4DA3@TFH30@S6@T1F
V4DU4DAFG26@TFTFO5FA4DF4FS4F
L4FT4DA1FS3@G9@EFSFO31@E20@J995FJF!F
T88K [define load address for main program]
GK [set @ (theta) for relative addresses]
[The 100 doors are at locations 200..299.
Doors are numbered 0..99 internally, and 1..100 for output.
The base address and the number of doors can be varied.
The value of a door is 0 if open, negative if closed.]
[Constants. Program also uses order 'P 1 F'
which is permanently at absolute address 2.]
[0] P200F [address of door #0]
[1] P100F [number of doors, as an address]
[2] UF [makes S order from T, since 'S' = 'T' + 'U']
[3] MF [makes A order from T, since 'A' = 'T' + 'M']
[4] V2047D [all 1's for "closed" (any negative value will do)]
[5] &F [line feed]
[6] @F [carriage return]
[7] K4096F [teleprinter null[
[Variables]
[8] PF [pass number; step when toggling doors]
[9] PF [door number, as address, 0-based]
[10] PF [order referring to door 0]
[Enter with acc = 0]
[Part 1 : close all the doors]
[11] T8@ [pass := 0 (used in part 2)]
T9@ [door number := 0]
A16@ [load 'T F' order]
A@ [add base address]
T10@ [store T order for door #0]
[16] TF [clear acc; also serves as constant]
A9@ [load door number]
A10@ [make T order]
T21@ [plant in code]
A4@ [load value for "closed"]
[21] TF [store in current door]
A9@ [load door number]
A2F [add 1]
U9@ [update door number]
S1@ [done all doors yet?]
G16@ [if not, loop back]
[Part 2 : 100 passes, toggling the doors]
[27] TF [clear acc]
A8@ [load pass number]
A2F [add 1]
T8@ [save updated pass number]
S2F [make -1]
U9@ [door number := -1]
A8@ [add pass number to get first door toggled on this pass]
S1@ [gone beyond end?]
E50@ [if so, move on to part 3]
[36] A1@ [restore acc after test]
U9@ [store current door number]
A10@ [make T order to load status]
U44@ [plant T order for first door in pass]
A2@ [convert to S order]
T43@ [plant S order]
A4@ [load value for "closed"]
[43] SF [subtract status; toggles status]
[44] TF [update status]
A9@ [load door number just toggled]
A8@ [add pass number to get next door in pass]
S1@ [gone beyond end?]
G36@ [no, loop to do next door]
E27@ [yes, loop to do next pass]
[Part 3 : Print list of open doors.
Header has set teleprinter to figures.]
[50] TF [clear acc]
T9@ [door nr := 0]
A10@ [T order for door 0]
A3@ [convert to A order]
T10@
[55] TF
A9@ [load door number]
A10@ [make A order to load value]
T59@ [plant in next order]
[59] AF [acc := 0 if open, < 0 if closed]
G69@ [skip if closed]
A9@ [door number as address]
A2F [add 1 for 1-based output]
RD [shift 1 right, address --> integer]
TF [store integer at 0 for printing]
[65] A65@ [for return from subroutine]
G56F [call subroutine to print door number]
O6@ [followed by CRLF]
O5@
[69] TF [clear acc]
A9@ [load door number]
A2F [add 1]
U9@ [update door number]
S1@ [done all doors yet?]
G55@ [if not, loop back]
[75] O7@ [output null to flush teleprinter buffer]
ZF [stop]
E11Z [define relative start address]
PF

View file

@ -1,6 +1,14 @@
class HundredDoors {
import java.util.BitSet;
public class HundredDoors {
public static void main(String[] args) {
for (int i = 1; i <= 10; i++)
System.out.printf("Door %d is open.%n", i * i);
final int n = 100;
var a = new BitSet(n);
for (int i = 1; i <= n; i++) {
for (int j = i - 1; j < n; j += i) {
a.flip(j);
}
}
a.stream().map(i -> i + 1).forEachOrdered(System.out::println);
}
}

View file

@ -1,12 +1,6 @@
import java.util.stream.Collectors;
import java.util.stream.IntStream;
class HundredDoors {
public static void main(String args[]) {
String openDoors = IntStream.rangeClosed(1, 100)
.filter(i -> Math.pow((int) Math.sqrt(i), 2) == i)
.mapToObj(Integer::toString)
.collect(Collectors.joining(", "));
System.out.printf("Open doors: %s%n", openDoors);
public static void main(String[] args) {
for (int i = 1; i <= 10; i++)
System.out.printf("Door %d is open.%n", i * i);
}
}

View file

@ -0,0 +1,12 @@
import java.util.stream.Collectors;
import java.util.stream.IntStream;
class HundredDoors {
public static void main(String args[]) {
String openDoors = IntStream.rangeClosed(1, 100)
.filter(i -> Math.pow((int) Math.sqrt(i), 2) == i)
.mapToObj(Integer::toString)
.collect(Collectors.joining(", "));
System.out.printf("Open doors: %s%n", openDoors);
}
}

View file

@ -1,16 +1,11 @@
from strutils import format
from strutils import `%`
proc check_doors() =
const n = 100
var is_open : array[1..n, bool] # auto-initialized to false
# pass over the doors n times
for pass in 1..n:
var i = pass
while i <= n:
is_open[i] = not is_open[i]
i += pass
# print the result
for door in 1..n:
echo format("door $1 is $2.", door, (if is_open[door]: "open" else: "closed"))
const numDoors = 100
var doors: array[1..numDoors, bool]
check_doors()
for pass in 1..numDoors:
for door in countup(pass, numDoors, pass):
doors[door] = not doors[door]
for door in 1..numDoors:
echo "Door $1 is $2." % [$door, if doors[door]: "open" else: "closed"]

View file

@ -1,9 +1,15 @@
var isOpen: array[1..100, bool]
from strutils import `%`
for pass in countup(1, 100):
for door in countup(pass,100,pass):
isOpen[door] = not isOpen[door]
const numDoors = 100
var doors {.compileTime.}: array[1..numDoors, bool]
for i in countup(1, 100):
if isOpen[i]:
echo("Door ",i," is open.")
proc calcDoors(): string =
for pass in 1..numDoors:
for door in countup(pass, numDoors, pass):
doors[door] = not doors[door]
for door in 1..numDoors:
result.add("Door $1 is $2.\n" % [$door, if doors[door]: "open" else: "closed"])
const outputString: string = calcDoors()
echo outputString

View file

@ -1,7 +1,7 @@
: doors
| i j l |
100 #[ false ] Array init dup ->l
100 false Array newWith dup ->l
100 loop: i [
i 100 i step: j [ l put(j, l at(j) not) ]
i 100 i step: j [ l put ( j , j l at not ) ]
]
l . ;
;

View file

@ -1 +1 @@
say "Door $_ is open" for 1..10 X** 2;
say 'Door $_ is open' for (1..10)»²;

View file

@ -1 +1 @@
say "Door $_ is ", <closed open>[.sqrt == .sqrt.floor] for 1..100;
say "Door $_ is open" for 1..10 X** 2;

View file

@ -1,26 +1 @@
sub output( @arr, $max ) {
my $output = 1;
for 1..^$max -> $index {
if @arr[$index] {
printf "%4d", $index;
say '' if $output++ %% 10;
}
}
say '';
}
sub MAIN ( Int :$doors = 100 ) {
my $doorcount = $doors + 1;
my @door[$doorcount] = 0 xx ($doorcount);
INDEX:
for 1...^$doorcount -> $index {
# flip door $index & its multiples, up to last door.
#
for ($index, * + $index ... *)[^$doors] -> $multiple {
next INDEX if $multiple > $doors;
@door[$multiple] = @door[$multiple] ?? 0 !! 1;
}
}
output @door, $doors+1;
}
say "Door $_ is ", <closed open>[.sqrt == .sqrt.floor] for 1..100;

View file

@ -0,0 +1,26 @@
sub output( @arr, $max ) {
my $output = 1;
for 1..^$max -> $index {
if @arr[$index] {
printf "%4d", $index;
say '' if $output++ %% 10;
}
}
say '';
}
sub MAIN ( Int :$doors = 100 ) {
my $doorcount = $doors + 1;
my @door[$doorcount] = 0 xx ($doorcount);
INDEX:
for 1...^$doorcount -> $index {
# flip door $index & its multiples, up to last door.
#
for ($index, * + $index ... *)[^$doors] -> $multiple {
next INDEX if $multiple > $doors;
@door[$multiple] = @door[$multiple] ?? 0 !! 1;
}
}
output @door, $doors+1;
}

View file

@ -1,3 +1,2 @@
: squared ( n-n ) dup * ;
: doors ( n- ) [ 1 repeat 2over squared > 0; drop dup squared putn space 1+ again ] do 2drop ;
100 doors
:doors (n-) [ #1 repeat dup-pair n:square gt? 0; drop dup n:square n:put sp n:inc again ] do drop-pair ;
#100 doors

View file

@ -0,0 +1,30 @@
fn main() {
mut is_open := [false].repeat(100)
// do 100 passes
for pass := 0; pass < 100; pass++ {
for door := pass; door < 100; door += pass + 1 {
// there is no NOT operator in V.
is_open[door] = match is_open[door] {
true { false }
false { true }
else { false }
}
}
}
// output results
for door := 0; door < 100; door ++ {
print( "door #" )
print( door + 1 )
print(
if is_open[door] {
" is open."
}
else {
" is closed."
}
)
println("")
}
}

View file

@ -3,6 +3,8 @@ import system'collections;
import system'dynamic;
import extensions;
// --- Expression ---
class ExpressionTree
{
object theTree;
@ -68,7 +70,7 @@ class ExpressionTree
var op := node.Operation;
^ mixin op(left).eval:right
^ op(left, right);
}
}
@ -80,8 +82,6 @@ class ExpressionTree
if (nil == node)
{ InvalidArgumentException.raise() };
var s := subjconst Leaf;
if (node.containsProperty(subjconst Leaf))
{
list.append(node.Leaf)
@ -97,6 +97,8 @@ class ExpressionTree
<= readLeaves(list,theTree);
}
// --- Game ---
class TwentyFourGame
{
object theNumbers;
@ -109,12 +111,12 @@ class TwentyFourGame
newPuzzle()
{
theNumbers := new object[]
{
1 + randomGenerator.eval:9,
1 + randomGenerator.eval:9,
1 + randomGenerator.eval:9,
1 + randomGenerator.eval:9
}
{
1 + randomGenerator.eval:9,
1 + randomGenerator.eval:9,
1 + randomGenerator.eval:9,
1 + randomGenerator.eval:9
}
}
help()

View file

@ -0,0 +1,101 @@
use Collection.Generic;
use System.Matrix;
class RPNParser {
@stk : Stack<IntHolder>;
@digits : List<IntHolder>;
function : Main(args : String[]) ~ Nil {
digits := List->New()<IntHolder>;
"Make 24 with the digits: "->Print();
for(i := 0; i < 4; i += 1;) {
n : Int := Int->Random(1, 9);
" {$n}"->Print();
digits->AddBack(n);
};
'\n'->Print();
parser := RPNParser->New();
if(parser->Parse(System.IO.Console->ReadString(), digits)) {
result := parser->GetResult();
if(result = 24) {
"Good job!"->PrintLine();
}
else {
"{$result}, Try again."->PrintLine();
};
}
else {
"Invalid sequence"->PrintLine();
};
}
New() {
@stk := Stack->New()<IntHolder>;
@digits := List->New()<IntHolder>;
}
method : Op(f : \Func->Calc) ~ Nil {
if(@stk->Size() < 2) { "Improperly written expression"->ErrorLine(); Runtime->Exit(1); };
b := @stk->Pop();
a := @stk->Pop();
@stk->Push(f(a, b));
}
method : Parse(c : Char) ~ Nil {
if(c >= '0' & c <= '9') {
value : Int := c - '0';
@stk->Push(value);
@digits->AddBack(value);
}
else if(c = '+') {
Op(\Func->Calc : (a, b) => a + b);
}
else if(c = '-') {
Op(\Func->Calc : (a, b) => a - b);
}
else if(c = '*') {
Op(\Func->Calc : (a, b) => a * b);
}
else if(c = '/') {
Op(\Func->Calc : (a, b) => { if(b <> 0) { return a / b; } else { return 0; }; });
};
}
method : GetResult() ~ Int {
if(@stk->Size() = 1) {
return @stk->Top();
};
return 0;
}
method : Parse(s : String, digits : List<IntHolder>) ~ Bool {
each(i : s) {
Parse(s->Get(i));
};
@digits->Rewind();
while(@digits->More()) {
left := @digits->Get()->Get();
digits->Rewind();
found := false;
while(digits->More() & found = false) {
right := digits->Get()->Get();
if(left = right) {
digits->Remove(); found := true;
}
else {
digits->Next();
};
};
@digits->Next();
};
return digits->IsEmpty();
}
}
alias Func {
Calc : (IntHolder, IntHolder) ~ IntHolder
}

View file

@ -0,0 +1,34 @@
import 'dart:math';
List<BigInt> partitions(int n) {
var cache = List<List<BigInt>>.filled(1, List<BigInt>.filled(1, BigInt.from(1)), growable: true);
for(int length = cache.length; length < n + 1; length++) {
var row = List<BigInt>.filled(1, BigInt.from(0), growable: true);
for(int index = 1; index < length + 1; index++) {
var partAtIndex = row[row.length - 1] + cache[length - index][min(index, length - index)];
row.add(partAtIndex);
}
cache.add(row);
}
return cache[n];
}
List<BigInt> row(int n) {
var parts = partitions(n);
return List<BigInt>.generate(n, (int index) => parts[index + 1] - parts[index]);
}
void printRows({int min = 1, int max = 11}) {
int maxDigits = max.toString().length;
print('Rows:');
for(int i in List.generate(max - min, (int index) => index + min)) {
print((' ' * (maxDigits - i.toString().length)) + '$i: ${row(i)}');
}
}
void printSums(List<int> args) {
print('Sums:');
for(int i in args) {
print('$i: ${partitions(i)[i]}');
}
}

View file

@ -0,0 +1,6 @@
import 'package:DD1_NamesOfGod/DD1_NamesOfGod.dart' as names_of_god;
main(List<String> arguments) {
names_of_god.printRows(min: 1, max: 11);
names_of_god.printSums([23, 123, 1234, 12345]);
}

View file

@ -0,0 +1,21 @@
USING: combinators io kernel math math.ranges memoize prettyprint
sequences ;
MEMO: p ( m n -- o )
{
{ [ dup zero? ] [ nip ] }
{ [ 2dup = ] [ 2drop 1 ] }
{ [ 2dup < ] [ 2drop 0 ] }
[ [ [ 1 - ] bi@ p ] [ [ - ] [ ] bi p + ] 2bi ]
} cond ;
: row ( n -- seq ) dup [1,b] [ p ] with map ;
: .row ( n -- ) row [ pprint bl ] each nl ;
: .triangle ( n -- ) [1,b] [ .row ] each ;
: G ( n -- sum ) row sum ;
25 .triangle nl
"Sums:" print { 23 123 1234 12345 } [ dup pprint bl G . ] each

View file

@ -6,11 +6,11 @@ import extensions'text;
extension bottleOp
{
bottleDescription()
= self.Printable + (self != 1).iif(" bottles"," bottle");
= self.toPrintable() + (self != 1).iif(" bottles"," bottle");
bottleEnumerator() = new Variable(self).doWith:(n)
{
^ new Enumerator:
^ new Enumerator
{
bool next() = n > 0;

View file

@ -0,0 +1,17 @@
-- An alternate version
include std/console.e
sequence howmany = {"No more bottles","%d bottle","","s"}
for beer = 99 to 1 by -1 do
display(`
[1] bottles of beer on the wall,
[1] bottles of beer.
Take one down, drink it right down,
[2][3] of beer.
`,{beer,
sprintf(howmany[(beer>1)+1],beer-1),
howmany[(beer>2)+3]
})
end for

View file

@ -19,12 +19,12 @@ end function
string this = bob(ninetynine)
string that = "Take one down, pass it around,\n"
for i=ninetynine to 0 by -1 do
puts(1,up1(this)&" on the wall,\n")
puts(1,this&".\n")
if i=0 then that = "Go to the store, buy some more,\n"
elsif i=1 then that[6..8] = "it" end if
this = bob(i-1)
puts(1,that&this&" on the wall.\n\n")
end for
if getc(0) then end if
for i=ninetynine to 0 by -1 do
puts(1,up1(this)&" on the wall,\n")
puts(1,this&".\n")
if i=0 then that = "Go to the store, buy some more,\n"
elsif i=1 then that[6..8] = "it" end if
this = bob(i-1)
puts(1,that&this&" on the wall.\n\n")
end for
{} = wait_key()

View file

@ -0,0 +1,20 @@
actor Main
let _env: Env
new create(env: Env) =>
_env = env
bottles(99)
be bottles(n: U32) =>
if n == 0 then
_env.out.print("No more bottles of beer on the wall, no more bottles of beer.")
_env.out.print("Go to the store and buy some more, 99 bottles of beer on the wall.")
else
if n == 1 then
_env.out.print("1 bottle of beer on the wall, 1 bottle of beer.")
_env.out.print("Take one down and pass it around, no more bottles of beer on the wall.\n")
else
_env.out.print(n.string() + " bottles of beer on the wall, " + n.string() + " bottles of beer.")
_env.out.print("Take one down and pass it around, "+ (n - 1).string() +" bottles of beer on the wall.\n")
end
bottles(n-1)
end

View file

@ -0,0 +1,18 @@
actor Main
let _env: Env
new create(env: Env) =>
_env = env
var n: I32 = 99
repeat
if n == 0 then
_env.out.print("No more bottles of beer on the wall, no more bottles of beer.")
_env.out.print("Go to the store and buy some more, 99 bottles of beer on the wall.")
elseif n == 1 then
_env.out.print("1 bottle of beer on the wall, 1 bottle of beer.")
_env.out.print("Take one down and pass it around, no more bottles of beer on the wall.\n")
else
_env.out.print(n.string() + " bottles of beer on the wall, " + n.string() + " bottles of beer.")
_env.out.print("Take one down and pass it around, "+ (n - 1).string() +" bottles of beer on the wall.\n")
end
n = n - 1
until n < 0 end

View file

@ -1,3 +0,0 @@
for (int i = 99; i > 0; i--) {
print(i + " bottles of beer on the wall\n" + i + " bottles of beer\nTake one down, pass it around\n" + (i - 1) + " bottles of beer on the wall\n\n");
}

View file

@ -0,0 +1,5 @@
for (int i = 99; i > 0; i--) {
print(i + " bottles of beer on the wall\n"
+ i + " bottles of beer\nTake one down, pass it around\n"
+ (i - 1) + " bottles of beer on the wall\n\n");
}

View file

@ -0,0 +1,18 @@
int i = 99;
void setup() {
size(200, 140);
}
void draw() {
background(0);
text(i + " bottles of beer on the wall\n"
+ i + " bottles of beer\nTake one down, pass it around\n"
+ (i - 1) + " bottles of beer on the wall\n\n",
10, 20);
if (frameCount%240==239) next(); // auto-advance every 4 secs
}
void mouseReleased() {
next(); // manual advance
}
void next() {
i = max(i-1, 1); // stop decreasing at 1-0 bottles
}

View file

@ -1,28 +1,10 @@
"""Pythonic 99 beer song (readability counts)."""
catchphrase = "%d bottles of beer on the wall"
regular_verse = '''\
{n} bottles of beer on the wall, {n} bottles of beer
Take one down and pass it around, {n_minus_1} bottles of beer on the wall.
strofas = ("\n".join((
catchphrase % n,
catchphrase[:18] % n,
"Take one down and pass it around",
catchphrase % (n-1)
)) for n in range(99, 0, -1))
'''
ending_verses = '''\
2 bottles of beer on the wall, 2 bottles of beer.
Take one down and pass it around, 1 bottle of beer on the wall.
1 bottle of beer on the wall, 1 bottle of beer.
Take one down and pass it around, no more bottles of beer on the wall.
No more bottles of beer on the wall, no more bottles of beer.
Go to the store and buy some more, 99 bottles of beer on the wall.
'''
# @todo: It is possible to refactor the code to avoid n-1 in the code,
# notice that the last line of any verse and the first line of the next
# verse share the same number of bottles. Nevertheless the code
# would be less readliable.
for n in range(99, 2, -1):
print(regular_verse.format(n=n, n_minus_1=n - 1))
print(ending_verses)
print("\n\n".join(strofas))

View file

@ -1,16 +1,17 @@
"""Pythonic 99 beer song (readability counts)."""
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
first = '''\
99 bottles of beer on the wall, 99 bottles of beer
'''
"""Pythonic 99 beer song (maybe the simplest naive implementation in Python 3)."""
middle = '''\
Take one down and pass it around, {n} bottles of beer on the wall.
REGULAR_VERSE = '''\
{n} bottles of beer on the wall, {n} bottles of beer
Take one down and pass it around, {n_minus_1} bottles of beer on the wall.
'''
last = '''\
ENDING_VERSES = '''\
2 bottles of beer on the wall, 2 bottles of beer.
Take one down and pass it around, 1 bottle of beer on the wall.
1 bottle of beer on the wall, 1 bottle of beer.
@ -18,9 +19,10 @@ Take one down and pass it around, no more bottles of beer on the wall.
No more bottles of beer on the wall, no more bottles of beer.
Go to the store and buy some more, 99 bottles of beer on the wall.
'''
print(first)
for n in range(98, 1, -1):
print(middle.format(n=n))
print(last)
for n in range(99, 2, -1):
print(REGULAR_VERSE.format(n=n, n_minus_1=n - 1))
print(ENDING_VERSES)

View file

@ -1,23 +1,34 @@
"""99 Bottles of Beer on the Wall made functional"""
"""
99 Bottles of Beer on the Wall made functional
Main function accepts a number of parameters, so you can specify a name of
the drink, its container and other things. English only.
"""
from functools import partial
from typing import Callable
def regular_plural(noun: str) -> str:
"""Regular rule to get the plural form of a word"""
"""English rule to get the plural form of a word"""
if noun[-1] == "s":
return noun + "es"
return noun + "s"
def beer_song(*,
location: str = 'on the wall',
distribution: str = 'Take one down, pass it around',
solution: str = 'Better go to the store to buy some more!',
container: str = 'bottle',
plurifier: Callable[[str], str] = regular_plural,
liquid: str = "beer",
initial_count: int = 99) -> None:
def beer_song(
*,
location: str = 'on the wall',
distribution: str = 'Take one down, pass it around',
solution: str = 'Better go to the store to buy some more!',
container: str = 'bottle',
plurifier: Callable[[str], str] = regular_plural,
liquid: str = "beer",
initial_count: int = 99,
) -> str:
"""
Displays the lyrics of the beer song
Return the lyrics of the beer song
:param location: initial location of the drink
:param distribution: specifies the process of its distribution
:param solution: what happens when we run out of drinks
@ -26,68 +37,92 @@ def beer_song(*,
:param liquid: the name of the drink in the given container
:param initial_count: how many containers available initially
"""
verse = partial(get_verse,
location=location,
distribution=distribution,
solution=solution,
container=container,
plurifier=plurifier,
liquid=liquid)
verse = partial(
get_verse,
initial_count = initial_count,
location = location,
distribution = distribution,
solution = solution,
container = container,
plurifier = plurifier,
liquid = liquid,
)
verses = map(verse, range(initial_count, -1, -1))
print(*verses, sep='\n\n')
return '\n\n'.join(verses)
def get_verse(count: int,
*,
location: str,
distribution: str,
solution: str,
container: str,
plurifier: Callable[[str], str],
liquid: str) -> str:
"""Returns the verse for the given initial amount of drinks"""
inventory = partial(get_inventory,
location=location)
asset = partial(get_asset,
container=container,
plurifier=plurifier,
liquid=liquid)
initial_asset = asset(count)
final_asset = asset(count - 1)
standard_verse = '\n'.join([inventory(initial_asset),
initial_asset,
distribution,
inventory(final_asset)])
return solution if count == 0 else standard_verse
def get_verse(
count: int,
*,
initial_count: str,
location: str,
distribution: str,
solution: str,
container: str,
plurifier: Callable[[str], str],
liquid: str,
) -> str:
"""Returns the verse for the given amount of drinks"""
asset = partial(
get_asset,
container = container,
plurifier = plurifier,
liquid = liquid,
)
current_asset = asset(count)
next_number = count - 1 if count else initial_count
next_asset = asset(next_number)
action = distribution if count else solution
inventory = partial(
get_inventory,
location = location,
)
return '\n'.join((
inventory(current_asset),
current_asset,
action,
inventory(next_asset),
))
def get_inventory(asset: str,
*,
location: str) -> str:
def get_inventory(
asset: str,
*,
location: str,
) -> str:
"""
Used to return the first or the fourth line of the verse
>>> get_inventory("10 bottles of beer", location="on the wall")
"10 bottles of beer on the wall"
"""
return ' '.join([asset, location])
return ' '.join((asset, location))
def get_asset(count: int,
*,
container: str,
plurifier: Callable[[str], str],
liquid: str) -> str:
def get_asset(
count: int,
*,
container: str,
plurifier: Callable[[str], str],
liquid: str,
) -> str:
"""
Quantified asset
>>> get_asset(0, container="jar", plurifier=regular_plural, liquid='milk')
"No more jars of milk"
"""
containers = container if count == 1 else plurifier(container)
spelled_out_quantity = "No more" if count == 0 else str(count)
return ' '.join([spelled_out_quantity, containers, "of", liquid])
containers = plurifier(container) if count != 1 else container
spelled_out_quantity = str(count) if count else "No more"
return ' '.join((spelled_out_quantity, containers, "of", liquid))
if __name__ == '__main__':
beer_song()
print(beer_song())

View file

@ -0,0 +1,256 @@
"""
Excercise of style. An overkill for the task :-D
1. OOP, with abstract class and implementation with much common magic methods
2. you can customize:
a. the initial number
b. the name of the item and its plural
c. the string to display when there's no more items
d. the normal action
e. the final action
f. the template used, for foreign languages
3. strofas of the song are created with multiprocessing
4. when you launch it as a script, you can specify an optional parameter for
the number of initial items
"""
from string import Template
from abc import ABC, abstractmethod
from multiprocessing.pool import Pool as ProcPool
from functools import partial
import sys
class Song(ABC):
@abstractmethod
def sing(self):
"""
it must return the song as a text-like object
"""
pass
class MuchItemsSomewhere(Song):
eq_attrs = (
"initial_number",
"zero_items",
"action1",
"action2",
"item",
"items",
"strofa_tpl"
)
hash_attrs = eq_attrs
repr_attrs = eq_attrs
__slots__ = eq_attrs + ("_repr", "_hash")
def __init__(
self,
items = "bottles of beer",
item = "bottle of beer",
where = "on the wall",
initial_number = None,
zero_items = "No more",
action1 = "Take one down, pass it around",
action2 = "Go to the store, buy some more",
template = None,
):
initial_number_true = 99 if initial_number is None else initial_number
try:
is_initial_number_int = (initial_number_true % 1) == 0
except Exception:
is_initial_number_int = False
if not is_initial_number_int:
raise ValueError("`initial_number` parameter must be None or a int-like object")
if initial_number_true < 0:
raise ValueError("`initial_number` parameter must be >=0")
true_tpl = template or """\
$i $items1 $where
$i $items1
$action
$j $items2 $where"""
strofa_tpl_tmp = Template(true_tpl)
strofa_tpl = Template(strofa_tpl_tmp.safe_substitute(where=where))
self.zero_items = zero_items
self.action1 = action1
self.action2 = action2
self.initial_number = initial_number_true
self.item = item
self.items = items
self.strofa_tpl = strofa_tpl
self._hash = None
self._repr = None
def strofa(self, number):
zero_items = self.zero_items
item = self.item
items = self.items
if number == 0:
i = zero_items
action = self.action2
j = self.initial_number
else:
i = number
action = self.action1
j = i - 1
if i == 1:
items1 = item
j = zero_items
else:
items1 = items
if j == 1:
items2 = item
else:
items2 = items
return self.strofa_tpl.substitute(
i = i,
j = j,
action = action,
items1 = items1,
items2 = items2
)
def sing(self):
with ProcPool() as proc_pool:
strofa = self.strofa
initial_number = self.initial_number
args = range(initial_number, -1, -1)
return "\n\n".join(proc_pool.map(strofa, args))
def __copy__(self, *args, **kwargs):
return self
def __deepcopy__(self, *args, **kwargs):
return self
def __eq__(self, other, *args, **kwargs):
if self is other:
return True
getmyattr = partial(getattr, self)
getotherattr = partial(getattr, other)
eq_attrs = self.eq_attrs
for attr in eq_attrs:
val = getmyattr(attr)
try:
val2 = getotherattr(attr)
except Exception:
return False
if attr == "strofa_tpl":
val_true = val.safe_substitute()
val2_true = val.safe_substitute()
else:
val_true = val
val2_true = val
if val_true != val2_true:
return False
return True
def __hash__(self, *args, **kwargs):
_hash = self._hash
if _hash is None:
getmyattr = partial(getattr, self)
attrs = self.hash_attrs
hash_true = self._hash = hash(tuple(map(getmyattr, attrs)))
else:
hash_true = _hash
return hash_true
def __repr__(self, *args, **kwargs):
_repr = self._repr
if _repr is None:
repr_attrs = self.repr_attrs
getmyattr = partial(getattr, self)
attrs = []
for attr in repr_attrs:
val = getmyattr(attr)
if attr == "strofa_tpl":
val_true = val.safe_substitute()
else:
val_true = val
attrs.append(f"{attr}={repr(val_true)}")
repr_true = self._repr = f"{self.__class__.__name__}({', '.join(attrs)})"
else:
repr_true = _repr
return repr_true
def muchBeersOnTheWall(num):
song = MuchItemsSomewhere(initial_number=num)
return song.sing()
def balladOfProgrammer(num):
"""
Prints
"99 Subtle Bugs in Production"
or
"The Ballad of Programmer"
"""
song = MuchItemsSomewhere(
initial_number = num,
items = "subtle bugs",
item = "subtle bug",
where = "in Production",
action1 = "Debug and catch, commit a patch",
action2 = "Release the fixes, wait for some tickets",
zero_items = "Zarro",
)
return song.sing()
def main(num):
print(f"### {num} Bottles of Beers on the Wall ###")
print()
print(muchBeersOnTheWall(num))
print()
print()
print('### "The Ballad of Programmer", by Marco Sulla')
print()
print(balladOfProgrammer(num))
if __name__ == "__main__":
# Ok, argparse is **really** too much
argv = sys.argv
if len(argv) == 1:
num = None
elif len(argv) == 2:
try:
num = int(argv[1])
except Exception:
raise ValueError(
f"{__file__} parameter must be an integer, or can be omitted"
)
else:
raise RuntimeError(f"{__file__} takes one parameter at max")
main(num)
__all__ = (Song.__name__, MuchItemsSomewhere.__name__, muchBeersOnTheWall.__name__, balladOfProgrammer.__name__)

View file

@ -1,2 +1 @@
as -o ab.o ab.S
ld -o a.out ab.o
arm-linux-gnueabi-as src.s -o src.o && arm-linux-gnueabi-gcc -static src.o -o run && qemu-arm run

View file

@ -1,513 +1,27 @@
.data
.align 2
.code 32
.section .rodata
.align 2
.code 32
overflow_msg: .ascii "Invalid number. Overflow.\n"
overflow_msglen = . - overflow_msg
bad_input_msg: .ascii "Invalid input. NaN.\n"
bad_input_msglen = . - bad_input_msg
range_err_msg: .ascii "Value out of range.\n"
range_err_msglen = . - range_err_msg
io_error_msg: .ascii "I/O error.\n"
io_error_msglen = . - range_err_msg
sys_exit = 1
sys_read = 3
sys_write = 4
max_rd_buf = 14
lf = 10
m10_9 = 0x3b9aca00
maxval = 1000
minval = -1000
.text
.global main
.extern printf
.extern scanf
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@ void main()
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
.align 2
.code 32
.type _start STT_FUNC
.global _start
_start:
stmfd sp!, {r4,r5,lr}
main:
push {lr}
ldr r0, =scanf_lit
ldr r1, =num_a
ldr r2, =num_b
bl scanf // scanf("%d %d", &num_a, &num_b);
ldr r0, =printf_lit
ldr r1, =num_a
ldr r1, [r1]
ldr r2, =num_b
ldr r2, [r2]
add r1, r1, r2
bl printf // printf("%d\n", num_a + num_b);
pop {pc}
.read_lhs:
ldr r0, =max_rd_buf
bl readint
mov r4, r0
bl printint
mov r0, r4
bl range_check
.read_rhs:
ldr r0, =max_rd_buf
bl readint
mov r5, r0
bl printint
mov r0, r5
bl range_check
.sum_and_print:
adds r0, r4, r5
bvs overflow
bl printint
.main_exit:
mov r0, #0
bl exit
ldmfd sp!, {r4,r5,pc}
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@ Read from stdin until we encounter a non-digit, or we have read bytes2rd digits.
@@ Ignore leading spaces.
@@ Return value to the caller converted to a signed int.
@@ We read positive values, but if we read a leading '-' sign, we convert the
@@ return value to two's complement.
@@ The argument is max number of bytes to read from stdin.
@@ int readint(int bytes2rd)
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
.align 2
.code 32
.type readint STT_FUNC
.global readint
readint:
stmfd sp!, {r4,r5,r6,r7,lr}
@@@@@@@@@@@@@@@
@@ r0 : #0 for stdin arg to read.
@@ r1 : ptr to current pos in local buffer.
@@ r2 : #1 to read one byte at a time.
@@ r3,r7 : tmp.
@@ r4 : number of bytes read.
@@ r5 : value of current byte.
@@ r6 : 0 while we are reading leading spaces.
@@@@@@@@@@@@@@@
sub sp, sp, r0
mov r1, sp
mov r3, #0
push {r3} @ sp,#4: local var @isnegative. return in r1. Default value is 0/false. Positive number.
push {r0} @ sp,#0: local var @maxbytes. const.
mov r2, #1
mov r4, #0
mov r6, #0
b .rd
@ we get here if r6 is 0.
@ if space, goto .rd.
@ else set r6 to 1 and goto .noleading.
.leadchk:
mov r0, r5
bl isspace
cmp r0, #1
beq .rd
.sign_chk:
mov r0, r5
push {r1}
bl issign
cmp r0, #1
streq r0, [sp,#8] @ sp,#4 + 4 for the pushed r1.
movhi r1, #0
strhi r1, [sp,#8] @ sp,#4 + 4 for the pushed r1.
pop {r1}
bhs .rd
mov r6, #1
b .noleading
.rd:
mov r0, #0
bl read
cmp r0, #1
bne .sum_digits_eof @ eof
mov r5, #0
ldrb r5, [r1]
cmp r6, #0
beq .leadchk
.noleading:
mov r0, r5
bl isdigit
cmp r0, #1
bne .sum_digits_nan @ r5 is non-digit
add r4, r4, #1
add r1, r1, #1
@ max chars to read is received in arg[0], stored in local var at sp.
@ Only 10 can be valid, so the default of 12 leaves space for separator.
ldr r3, [sp]
cmp r4, r3
beq .sum_digits_maxrd @ max bytes read.
b .rd
@@@@@@@@@@@@@@@
@ We have read r4 (0..arg[0](default 12)) digits when we get here. Go through them
@ and add/mul them together to calculate a number.
@ We multiply and add the digits in reverse order to simplify the multiplication.
@@@@@@@@@@@@@@@
@ r0: return value.
@ r1: local variable for read buffer.
@ r2: tmp for conversion.
@ r3,r6,r7: tmp
@ r4: number of chars we have read.
@ r5: multiplier 1,10,100.
@@@@@@@@@@@@@@@
.sum_digits_nan:
mov r0, r5
bl isspace
cmp r0, #1
bne bad_input
.sum_digits_maxrd:
.sum_digits_eof:
mov r0, #0
mov r5, #1
.count:
cmp r4, #0
beq .readint_ret
sub r4, r4, #1
sub r1, #1
ldrb r2, [r1]
sub r2, r2, #48
mov r3, r2
@ multiply r3 (char value of digit) with r5 (multiplier).
@ possible overflow.
@ MI means negative.
@ smulls multiples two signed 32 bit vals and returns a 64 bit result.
@ If we get anything in r7, the value has overflowed.
@ having r2[31] set is overflow too.
smulls r2, r7, r3, r5
cmp r7, #0
bne overflow
cmp r2, #0
bmi overflow
@@ possible overflow.
adds r0, r0, r2
bvs overflow
bmi overflow
@@ end of array check.
@@ check is needed here too, for large numbers, since 10 billion is not a valid 32 bit val.
cmp r4, #0
beq .readint_ret
@@ multiple multiplier by 10.
@@ possible overflow.
@@ too many digits is input. happens if input is more than 10 digits.
mov r3, #10
mov r6, r5
smulls r5, r7, r3, r6
cmp r7, #0
bne overflow
cmp r5, #0
bmi overflow
b .count
.readint_ret:
ldr r1, [sp,#4] @ read isnegative value.
cmp r1, #0
rsbne r0, r0, #0
pop {r2}
add sp, sp, #4
add sp, sp, r2
ldmfd sp!, {r4,r5,r6,r7,pc}
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@ int isdigit(int)
@@ #48..#57 ascii range for '0'..'9'.
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
.align 2
.code 32
.type isdigit STT_FUNC
.global isdigit
isdigit:
stmfd sp!, {r1,lr}
cmp r0, #48
blo .o_range
cmp r0, #57
bhi .o_range
mov r0, #1
ldmfd sp!, {r1,pc}
.o_range:
mov r0, #0
ldmfd sp!, {r1,pc}
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@ int isspace(int)
@@ ascii space = 32, tab = 9, newline 10, cr = 13.
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
.align 2
.code 32
.type isspace STT_FUNC
.global isspace
isspace:
stmfd sp!, {lr}
cmp r0, #32
cmpne r0, #9
cmpne r0, #10
cmpne r0, #13
beq .is_space
mov r0, #0
ldmfd sp!, {pc}
.is_space:
mov r0, #1
ldmfd sp!, {pc}
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@ Return value is 1 for '-' 2 for '+'.
@@ int isspace(int)
@@ '+' = 43 and '-' = 45.
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
.align 2
.code 32
.type issign STT_FUNC
.global issign
issign:
stmfd sp!, {lr}
cmp r0, #43
beq .plus_sign
cmp r0, #45
beq .minus_sign
mov r0, #0
ldmfd sp!, {pc}
.plus_sign:
mov r0, #2
ldmfd sp!, {pc}
.minus_sign:
mov r0, #1
ldmfd sp!, {pc}
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@ ARGS:
@@ r0 : in out arg (current int value)
@@ r1 : in out arg (ptr to current pos in buffer)
@@ r2 : in arg (const increment. 1000_000_000, 100_000_000, 10_000_000, 1000_000, 100_000, 10_000, 1000, 100, 10, 1.)
@@
@@ r4 : tmp local. Outer scope must init to #10 and count down to #0.
@@ Special case is INTMAX. Must init to 5 if r4 >= 1000_000_000 (0x3b9aca00 = m10_9).
@@ r5: tmp
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
.align 2
.code 32
.type get_digit STT_FUNC
.global get_digit
get_digit:
stmfd sp!, {r2,r4,r5,lr}
ldr r5, =m10_9
cmp r2, r5
movlo r4, #10
movhs r4, #5
.get_digit_loop:
sub r4, #1
mul r5, r4, r2
cmp r0, r5
blo .get_digit_loop
sub r0, r5
add r4, r4, #48
strb r4, [r1], #1
ldmfd sp!, {r2,r4,r5,pc}
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@ A quick way to divide (numbers evenly divisible by 10) by 10.
@@ Most ARM cpus don't have a divide instruction,
@@ so this will always work.
@@ A generic div function is long and not needed here.
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
.align 2
.div_r2_10:
stmfd sp!, {r0,r1,r3,lr}
mov r0, #1
mov r1, #10
.find_x:
mul r3, r0, r1;
cmp r3, r2
movlo r0, r3
blo .find_x
mov r2, r0
ldmfd sp!, {r0,r1,r3,pc}
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
.align 2
.print_neg_sign:
stmfd sp!, {r0,r1,r2,lr}
@ 45 = '-'
mov r1, #45
push {r1}
mov r2, #1
@ r1 is ptr to our local variable (holding '-').
mov r1, sp
mov r0, #1
bl write
cmp r0, #0
blne io_error
pop {r1}
ldmfd sp!, {r0,r1,r2,pc}
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@ void printint(int val)
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
.align 2
.code 32
.type printint STT_FUNC
.global printint
printint:
stmfd sp!, {r4,r5,r6,lr}
mov r1, #1
ands r1, r1, r0, LSR #31
rsbne r0, r0, #0
blne .print_neg_sign
sub sp, sp, #20
mov r1, sp
mov r3, sp
ldr r2, =m10_9
.getc_loop:
bl get_digit
cmp r2, #1
beq .exit_getc_loop
bl .div_r2_10
b .getc_loop
.exit_getc_loop:
ldr r0, =lf
strb r0, [r1], #1
sub r2, r1, r3
mov r1, r3
mov r0, #1
bl write
cmp r0, #0
blne io_error
add sp, sp, #20
ldmfd sp!, {r4,r5,r6,pc}
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
.align 2
range_check:
stmfd sp!, {r4,r5,lr}
ldr r4, =minval
ldr r5, =maxval
cmp r4, #0
cmpeq r5, #0
beq .skip_range_check
cmp r0, r4
bllt range_err
cmp r0, r5
blgt range_err
.skip_range_check:
ldmfd sp!, {r4,r5,pc}
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ void range_err()
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
.align 2
range_err:
stmfd sp!, {lr}
ldr r2, =range_err_msglen
ldr r1, =range_err_msg
mov r0, #2
bl write
mov r0, #-1
bl exit
ldmfd sp!, {pc}
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ void overflow()
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
.align 2
overflow:
stmfd sp!, {lr}
ldr r2, =overflow_msglen
ldr r1, =overflow_msg
mov r0, #2
bl write
mov r0, #-1
bl exit
ldmfd sp!, { pc}
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ void bad_input()
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
.align 2
bad_input:
stmfd sp!, {lr}
ldr r2, =bad_input_msglen
ldr r1, =bad_input_msg
mov r0, #2
bl write
mov r0, #-1
bl exit
ldmfd sp!, {pc}
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ void io_error()
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
.align 2
io_error:
stmfd sp!, {lr}
ldr r2, =io_error_msglen
ldr r1, =io_error_msg
mov r0, #2
bl write
mov r0, #-1
bl exit
ldmfd sp!, {pc}
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ void exit(int)
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
.align 2
.code 32
.type _start STT_FUNC
.global exit
exit:
stmfd sp!, {r7, lr}
ldr r7, =sys_exit
svc #0
ldmfd sp!, {r7, pc}
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ int write(int fd,char*buf,int len)
@ Return 0 if we successfully write all bytes. Otherwise return the error code.
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
.align 2
.code 32
.type _start STT_FUNC
.global write
write:
stmfd sp!, {r4,r7, lr}
mov r4, r2
.wr_loop:
ldr r7, =sys_write
svc #0
@ If r0 is negative, it is more than r4 with LO (unsigned <).
cmp r0, r4
sublo r4, r0
blo .wr_loop
moveq r0, #0
ldmfd sp!, {r4,r7, pc}
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ int read(int fd,char*buf,int len)
@ Return number of bytes successfully read. Ignore errors.
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
.align 2
.code 32
.type _start STT_FUNC
.global read
read:
stmfd sp!, {r7, lr}
ldr r7, =sys_read
svc #0
cmp r0, #0
movlt r0, #0
ldmfd sp!, {r7, pc}
.data
scanf_lit: .asciz "%d %d"
printf_lit: .asciz "%d\n"
.align 4
.bss
num_a: .skip 4
num_b: .skip 4

View file

@ -0,0 +1,2 @@
as -o ab.o ab.S
ld -o a.out ab.o

View file

@ -0,0 +1,513 @@
.data
.align 2
.code 32
.section .rodata
.align 2
.code 32
overflow_msg: .ascii "Invalid number. Overflow.\n"
overflow_msglen = . - overflow_msg
bad_input_msg: .ascii "Invalid input. NaN.\n"
bad_input_msglen = . - bad_input_msg
range_err_msg: .ascii "Value out of range.\n"
range_err_msglen = . - range_err_msg
io_error_msg: .ascii "I/O error.\n"
io_error_msglen = . - range_err_msg
sys_exit = 1
sys_read = 3
sys_write = 4
max_rd_buf = 14
lf = 10
m10_9 = 0x3b9aca00
maxval = 1000
minval = -1000
.text
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@ void main()
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
.align 2
.code 32
.type _start STT_FUNC
.global _start
_start:
stmfd sp!, {r4,r5,lr}
.read_lhs:
ldr r0, =max_rd_buf
bl readint
mov r4, r0
bl printint
mov r0, r4
bl range_check
.read_rhs:
ldr r0, =max_rd_buf
bl readint
mov r5, r0
bl printint
mov r0, r5
bl range_check
.sum_and_print:
adds r0, r4, r5
bvs overflow
bl printint
.main_exit:
mov r0, #0
bl exit
ldmfd sp!, {r4,r5,pc}
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@ Read from stdin until we encounter a non-digit, or we have read bytes2rd digits.
@@ Ignore leading spaces.
@@ Return value to the caller converted to a signed int.
@@ We read positive values, but if we read a leading '-' sign, we convert the
@@ return value to two's complement.
@@ The argument is max number of bytes to read from stdin.
@@ int readint(int bytes2rd)
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
.align 2
.code 32
.type readint STT_FUNC
.global readint
readint:
stmfd sp!, {r4,r5,r6,r7,lr}
@@@@@@@@@@@@@@@
@@ r0 : #0 for stdin arg to read.
@@ r1 : ptr to current pos in local buffer.
@@ r2 : #1 to read one byte at a time.
@@ r3,r7 : tmp.
@@ r4 : number of bytes read.
@@ r5 : value of current byte.
@@ r6 : 0 while we are reading leading spaces.
@@@@@@@@@@@@@@@
sub sp, sp, r0
mov r1, sp
mov r3, #0
push {r3} @ sp,#4: local var @isnegative. return in r1. Default value is 0/false. Positive number.
push {r0} @ sp,#0: local var @maxbytes. const.
mov r2, #1
mov r4, #0
mov r6, #0
b .rd
@ we get here if r6 is 0.
@ if space, goto .rd.
@ else set r6 to 1 and goto .noleading.
.leadchk:
mov r0, r5
bl isspace
cmp r0, #1
beq .rd
.sign_chk:
mov r0, r5
push {r1}
bl issign
cmp r0, #1
streq r0, [sp,#8] @ sp,#4 + 4 for the pushed r1.
movhi r1, #0
strhi r1, [sp,#8] @ sp,#4 + 4 for the pushed r1.
pop {r1}
bhs .rd
mov r6, #1
b .noleading
.rd:
mov r0, #0
bl read
cmp r0, #1
bne .sum_digits_eof @ eof
mov r5, #0
ldrb r5, [r1]
cmp r6, #0
beq .leadchk
.noleading:
mov r0, r5
bl isdigit
cmp r0, #1
bne .sum_digits_nan @ r5 is non-digit
add r4, r4, #1
add r1, r1, #1
@ max chars to read is received in arg[0], stored in local var at sp.
@ Only 10 can be valid, so the default of 12 leaves space for separator.
ldr r3, [sp]
cmp r4, r3
beq .sum_digits_maxrd @ max bytes read.
b .rd
@@@@@@@@@@@@@@@
@ We have read r4 (0..arg[0](default 12)) digits when we get here. Go through them
@ and add/mul them together to calculate a number.
@ We multiply and add the digits in reverse order to simplify the multiplication.
@@@@@@@@@@@@@@@
@ r0: return value.
@ r1: local variable for read buffer.
@ r2: tmp for conversion.
@ r3,r6,r7: tmp
@ r4: number of chars we have read.
@ r5: multiplier 1,10,100.
@@@@@@@@@@@@@@@
.sum_digits_nan:
mov r0, r5
bl isspace
cmp r0, #1
bne bad_input
.sum_digits_maxrd:
.sum_digits_eof:
mov r0, #0
mov r5, #1
.count:
cmp r4, #0
beq .readint_ret
sub r4, r4, #1
sub r1, #1
ldrb r2, [r1]
sub r2, r2, #48
mov r3, r2
@ multiply r3 (char value of digit) with r5 (multiplier).
@ possible overflow.
@ MI means negative.
@ smulls multiples two signed 32 bit vals and returns a 64 bit result.
@ If we get anything in r7, the value has overflowed.
@ having r2[31] set is overflow too.
smulls r2, r7, r3, r5
cmp r7, #0
bne overflow
cmp r2, #0
bmi overflow
@@ possible overflow.
adds r0, r0, r2
bvs overflow
bmi overflow
@@ end of array check.
@@ check is needed here too, for large numbers, since 10 billion is not a valid 32 bit val.
cmp r4, #0
beq .readint_ret
@@ multiple multiplier by 10.
@@ possible overflow.
@@ too many digits is input. happens if input is more than 10 digits.
mov r3, #10
mov r6, r5
smulls r5, r7, r3, r6
cmp r7, #0
bne overflow
cmp r5, #0
bmi overflow
b .count
.readint_ret:
ldr r1, [sp,#4] @ read isnegative value.
cmp r1, #0
rsbne r0, r0, #0
pop {r2}
add sp, sp, #4
add sp, sp, r2
ldmfd sp!, {r4,r5,r6,r7,pc}
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@ int isdigit(int)
@@ #48..#57 ascii range for '0'..'9'.
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
.align 2
.code 32
.type isdigit STT_FUNC
.global isdigit
isdigit:
stmfd sp!, {r1,lr}
cmp r0, #48
blo .o_range
cmp r0, #57
bhi .o_range
mov r0, #1
ldmfd sp!, {r1,pc}
.o_range:
mov r0, #0
ldmfd sp!, {r1,pc}
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@ int isspace(int)
@@ ascii space = 32, tab = 9, newline 10, cr = 13.
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
.align 2
.code 32
.type isspace STT_FUNC
.global isspace
isspace:
stmfd sp!, {lr}
cmp r0, #32
cmpne r0, #9
cmpne r0, #10
cmpne r0, #13
beq .is_space
mov r0, #0
ldmfd sp!, {pc}
.is_space:
mov r0, #1
ldmfd sp!, {pc}
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@ Return value is 1 for '-' 2 for '+'.
@@ int isspace(int)
@@ '+' = 43 and '-' = 45.
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
.align 2
.code 32
.type issign STT_FUNC
.global issign
issign:
stmfd sp!, {lr}
cmp r0, #43
beq .plus_sign
cmp r0, #45
beq .minus_sign
mov r0, #0
ldmfd sp!, {pc}
.plus_sign:
mov r0, #2
ldmfd sp!, {pc}
.minus_sign:
mov r0, #1
ldmfd sp!, {pc}
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@ ARGS:
@@ r0 : in out arg (current int value)
@@ r1 : in out arg (ptr to current pos in buffer)
@@ r2 : in arg (const increment. 1000_000_000, 100_000_000, 10_000_000, 1000_000, 100_000, 10_000, 1000, 100, 10, 1.)
@@
@@ r4 : tmp local. Outer scope must init to #10 and count down to #0.
@@ Special case is INTMAX. Must init to 5 if r4 >= 1000_000_000 (0x3b9aca00 = m10_9).
@@ r5: tmp
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
.align 2
.code 32
.type get_digit STT_FUNC
.global get_digit
get_digit:
stmfd sp!, {r2,r4,r5,lr}
ldr r5, =m10_9
cmp r2, r5
movlo r4, #10
movhs r4, #5
.get_digit_loop:
sub r4, #1
mul r5, r4, r2
cmp r0, r5
blo .get_digit_loop
sub r0, r5
add r4, r4, #48
strb r4, [r1], #1
ldmfd sp!, {r2,r4,r5,pc}
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@ A quick way to divide (numbers evenly divisible by 10) by 10.
@@ Most ARM cpus don't have a divide instruction,
@@ so this will always work.
@@ A generic div function is long and not needed here.
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
.align 2
.div_r2_10:
stmfd sp!, {r0,r1,r3,lr}
mov r0, #1
mov r1, #10
.find_x:
mul r3, r0, r1;
cmp r3, r2
movlo r0, r3
blo .find_x
mov r2, r0
ldmfd sp!, {r0,r1,r3,pc}
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
.align 2
.print_neg_sign:
stmfd sp!, {r0,r1,r2,lr}
@ 45 = '-'
mov r1, #45
push {r1}
mov r2, #1
@ r1 is ptr to our local variable (holding '-').
mov r1, sp
mov r0, #1
bl write
cmp r0, #0
blne io_error
pop {r1}
ldmfd sp!, {r0,r1,r2,pc}
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@ void printint(int val)
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
.align 2
.code 32
.type printint STT_FUNC
.global printint
printint:
stmfd sp!, {r4,r5,r6,lr}
mov r1, #1
ands r1, r1, r0, LSR #31
rsbne r0, r0, #0
blne .print_neg_sign
sub sp, sp, #20
mov r1, sp
mov r3, sp
ldr r2, =m10_9
.getc_loop:
bl get_digit
cmp r2, #1
beq .exit_getc_loop
bl .div_r2_10
b .getc_loop
.exit_getc_loop:
ldr r0, =lf
strb r0, [r1], #1
sub r2, r1, r3
mov r1, r3
mov r0, #1
bl write
cmp r0, #0
blne io_error
add sp, sp, #20
ldmfd sp!, {r4,r5,r6,pc}
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
.align 2
range_check:
stmfd sp!, {r4,r5,lr}
ldr r4, =minval
ldr r5, =maxval
cmp r4, #0
cmpeq r5, #0
beq .skip_range_check
cmp r0, r4
bllt range_err
cmp r0, r5
blgt range_err
.skip_range_check:
ldmfd sp!, {r4,r5,pc}
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ void range_err()
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
.align 2
range_err:
stmfd sp!, {lr}
ldr r2, =range_err_msglen
ldr r1, =range_err_msg
mov r0, #2
bl write
mov r0, #-1
bl exit
ldmfd sp!, {pc}
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ void overflow()
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
.align 2
overflow:
stmfd sp!, {lr}
ldr r2, =overflow_msglen
ldr r1, =overflow_msg
mov r0, #2
bl write
mov r0, #-1
bl exit
ldmfd sp!, { pc}
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ void bad_input()
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
.align 2
bad_input:
stmfd sp!, {lr}
ldr r2, =bad_input_msglen
ldr r1, =bad_input_msg
mov r0, #2
bl write
mov r0, #-1
bl exit
ldmfd sp!, {pc}
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ void io_error()
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
.align 2
io_error:
stmfd sp!, {lr}
ldr r2, =io_error_msglen
ldr r1, =io_error_msg
mov r0, #2
bl write
mov r0, #-1
bl exit
ldmfd sp!, {pc}
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ void exit(int)
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
.align 2
.code 32
.type _start STT_FUNC
.global exit
exit:
stmfd sp!, {r7, lr}
ldr r7, =sys_exit
svc #0
ldmfd sp!, {r7, pc}
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ int write(int fd,char*buf,int len)
@ Return 0 if we successfully write all bytes. Otherwise return the error code.
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
.align 2
.code 32
.type _start STT_FUNC
.global write
write:
stmfd sp!, {r4,r7, lr}
mov r4, r2
.wr_loop:
ldr r7, =sys_write
svc #0
@ If r0 is negative, it is more than r4 with LO (unsigned <).
cmp r0, r4
sublo r4, r0
blo .wr_loop
moveq r0, #0
ldmfd sp!, {r4,r7, pc}
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ int read(int fd,char*buf,int len)
@ Return number of bytes successfully read. Ignore errors.
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
.align 2
.code 32
.type _start STT_FUNC
.global read
read:
stmfd sp!, {r7, lr}
ldr r7, =sys_read
svc #0
cmp r0, #0
movlt r0, #0
ldmfd sp!, {r7, pc}

View file

@ -1,4 +1,4 @@
dim a(2)
input "Enter two numbers separated by a space?", t$
a = explode(t$," ")
print t$ + " " + (a[0] + a[1])
print t$ & " " & int(a[0]) + int(a[1])

View file

@ -0,0 +1,108 @@
[A + B for Rosetta Code.
Read two integers and find their sum.
EDSAC program, Initial Orders 2.]
[Print signed number, up to 10 digits, right-justified.
Modification of library subroutine P7.
55 locations, load at even address.]
T 56 K
GKA3FT42@A47@T31@ADE10@T31@A48@T31@SDTDH44#@NDYFLDT4DS43@TF
H17@S17@A43@G23@UFS43@T1FV4DAFG50@SFLDUFXFOFFFSFL4FT4DA49@T31@
A1FA43@G20@XFP1024FP610D@524D!FO46@O26@XFO46@SFL8FT4DE39@
[Subroutine to read signed number from input, up to 10 digits.
Partly based on library subroutine R2. Result in 4D.
Working registers: 0F = dump to clear acc
1F < 0 if number starts with minus, = 0 if not.
6D = character code, as double-word value]
T 120 K
G K
A 3 F [make link for return]
T 36 @ [plant in code; clear acc]
H 7 @ [mult reg := 10/32]
T 4 D [initialize result to 0]
T 1 F [no minus sign yet]
T 6 D [ensure 7F and sandwich bit are 0]
[Loop until find valid first character of integer, namely
decimal digit (char codes 0..9), plus (13), or minus (22).]
[6] I 6 F [char code from input]
[7] T F [clear acc; also serves as constant 10/32]
S 6 F [load negative of char code]
A 39 @ [add 9]
E 24 @ [if decimal digit, out]
A 38 @ [add 3]
E 6 @ [if 10..12, try again]
A 37 @ [add 1]
E 20 @ [if plus, out with acc = 0]
A 39 @ [add 9]
G 6 @ [if 23..31, try again]
S 37 @ [subtract 1]
E 6 @ [if 14..21, try again]
T 1 F [minus, acc = -1, store in sign]
[Loop to read characters after first. Assumes acc = 0 here.]
[20] I 6 F [next char from input]
S 6 F [negative to acc]
A 39 @ [add 9]
G 30 @ [finished if not digit]
[24] T F [clear acc]
V 4 D [acc := 10/32 times partial sum]
L 8 F [shift 5 left]
A 6 D [add latest digit]
T 4 D [update partial sum]
E 20 @ [loop for next char]
[Here when no more digits]
[30] T F [clear acc]
A 1 F [load sign of result]
E 36 @ [exit (with acc = 0) if >= 0]
T F [< 0, clear acc]
S 4 D [subtract number]
T 4 D [store back negated; clear acc]
[36] E F [exit with acc = 0 (EDSAC convention)]
[Constants]
[37] P D [1]
[38] P 1 D [3]
[39] P 4 D [9]
[Main routine]
T 200 K
G K
[Variables]
[0] P F P F [integer A]
[2] P F P F [integer B]
[Constants]
[4] # F [figures]
[5] @ F [carriage return]
[6] & F [line feed]
[7] K 4096 F [null char]
[Enter with acc = 0]
[8] O 4 @ [set teleprinter to figures]
A 9 @
G 120 F [read integer A from input]
A 4 D [load]
U #@ [save]
T D [to 0D for printing]
A 14 @
G 56 F [print A]
O 5 @ [followed by new line]
O 6 @
A 18 @
G 120 F [read integer B from input]
A 4 D [load]
U 2#@ [save]
T D [to 0D for printing]
A 23 @
G 56 F [print B]
O 5 @ [followed by new line]
O 6 @
A #@ [load A]
A 2#@ [add B]
T D [A + B to 0D for printing]
A 30 @
G 56 F [print A + B]
O 5 @ [followed by new line]
O 6 @
O 7 @ [print null to flush teleprinter buffer]
Z F [stop]
E 8 Z
P F
-987.123.

View file

@ -2,8 +2,8 @@ import extensions;
public program()
{
var A := new Integer();
var B := new Integer();
var A := Integer.new();
var B := Integer.new();
console.loadLine(A,B).printLine(A + B)
}

View file

@ -5,6 +5,6 @@ public program()
{
console.printLine(console.readLine()
.split()
.selectBy(__mssg toInt<convertorOp>[0])
.selectBy(mssgconst toInt<convertorOp>[1])
.summarize())
}

View file

@ -1,4 +1,4 @@
import java.util.*;
import java.util.Scanner;
public class Sum2 {
public static void main(String[] args) {

View file

@ -0,0 +1,15 @@
(:
Using the EXPath File Module, which is built into most XQuery processors
by default and thus does not need to get imported. Some processors bind the
namespace automatically, others require explicit declaration.
:)
xquery version "3.1";
declare namespace file = 'http://expath.org/ns/file';
let $in := 'input.txt'
let $out := 'output.txt'
let $numbers := tokenize(file:read-text($in))
let $result := xs:numeric($numbers[1]) + xs:numeric($numbers[2])
return file:write-text($out, xs:string($result))

View file

@ -28,12 +28,12 @@ extension op
public program()
{
var blocks := new object[] {"BO", "XK", "DQ", "CP", "NA",
var blocks := new string[]{"BO", "XK", "DQ", "CP", "NA",
"GT", "RE", "TG", "QD", "FS",
"JW", "HU", "VI", "AN", "OB",
"ER", "FS", "LY", "PC", "ZM"};
var words := new object[] {"", "A", "BARK", "BOOK", "TREAT", "COMMON", "SQUAD", "Confuse"};
var words := new string[]{"", "A", "BARK", "BOOK", "TREAT", "COMMON", "SQUAD", "Confuse"};
Enumerator e := words.enumerator();
e.next();

View file

@ -1,3 +1,5 @@
using Printf
function abc(str::AbstractString, list)
isempty(str) && return true
for i in eachindex(list)

View file

@ -7,15 +7,15 @@ blocks= 'BO XK DQ CP NA GT RE TG QD FS JW HU VI AN OB ER FS LY
exit /*stick a fork in it, we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
spell: procedure expose blocks; arg x /*ARG uppercases the word to be spelt.*/
L=length(x); @.=0 /*get length of the word to be spelt. */
do try=1 for L; z=blocks; upper z /*use a fresh copy of the "Z" blocks.*/
do n=1 for L; y=substr(x, n, 1) /*attempt another letter in the word. */
@.n=pos(y, z, 1 + @.n); if @.n==0 then leave /*not found? Try again*/
z=overlay(' ', z, @.n) /*mutate the toy block ───► a onesy. */
do q=1 for words(z); if length(word(z, q))==1 then z=delword(z, q, 1)
L= length(x); @.= 0 /*get length of the word to be spelt. */
do try=1 for L; z= blocks; upper z /*use a fresh copy of the "Z" blocks.*/
do n=1 for L; y= substr(x, n, 1) /*attempt another letter in the word. */
@.n= pos(y, z, 1 + @.n); if @.n==0 then leave /*not found? Try again*/
z= overlay(' ', z, @.n) /*mutate the toy block ───► a onesy. */
do q=1 for words(z); if length(word(z,q))==1 then z= delword(z, q, 1)
end /*q*/ /* [↑] elide any existing onesy block.*/
if n==L then leave try /*was last letter used in the spelling?*/
end /*n*/ /* [↑] end of a toy block usage. */
end /*try*/ /* [↑] end of a "TRY" permute. */
say right(arg(1), 30) right( word( "can't can", (n==L) +1), 6) 'be spelt.'
say right( arg(1), 30) right( word( "can't can", (n==L) + 1), 6) 'be spelt.'
return

View file

@ -0,0 +1,29 @@
string 0;
char Side1, Side2;
def Size = 20;
char Avail(Size);
func CanMakeWord(Word); \returns 'true' if blocks can make Word
char Word;
int I, Let;
[Let:= Word(0) & $5F; \get letter and make sure it's uppercase
if Let = 0 then return true; \if 0 then end of word; return successful
for I:= 0 to Size-1 do \scan for block that contains letter
if Avail(I) and (Side1(I) = Let or Side2(I) = Let) then
[Avail(I):= false;
if CanMakeWord(Word+1) then return true;
];
return false;
];
int I, J, Words;
[Side1:= "BXDCNGRTQFJHVAOEFLPZ";
Side2:= "OKQPATEGDSWUINBRSYCM";
Words:= ["A", "bark", "Book", "Treat", "Common", "Squad", "conFuse"];
for J:= 0 to 6 do
[Text(0, "Can make ^""); Text(0, Words(J)); Text(0, "^": ");
for I:= 0 to Size-1 do Avail(I):= true;
Text(0, if CanMakeWord(Words(J)) then "True" else "False"); CrLf(0);
];
]

View file

@ -0,0 +1,88 @@
with Ada.Text_IO;
procedure Test_For_Primes is
type Pascal_Triangle_Type is array (Natural range <>) of Long_Long_Integer;
function Calculate_Pascal_Triangle (N : in Natural) return Pascal_Triangle_Type is
Pascal_Triangle : Pascal_Triangle_Type (0 .. N);
begin
Pascal_Triangle (0) := 1;
for I in Pascal_Triangle'First .. Pascal_Triangle'Last - 1 loop
Pascal_Triangle (1 + I) := 1;
for J in reverse 1 .. I loop
Pascal_Triangle (J) := Pascal_Triangle (J - 1) - Pascal_Triangle (J);
end loop;
Pascal_Triangle (0) := -Pascal_Triangle (0);
end loop;
return Pascal_Triangle;
end Calculate_Pascal_Triangle;
function Is_Prime (N : Integer) return Boolean is
I : Integer;
Result : Boolean := True;
Pascal_Triangle : constant Pascal_Triangle_Type := Calculate_Pascal_Triangle (N);
begin
I := N / 2;
while Result and I > 1 loop
Result := Result and Pascal_Triangle (I) mod Long_Long_Integer (N) = 0;
I := I - 1;
end loop;
return Result;
end Is_Prime;
function Image (N : in Long_Long_Integer;
Sign : in Boolean := False) return String is
Image : constant String := N'Image;
begin
if N < 0 then
return Image;
else
if Sign then
return "+" & Image (Image'First + 1 .. Image'Last);
else
return Image (Image'First + 1 .. Image'Last);
end if;
end if;
end Image;
procedure Show (Triangle : in Pascal_Triangle_Type) is
use Ada.Text_IO;
Begin
for I in reverse Triangle'Range loop
Put (Image (Triangle (I), Sign => True));
Put ("x^");
Put (Image (Long_Long_Integer (I)));
Put (" ");
end loop;
end Show;
procedure Show_Pascal_Triangles is
use Ada.Text_IO;
begin
for N in 0 .. 9 loop
declare
Pascal_Triangle : constant Pascal_Triangle_Type := Calculate_Pascal_Triangle (N);
begin
Put ("(x-1)^" & Image (Long_Long_Integer (N)) & " = ");
Show (Pascal_Triangle);
New_Line;
end;
end loop;
end Show_Pascal_Triangles;
procedure Show_Primes is
use Ada.Text_IO;
begin
for N in 2 .. 63 loop
if Is_Prime (N) then
Put (N'Image);
end if;
end loop;
New_Line;
end Show_Primes;
begin
Show_Pascal_Triangles;
Show_Primes;
end Test_For_Primes;

View file

@ -1,3 +1,5 @@
using Printf
function stringpoly(n::Int64)
if n < 0
return ""

View file

@ -1,7 +1,5 @@
use std::iter::repeat;
fn aks_coefficients(k: usize) -> Vec<i64> {
let mut coefficients = repeat(0i64).take(k + 1).collect::<Vec<_>>();
let mut coefficients = vec![0i64; k + 1];
coefficients[0] = 1;
for i in 1..(k + 1) {
coefficients[i] = -(1..i).fold(coefficients[0], |prev, j|{
@ -18,7 +16,7 @@ fn is_prime(p: usize) -> bool {
false
} else {
let c = aks_coefficients(p);
(1 .. (c.len() - 1) / 2 + 1).all(|i| (c[i] % (p as i64)) == 0)
(1..p / 2 + 1).all(|i| c[i] % p as i64 == 0)
}
}
@ -26,7 +24,7 @@ fn main() {
for i in 0..8 {
println!("{}: {:?}", i, aks_coefficients(i));
}
for i in (1..51).filter(|&i| is_prime(i)) {
for i in (1..=50).filter(|&i| is_prime(i)) {
print!("{} ", i);
}
}

View file

@ -9,3 +9,5 @@ It is important not to confuse this ''abstractness'' (of implementation) with on
In some languages, like for example in Objective Caml which is strongly statically typed, it is also possible to have '''abstract types''' that are not OO related and are not an abstractness too. These are ''pure abstract types'' without any definition even in the implementation and can be used for example for the type algebra, or for some consistence of the type inference. For example in this area, an abstract type can be used as a phantom type to augment another type as its parameter. <!-- An OCaml Guru would explain this better than me, a poor beginner... -->
'''Task''': show how an abstract type can be declared in the language. If the language makes a distinction between interfaces and partially implemented types illustrate both.
{{omit from|MiniZinc|no ability to declare new types at all}}

View file

@ -0,0 +1,29 @@
package main
import "fmt"
type Beast interface {
Cry() string
}
type Pet struct{}
type Cat struct {
Pet
}
func (p Pet) Name(b Beast) {
fmt.Println(b.Cry())
}
func (p Pet) Cry() string {
return "Woof"
}
func (c Cat) Cry() string {
return "Meow"
}
func main() {
p := Pet{}
c := Cat{}
p.Name(p) // prt Woof
c.Name(c) // prt Meow
}

View file

@ -0,0 +1,29 @@
public abstract class Animal : Object {
public void eat() {
print("Chomp! Chomp!\n");
}
public abstract void talk();
}
public class Mouse : Animal {
public override void talk() {
print("Squeak! Squeak!\n");
}
}
public class Dog : Animal {
public override void talk() {
print("Woof! Woof!\n");
}
}
void main() {
Dog mike = new Dog();
Mouse scott = new Mouse();
mike.talk();
mike.eat();
scott.talk();
scott.eat();
}

View file

@ -2,29 +2,26 @@ with Ada.Text_IO, Generic_Divisors;
procedure ADB_Classification is
function Same(P: Positive) return Positive is (P);
package Divisor_Sum is new Generic_Divisors
(Result_Type => Natural, None => 0, One => Same, Add => "+");
type Class_Type is (Deficient, Perfect, Abundant);
function Class(D_Sum, N: Natural) return Class_Type is
(if D_Sum < N then Deficient
elsif D_Sum = N then Perfect
else Abundant);
Cls: Class_Type;
Results: array (Class_Type) of Natural := (others => 0);
Sum: Natural;
package NIO is new Ada.Text_IO.Integer_IO(Natural);
package CIO is new Ada.Text_IO.Enumeration_IO(Class_Type);
begin
for N in 1 .. 20_000 loop
Sum := Divisor_Sum.Process(N);
if Sum < N then
Results(Deficient) := Results(Deficient)+1;
elsif Sum = N then
Results(Perfect) := Results(Perfect)+1;
else
Results(Abundant) := Results(Abundant)+1;
end if;
Cls := Class(Divisor_Sum.Process(N), N);
Results(Cls) := Results(Cls)+1;
end loop;
Sum := 0;
for Class in Results'Range loop
CIO.Put(Class, 12);
NIO.Put(Results(Class), 8);
@ -32,7 +29,7 @@ begin
end loop;
Ada.Text_IO.Put_Line("--------------------");
Ada.Text_IO.Put("Sum ");
NIO.Put(Sum, 8);
NIO.Put(Results(Deficient)+Results(Perfect)+Results(Abundant), 8);
Ada.Text_IO.New_Line;
Ada.Text_IO.Put_Line("====================");
end ADB_Classification;

View file

@ -6,15 +6,15 @@ divs(1) -> [];
divs(N) -> lists:sort(divisors(1,N)).
divisors(1,N) ->
[1] ++ divisors(2,N,math:sqrt(N)).
divisors(2,N,math:sqrt(N),[1]).
divisors(K,_N,Q) when K > Q -> [];
divisors(K,N,_Q) when N rem K =/= 0 ->
[] ++ divisors(K+1,N,math:sqrt(N));
divisors(K,N,_Q) when K * K == N ->
[K] ++ divisors(K+1,N,math:sqrt(N));
divisors(K,N,_Q) ->
[K, N div K] ++ divisors(K+1,N,math:sqrt(N)).
divisors(K,_N,Q,L) when K > Q -> L;
divisors(K,N,_Q,L) when N rem K =/= 0 ->
divisors(K+1,N,_Q,L);
divisors(K,N,_Q,L) when K * K =:= N ->
divisors(K+1,N,_Q,[K|L]);
divisors(K,N,_Q,L) ->
divisors(K+1,N,_Q,[N div K, K|L]).
sumdivs(N) -> lists:sum(divs(N)).

View file

@ -0,0 +1,11 @@
d = new dict
for n = 1 to 20000
{
s = sum[allFactors[n, true, false, true], 0]
rel = s <=> n
d.increment[rel, 1]
}
println["Deficient: " + d@(-1)]
println["Perfect: " + d@0]
println["Abundant: " + d@1]

View file

@ -0,0 +1,27 @@
import Data.Numbers.Primes (primeFactors)
import Data.List (group, sort)
import Data.Bool (bool)
deficientPerfectAbundantCountsUpTo :: Int -> (Int, Int, Int)
deficientPerfectAbundantCountsUpTo n =
foldr
(\x (deficient, perfect, abundant) ->
let divisorSum = sum $ properDivisors x
in bool
(bool
(deficient, succ perfect, abundant)
(deficient, perfect, succ abundant)
(divisorSum > x))
(succ deficient, perfect, abundant)
(divisorSum < x))
(0, 0, 0)
[1 .. n :: Int]
properDivisors :: Int -> [Int]
properDivisors =
init . sort . foldr (
flip ((<*>) . fmap (*)) . scanl (*) 1
) [1] . group . primeFactors
main :: IO ()
main = print $ deficientPerfectAbundantCountsUpTo 20000

View file

@ -0,0 +1,109 @@
'''Abundant, deficient and perfect number classifications'''
from itertools import accumulate, chain, groupby, product
from functools import reduce
from math import floor, sqrt
from operator import mul
# deficientPerfectAbundantCountsUpTo :: Int -> (Int, Int, Int)
def deficientPerfectAbundantCountsUpTo(n):
'''Counts of deficient, perfect, and abundant
integers in the range [1..n].
'''
def go(dpa, x):
deficient, perfect, abundant = dpa
divisorSum = sum(properDivisors(x))
return (
succ(deficient), perfect, abundant
) if x > divisorSum else (
deficient, perfect, succ(abundant)
) if x < divisorSum else (
deficient, succ(perfect), abundant
)
return reduce(go, range(1, 1 + n), (0, 0, 0))
# --------------------------TEST--------------------------
# main :: IO ()
def main():
'''Size of each sub-class of integers drawn from [1..20000]:'''
print(main.__doc__)
print(
'\n'.join(map(
lambda a, b: a.rjust(10) + ' -> ' + str(b),
['Deficient', 'Perfect', 'Abundant'],
deficientPerfectAbundantCountsUpTo(20000)
))
)
# ------------------------GENERIC-------------------------
# primeFactors :: Int -> [Int]
def primeFactors(n):
'''A list of the prime factors of n.
'''
def f(qr):
r = qr[1]
return step(r), 1 + r
def step(x):
return 1 + (x << 2) - ((x >> 1) << 1)
def go(x):
root = floor(sqrt(x))
def p(qr):
q = qr[0]
return root < q or 0 == (x % q)
q = until(p)(f)(
(2 if 0 == x % 2 else 3, 1)
)[0]
return [x] if q > root else [q] + go(x // q)
return go(n)
# properDivisors :: Int -> [Int]
def properDivisors(n):
'''The ordered divisors of n, excluding n itself.
'''
def go(a, x):
return [a * b for a, b in product(
a,
accumulate(chain([1], x), mul)
)]
return sorted(
reduce(go, [
list(g) for _, g in groupby(primeFactors(n))
], [1])
)[:-1] if 1 < n else []
# succ :: Int -> Int
def succ(x):
'''The successor of a value.
For numeric types, (1 +).
'''
return 1 + x
# until :: (a -> Bool) -> (a -> a) -> a -> a
def until(p):
'''The result of repeatedly applying f until p holds.
The initial seed value is x.
'''
def go(f, x):
v = x
while not p(v):
v = f(v)
return v
return lambda f: lambda x: go(f, x)
# MAIN ---
if __name__ == '__main__':
main()

View file

@ -0,0 +1,11 @@
# nthArrow :: (a -> b) -> Tuple -> Int -> Tuple
def nthArrow(f):
'''A simple function lifted to one which applies to a
tuple, transforming only its nth value.
'''
def go(v, n):
m = n - 1
return v if n > len(v) else [
x if m != i else f(x) for i, x in enumerate(v)
]
return lambda tpl: lambda n: tuple(go(tpl, n))

View file

@ -0,0 +1,13 @@
# deficientPerfectAbundantCountsUpTo :: Int -> (Int, Int, Int)
def deficientPerfectAbundantCountsUpTo(n):
'''Counts of deficient, perfect, and abundant
integers in the range [1..n].
'''
def go(dpa, x):
divisorSum = sum(properDivisors(x))
return nthArrow(succ)(dpa)(
1 if x > divisorSum else (
3 if x < divisorSum else 2
)
)
return reduce(go, range(1, 1 + n), (0, 0, 0))

View file

@ -0,0 +1,35 @@
enum Classification {
DEFICIENT,
PERFECT,
ABUNDANT
}
void main() {
var i = 0; var j = 0;
var sum = 0; var try_max = 0;
int[] count_list = {1, 0, 0};
for (i = 2; i <= 20000; i++) {
try_max = i / 2;
sum = 1;
for (j = 2; j < try_max; j++) {
if (i % j != 0)
continue;
try_max = i / j;
sum += j;
if (j != try_max)
sum += try_max;
}
if (sum < i) {
count_list[Classification.DEFICIENT]++;
continue;
}
if (sum > i) {
count_list[Classification.ABUNDANT]++;
continue;
}
count_list[Classification.PERFECT]++;
}
print(@"There are $(count_list[Classification.DEFICIENT]) deficient,");
print(@" $(count_list[Classification.PERFECT]) perfect,");
print(@" $(count_list[Classification.ABUNDANT]) abundant numbers between 1 and 20000.\n");
}

View file

@ -0,0 +1,2 @@
:acc (ns-)
d:create , [ [ fetch ] [ v:inc ] bi ] does ;

View file

@ -15,8 +15,10 @@ The Ackermann function is usually defined as follows:
<!-- <table><tr><td width=12><td><td><math>n+1</math><td>if <math>m=0</math> <tr><td> <td><math>A(m, n) =</math> <td><math>A(m-1, 1)</math> <td>if <math>m>0</math> and <math>n=0</math> <tr><td><td><td><math>A(m-1, A(m, n-1))</math>&nbsp;&nbsp;<td> if <math>m>0</math> and <math>n>0</math></table> -->
Its arguments are never negative and it always terminates. Write a function which returns the value of <math>A(m, n)</math>. Arbitrary precision is preferred (since the function grows so quickly), but not required.
Its arguments are never negative and it always terminates.
;Task:
Write a function which returns the value of <math>A(m, n)</math>. Arbitrary precision is preferred (since the function grows so quickly), but not required.
;See also:
* [[wp:Conway_chained_arrow_notation#Ackermann_function|Conway chained arrow notation]] for the Ackermann function.

View file

@ -0,0 +1,6 @@
function ack(M,N) {
for (; M > 0; M--) {
N = N === 0 ? 1 : ack(M,N-1);
}
return N+1;
}

View file

@ -0,0 +1,20 @@
function stackermann(M, N) {
const stack = [];
for (;;) {
if (M === 0) {
N++;
if (stack.length === 0) return N;
const r = stack[stack.length-1];
if (r[1] === 1) stack.length--;
else r[1]--;
M = r[0];
} else if (N === 0) {
M--;
N = 1;
} else {
M--
stack.push([M, N]);
N = 1;
}
}
}

View file

@ -0,0 +1,26 @@
#!/usr/bin/env nodejs
function ack(M, N){
const next = new Float64Array(M + 1);
const goal = new Float64Array(M + 1).fill(1, 0, M);
const n = N + 1;
// This serves as a sentinel value;
// next[M] never equals goal[M] == -1,
// so we don't need an extra check for
// loop termination below.
goal[M] = -1;
let v;
do {
v = next[0] + 1;
let m = 0;
while (next[m] === goal[m]) {
goal[m] = v;
next[m++]++;
}
next[m]++;
} while (next[M] !== n);
return v;
}
var args = process.argv;
console.log(ack(parseInt(args[2]), parseInt(args[3])));

View file

@ -0,0 +1,38 @@
(() => {
'use strict';
// ackermann :: Int -> Int -> Int
const ackermann = m => n => {
const go = (m, n) =>
0 === m ? (
succ(n)
) : go(pred(m), 0 === n ? (
1
) : go(m, pred(n)));
return go(m, n);
};
// TEST -----------------------------------------------
const main = () => console.log(JSON.stringify(
[0, 1, 2, 3].map(
flip(ackermann)(3)
)
));
// GENERAL FUNCTIONS ----------------------------------
// flip :: (a -> b -> c) -> b -> a -> c
const flip = f =>
x => y => f(y)(x);
// pred :: Enum a => a -> a
const pred = x => x - 1;
// succ :: Enum a => a -> a
const succ = x => 1 + x;
// MAIN ---
return main();
})();

View file

@ -0,0 +1,38 @@
#!/usr/bin/env luajit
local gmp = require 'gmp' ('libgmp')
local mpz, z_mul, z_add, z_add_ui, z_set_d =
gmp.types.z, gmp.z_mul, gmp.z_add, gmp.z_add_ui, gmp.z_set_d
local z_cmp, z_cmp_ui, z_init_d, z_set=
gmp.z_cmp, gmp.z_cmp_ui, gmp.z_init_set_d, gmp.z_set
local printf = gmp.printf
local function ack(i,n)
local nxt=setmetatable({}, {__index=function(t,k) local z=mpz() z_init_d(z, 0) t[k]=z return z end})
local goal=setmetatable({}, {__index=function(t,k) local o=mpz() z_init_d(o, 1) t[k]=o return o end})
goal[i]=mpz() z_init_d(goal[i], -1)
local v=mpz() z_init_d(v, 0)
local ic
local END=n+1
local ntmp,gtmp
repeat
ic=0
ntmp,gtmp=nxt[ic], goal[ic]
z_add_ui(v, ntmp, 1)
while z_cmp(ntmp, gtmp) == 0 do
z_set(gtmp,v)
z_add_ui(ntmp, ntmp, 1)
nxt[ic], goal[ic]=ntmp, gtmp
ic=ic+1
ntmp,gtmp=nxt[ic], goal[ic]
end
z_add_ui(ntmp, ntmp, 1)
nxt[ic]=ntmp
until z_cmp_ui(nxt[i], END) == 0
return v
end
if #arg<1 then
print("Ackermann: "..arg[0].." <num1> [num2]")
else
printf("%Zd\n", ack(tonumber(arg[1]), arg[2] and tonumber(arg[2]) or 0))
end

View file

@ -1,9 +1,19 @@
int ackermann(int m, n)
{
if (m == 0)
return n + 1;
else if (m > 0 && n == 0)
return ackermann(m - 1, 1);
else
return ackermann( m - 1, ackermann(m, n - 1) );
int ackermann(int m, int n) {
if (m == 0)
return n + 1;
else if (m > 0 && n == 0)
return ackermann(m - 1, 1);
else
return ackermann( m - 1, ackermann(m, n - 1) );
}
// Call function to produce output:
// the first 4x7 Ackermann numbers
void setup() {
for (int m=0; m<4; m++) {
for (int n=0; n<7; n++) {
print(ackermann(m, n), " ");
}
println();
}
}

View file

@ -0,0 +1,13 @@
uint64 ackermann(uint64 m, uint64 n) {
if (m == 0) return n + 1;
if (n == 0) return ackermann(m - 1, 1);
return ackermann(m - 1, ackermann(m, n - 1));
}
void main () {
for (uint64 m = 0; m < 4; ++m) {
for (uint64 n = 0; n < 10; ++n) {
print(@"A($m,$n) = $(ackermann(m,n))\n");
}
}
}

View file

@ -0,0 +1,29 @@
section .text
global _main
_main:
mov eax, 3 ;m
mov ebx, 4 ;n
call ack ;returns number in ebx
ret
ack:
cmp eax, 0
je M0 ;if M == 0
cmp ebx, 0
je N0 ;if N == 0
dec ebx ;else N-1
push eax ;save M
call ack1 ;ack(m,n) -> returned in ebx so no further instructions needed
pop eax ;restore M
dec eax ;M - 1
call ack1 ;return ack(m-1,ack(m,n-1))
ret
M0:
inc ebx ;return n + 1
ret
N0:
dec eax
inc ebx ;ebx always 0: inc -> ebx = 1
call ack1 ;return ack(M-1,1)
ret

View file

@ -0,0 +1,7 @@
Import-Module ActiveDirectory
$searchData = "user name"
$searchBase = "DC=example,DC=com"
#searches by some of the most common unique identifiers
get-aduser -Filter((DistinguishedName -eq $searchdata) -or (UserPrincipalName -eq $searchdata) -or (SamAccountName -eq $searchdata)) -SearchBase $searchBase

View file

@ -0,0 +1,65 @@
integer xlock = init_cs()
class integrator
--
-- Integrates input function f over time
-- v + (t1 - t0) * (f(t1) + f(t0)) / 2
--
integer f -- function f(atom t); (see note)
atom interval, t0, k0 = 0, v = 0
bool running
public integer id
procedure set_func(integer rid)
this.f = rid
end procedure
procedure update()
enter_cs(xlock)
integer f = this.f -- (nb: no "this")
atom t1 = time(),
k1 = f(t1)
-- (oops, '+=' not yet properly supported on class fields...)
-- v += (t1 - t0) * (k1 + k0) / 2
v = v + (t1 - t0) * (k1 + k0) / 2
t0 = t1
k0 = k1
leave_cs(xlock)
end procedure
procedure tick()
running = true
while running do
sleep(interval)
update()
end while
end procedure
procedure stop()
running = false
wait_thread(id)
end procedure
function get_output()
return v
end function
end class
function new_integrator(integer rid, atom interval)
integrator i = new({rid,interval,time()})
i.update()
i.id = create_thread(i.tick,{i})
return i
end function
function zero(atom /*t*/) return 0 end function
function sine(atom t) return sin(2*PI*0.5*t) end function
integrator i = new_integrator(sine,0.01);
sleep(2)
?i.get_output()
i.set_func(zero)
sleep(0.5)
i.stop()
?i.get_output()

View file

@ -1,5 +1,8 @@
julia> x = 3
julia> x = [1, 2, 3]
julia> ptr = pointer_from_objref(x)
Ptr{Void} @0x000000010282e4a0
julia> unsafe_pointer_to_objref(ptr)
3
3-element Array{Int64,1}:
1
2
3

View file

@ -1,2 +1,2 @@
use Scalar::Util qw(refaddr);
print refaddr(\my $v), "\n"; # 135691508
print refaddr(\my $v), "\n"; # 140502490125712

View file

@ -1,4 +1 @@
my $a = 12;
my $b = \$a; # get reference
$$b = $$b + 30; # access referenced value
print $a; # prints 42
printf "%p", $v; # 7fc949039590

View file

@ -1,6 +1,4 @@
my $a = 12;
our $b; # you can overlay only global variables (this line is only for strictness)
*b = \$a;
print $b; # prints 12
$b++;
print $a; # prints 13
my $b = \$a; # get reference
$$b = $$b + 30; # access referenced value
print $a; # prints 42

View file

@ -0,0 +1,6 @@
my $a = 12;
our $b; # you can overlay only global variables (this line is only for strictness)
*b = \$a;
print $b; # prints 12
$b++;
print $a; # prints 13

View file

@ -0,0 +1,9 @@
x <- 5
y <- x
pryr::address(x)
pryr::address(y)
y <- y + 1
pryr::address(x)
pryr::address(y)

View file

@ -0,0 +1,12 @@
address <- function(obj) {
paste0("0x", substring(sub(" .*$","",capture.output(.Internal(inspect(obj)))),2))
}
x <- 5
y <- x
address(x)
address(y)
y <- y + 1
address(x)
address(y)

View file

@ -1,45 +1,19 @@
from StringIO import StringIO
from itertools import zip_longest
textinfile = '''Given$a$text$file$of$many$lines,$where$fields$within$a$line$
txt = """Given$a$txt$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.'''
justified,$right$justified,$or$center$justified$within$its$column."""
j2justifier = dict(L=str.ljust, R=str.rjust, C=str.center)
parts = [line.rstrip("$").split("$") for line in txt.splitlines()]
widths = [max(len(word) for word in col)
for col in zip_longest(*parts, fillvalue='')]
def aligner(infile, justification = 'L'):
''' \
Justify columns of textual tabular input where the row separator is the newline
and the field separator is a 'dollar' character.
justification can be L, R, or C; (Left, Right, or Centered).
Return the justified output as a string
'''
assert justification in j2justifier, "justification can be L, R, or C; (Left, Right, or Centered)."
justifier = j2justifier[justification]
fieldsbyrow= [line.strip().split('$') for line in infile]
# pad to same number of fields per row
maxfields = max(len(row) for row in fieldsbyrow)
fieldsbyrow = [fields + ['']*(maxfields - len(fields))
for fields in fieldsbyrow]
# rotate
fieldsbycolumn = zip(*fieldsbyrow)
# calculate max fieldwidth per column
colwidths = [max(len(field) for field in column)
for column in fieldsbycolumn]
# pad fields in columns to colwidth with spaces
fieldsbycolumn = [ [justifier(field, width) for field in column]
for width, column in zip(colwidths, fieldsbycolumn) ]
# rotate again
fieldsbyrow = zip(*fieldsbycolumn)
return "\n".join( " ".join(row) for row in fieldsbyrow)
for align in 'Left Right Center'.split():
infile = StringIO(textinfile)
print "\n# %s Column-aligned output:" % align
print aligner(infile, align[0])
for justify in "<_Left ^_Center >_Right".split():
j, jtext = justify.split('_')
print(f"{jtext} column-aligned output:\n")
for line in parts:
print(' '.join(f"{wrd:{j}{wdth}}" for wdth, wrd in zip(widths, line)))
print("- " * 52)

View file

@ -1,18 +1,45 @@
'''
cat <<'EOF' > align_columns.dat
Given$a$text$file$of$many$lines,$where$fields$within$a$line$
from StringIO import StringIO
textinfile = '''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.
EOF
'''
justified,$right$justified,$or$center$justified$within$its$column.'''
for align in '<^>':
rows = [ line.strip().split('$') for line in open('align_columns.dat') ]
fmts = [ '{:%s%d}' % (align, max( len(row[i]) if i < len(row) else 0 for row in rows ))
for i in range(max(map(len, rows))) ]
for row in rows:
print(' '.join(fmts).format(*(row + [''] * len(fmts))))
print('')
j2justifier = dict(L=str.ljust, R=str.rjust, C=str.center)
def aligner(infile, justification = 'L'):
''' \
Justify columns of textual tabular input where the row separator is the newline
and the field separator is a 'dollar' character.
justification can be L, R, or C; (Left, Right, or Centered).
Return the justified output as a string
'''
assert justification in j2justifier, "justification can be L, R, or C; (Left, Right, or Centered)."
justifier = j2justifier[justification]
fieldsbyrow= [line.strip().split('$') for line in infile]
# pad to same number of fields per row
maxfields = max(len(row) for row in fieldsbyrow)
fieldsbyrow = [fields + ['']*(maxfields - len(fields))
for fields in fieldsbyrow]
# rotate
fieldsbycolumn = zip(*fieldsbyrow)
# calculate max fieldwidth per column
colwidths = [max(len(field) for field in column)
for column in fieldsbycolumn]
# pad fields in columns to colwidth with spaces
fieldsbycolumn = [ [justifier(field, width) for field in column]
for width, column in zip(colwidths, fieldsbycolumn) ]
# rotate again
fieldsbyrow = zip(*fieldsbycolumn)
return "\n".join( " ".join(row) for row in fieldsbyrow)
for align in 'Left Right Center'.split():
infile = StringIO(textinfile)
print "\n# %s Column-aligned output:" % align
print aligner(infile, align[0])

View file

@ -1,21 +1,18 @@
txt = """Given$a$txt$file$of$many$lines,$where$fields$within$a$line$
'''
cat <<'EOF' > align_columns.dat
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."""
justified,$right$justified,$or$center$justified$within$its$column.
EOF
'''
parts = [line.rstrip("$").split("$") for line in txt.splitlines()]
max_widths = {}
for line in parts:
for i, word in enumerate(line):
max_widths[i] = max(max_widths.get(i, 0), len(word))
for i, justify in enumerate([str.ljust, str.center, str.rjust]):
print ["Left", "Center", "Right"][i], " column-aligned output:\n"
for line in parts:
for j, word in enumerate(line):
print justify(word, max_widths[j]),
print
print "- " * 52
for align in '<^>':
rows = [ line.strip().split('$') for line in open('align_columns.dat') ]
fmts = [ '{:%s%d}' % (align, max( len(row[i]) if i < len(row) else 0 for row in rows ))
for i in range(max(map(len, rows))) ]
for row in rows:
print(' '.join(fmts).format(*(row + [''] * len(fmts))))
print('')

View file

@ -1,75 +1,21 @@
'''Variously aligned columns
from delimited text.
'''
from functools import reduce
from itertools import repeat
# TEST ----------------------------------------------------
# main :: IO ()
def main():
'''Test of three alignments.'''
txt = '''Given$a$text$file$of$many$lines,$where$fields$within$a$line$
txt = """Given$a$txt$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.'''
justified,$right$justified,$or$center$justified$within$its$column."""
rows = [x.split('$') for x in txt.splitlines()]
table = paddedRows(max(map(len, rows)))('')(rows)
parts = [line.rstrip("$").split("$") for line in txt.splitlines()]
print('\n\n'.join(map(
alignedTable(table)(' '),
[-1, 0, 1] # Left, Center, Right
)))
max_widths = {}
for line in parts:
for i, word in enumerate(line):
max_widths[i] = max(max_widths.get(i, 0), len(word))
# alignedTable :: [[String]] -> Alignment -> String -> String
def alignedTable(rows):
'''Tabulation of rows of cells, with cell alignment
specified by:
eAlign -1 = left
eAlign 0 = center
eAlign 1 = right
and separator between columns
supplied by the `sep` argument.
'''
def go(sep, eAlign):
lcr = ['ljust', 'center', 'rjust'][1 + eAlign]
# nextAlignedCol :: [[String]] -> [String] -> [[String]]
def nextAlignedCol(cols, col):
w = max(len(cell) for cell in col)
return cols + [
[getattr(s, lcr)(w, ' ') for s in col]
]
return '\n'.join([
sep.join(cells) for cells in
zip(*reduce(nextAlignedCol, zip(*rows), []))
])
return lambda sep: lambda eAlign: go(sep, eAlign)
# GENERIC -------------------------------------------------
# paddedRows :: Int -> a -> [[a]] -> [[a]]
def paddedRows(n):
'''A list of rows of even length,
in which each may be padded (but
not truncated) to length n with
appended copies of value v.'''
def go(v, xs):
def pad(x):
d = n - len(x)
return (x + list(repeat(v, d))) if 0 < d else x
return [pad(row) for row in xs]
return lambda v: lambda xs: go(v, xs) if xs else []
# MAIN ---
if __name__ == '__main__':
main()
for i, justify in enumerate([str.ljust, str.center, str.rjust]):
print(["Left", "Center", "Right"][i], " column-aligned output:\n")
for line in parts:
for j, word in enumerate(line):
print(justify(word, max_widths[j]), end=' ')
print()
print("- " * 52)

View file

@ -0,0 +1,75 @@
'''Variously aligned columns
from delimited text.
'''
from functools import reduce
from itertools import repeat
# TEST ----------------------------------------------------
# main :: IO ()
def main():
'''Test of three alignments.'''
txt = '''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.'''
rows = [x.split('$') for x in txt.splitlines()]
table = paddedRows(max(map(len, rows)))('')(rows)
print('\n\n'.join(map(
alignedTable(table)(' '),
[-1, 0, 1] # Left, Center, Right
)))
# alignedTable :: [[String]] -> Alignment -> String -> String
def alignedTable(rows):
'''Tabulation of rows of cells, with cell alignment
specified by:
eAlign -1 = left
eAlign 0 = center
eAlign 1 = right
and separator between columns
supplied by the `sep` argument.
'''
def go(sep, eAlign):
lcr = ['ljust', 'center', 'rjust'][1 + eAlign]
# nextAlignedCol :: [[String]] -> [String] -> [[String]]
def nextAlignedCol(cols, col):
w = max(len(cell) for cell in col)
return cols + [
[getattr(s, lcr)(w, ' ') for s in col]
]
return '\n'.join([
sep.join(cells) for cells in
zip(*reduce(nextAlignedCol, zip(*rows), []))
])
return lambda sep: lambda eAlign: go(sep, eAlign)
# GENERIC -------------------------------------------------
# paddedRows :: Int -> a -> [[a]] -> [[a]]
def paddedRows(n):
'''A list of rows of even length,
in which each may be padded (but
not truncated) to length n with
appended copies of value v.'''
def go(v, xs):
def pad(x):
d = n - len(x)
return (x + list(repeat(v, d))) if 0 < d else x
return [pad(row) for row in xs]
return lambda v: lambda xs: go(v, xs) if xs else []
# MAIN ---
if __name__ == '__main__':
main()

View file

@ -1,3 +1,5 @@
using Printf
println("Classification Tests:")
tests = [1:12, 28, 496, 220, 1184, 12496, 1264460, 790, 909, 562, 1064, 1488]
for i in tests

View file

@ -0,0 +1,40 @@
program AlmostPrime;
{$APPTYPE CONSOLE}
function IsKPrime(const n, k: Integer): Boolean;
var
p, f, v: Integer;
begin
f := 0;
p := 2;
v := n;
while (f < k) and (p*p <= n) do begin
while (v mod p) = 0 do begin
v := v div p;
Inc(f);
end;
Inc(p);
end;
if v > 1 then Inc(f);
Result := f = k;
end;
var
i, c, k: Integer;
begin
for k := 1 to 5 do begin
Write('k = ', k, ':');
c := 0;
i := 2;
while c < 10 do begin
if IsKPrime(i, k) then begin
Write(' ', i);
Inc(c);
end;
Inc(i);
end;
WriteLn;
end;
end.

View file

@ -0,0 +1,17 @@
using Primes
isalmostprime(n::Integer, k::Integer) = sum(values(factor(n))) == k
function almostprimes(N::Integer, k::Integer) # return first N almost-k primes
P = Vector{typeof(k)}(undef,N)
i = 0; n = 2
while i < N
if isalmostprime(n, k) P[i += 1] = n end
n += 1
end
return P
end
for k in 1:5
println("$k-Almost-primes: ", join(almostprimes(10, k), ", "), "...")
end

View file

@ -0,0 +1,35 @@
struct KPrimeGen: Sequence, IteratorProtocol {
let k: Int
private(set) var n: Int
private func isKPrime() -> Bool {
var primes = 0
var f = 2
var rem = n
while primes < k && rem > 1 {
while rem % f == 0 && rem > 1 {
rem /= f
primes += 1
}
f += 1
}
return rem == 1 && primes == k
}
mutating func next() -> Int? {
n += 1
while !isKPrime() {
n += 1
}
return n
}
}
for k in 1..<6 {
print("\(k): \(Array(KPrimeGen(k: k, n: 1).lazy.prefix(10)))")
}

View file

@ -68,7 +68,8 @@ public program()
try
{
ambOperator
.for(new {"the","that","a"},new {"frog", "elephant", "thing"},new {"walked", "treaded", "grows"}, new {"slowly", "quickly"})
.for(new::("the","that","a"),new::("frog", "elephant", "thing"),new::("walked", "treaded", "grows"),
new::("slowly", "quickly"))
.seek:(a,b,c,d => joinable(a,b) && joinable(b,c) && joinable(c,d) )
.do:(a,b,c,d) { console.printLine(a," ",b," ",c," ",d) }
}

View file

@ -9,7 +9,7 @@ example = do
w2 <- amb ["frog", "elephant", "thing"]
w3 <- amb ["walked", "treaded", "grows"]
w4 <- amb ["slowly", "quickly"]
unless (joins w1 w2) (amb [])
unless (joins w2 w3) (amb [])
unless (joins w3 w4) (amb [])
return (unwords [w1, w2, w3, w4])
guard (w1 `joins` w2)
guard (w2 `joins` w3)
guard (w3 `joins` w4)
pure $ unwords [w1, w2, w3, w4]

View file

@ -24,7 +24,7 @@ extension op
var sum := divsums[i];
^ (i < sum) && (sum < divsums.Length) && (divsums[sum] == i)
}
.selectBy:(i => new:{ Item1 = i; Item2 = divsums[i]; })
.selectBy:(i => new::{ Item1 = i; Item2 = divsums[i]; })
}
}

Some files were not shown because too many files have changed in this diff Show more