2016 Update
This commit is contained in:
parent
948b86eafa
commit
dcf5d15da3
7965 changed files with 139854 additions and 31002 deletions
|
|
@ -1,6 +1,8 @@
|
|||
The objective of this task is to create a reasonably complete implementation of rational arithmetic in the particular language using the idioms of the language.
|
||||
;Task:
|
||||
Create a reasonably complete implementation of rational arithmetic in the particular language using the idioms of the language.
|
||||
|
||||
For example:
|
||||
|
||||
;Example:
|
||||
Define a new type called '''frac''' with binary operator "//" of two integers that returns a '''structure''' made up of the numerator and the denominator (as per a rational number).
|
||||
|
||||
Further define the appropriate rational unary '''operators''' '''abs''' and '-', with the binary '''operators''' for addition '+', subtraction '-', multiplication '×', division '/', integer division '÷', modulo division, the comparison operators (e.g. '<', '≤', '>', & '≥') and equality operators (e.g. '=' & '≠').
|
||||
|
|
@ -12,5 +14,7 @@ If space allows, define standard increment and decrement '''operators''' (e.g. '
|
|||
Finally test the operators:
|
||||
Use the new type '''frac''' to find all [[Perfect Numbers|perfect numbers]] less than 2<sup>19</sup> by summing the reciprocal of the factors.
|
||||
|
||||
'''See also'''
|
||||
* [[Perfect Numbers]]
|
||||
|
||||
;Related task:
|
||||
* [[Perfect Numbers]]
|
||||
<br><br>
|
||||
|
|
|
|||
66
Task/Arithmetic-Rational/Elixir/arithmetic-rational.elixir
Normal file
66
Task/Arithmetic-Rational/Elixir/arithmetic-rational.elixir
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
defmodule Rational do
|
||||
import Kernel, except: [div: 2]
|
||||
|
||||
defstruct numerator: 0, denominator: 1
|
||||
|
||||
def new(numerator), do: %Rational{numerator: numerator, denominator: 1}
|
||||
|
||||
def new(numerator, denominator) do
|
||||
sign = if numerator * denominator < 0, do: -1, else: 1
|
||||
{numerator, denominator} = {abs(numerator), abs(denominator)}
|
||||
gcd = gcd(numerator, denominator)
|
||||
%Rational{numerator: sign * Kernel.div(numerator, gcd),
|
||||
denominator: Kernel.div(denominator, gcd)}
|
||||
end
|
||||
|
||||
def add(a, b) do
|
||||
{a, b} = convert(a, b)
|
||||
new(a.numerator * b.denominator + b.numerator * a.denominator,
|
||||
a.denominator * b.denominator)
|
||||
end
|
||||
|
||||
def sub(a, b) do
|
||||
{a, b} = convert(a, b)
|
||||
new(a.numerator * b.denominator - b.numerator * a.denominator,
|
||||
a.denominator * b.denominator)
|
||||
end
|
||||
|
||||
def mult(a, b) do
|
||||
{a, b} = convert(a, b)
|
||||
new(a.numerator * b.numerator, a.denominator * b.denominator)
|
||||
end
|
||||
|
||||
def div(a, b) do
|
||||
{a, b} = convert(a, b)
|
||||
new(a.numerator * b.denominator, a.denominator * b.numerator)
|
||||
end
|
||||
|
||||
defp convert(a), do: if is_integer(a), do: new(a), else: a
|
||||
|
||||
defp convert(a, b), do: {convert(a), convert(b)}
|
||||
|
||||
defp gcd(a, 0), do: a
|
||||
defp gcd(a, b), do: gcd(b, rem(a, b))
|
||||
end
|
||||
|
||||
defimpl Inspect, for: Rational do
|
||||
def inspect(r, _opts) do
|
||||
"%Rational<#{r.numerator}/#{r.denominator}>"
|
||||
end
|
||||
end
|
||||
|
||||
Enum.each(2..trunc(:math.pow(2,19)), fn candidate ->
|
||||
sum = 2 .. round(:math.sqrt(candidate))
|
||||
|> Enum.reduce(Rational.new(1, candidate), fn factor,sum ->
|
||||
if rem(candidate, factor) == 0 do
|
||||
Rational.add(sum, Rational.new(1, factor))
|
||||
|> Rational.add(Rational.new(1, div(candidate, factor)))
|
||||
else
|
||||
sum
|
||||
end
|
||||
end)
|
||||
if sum.denominator == 1 do
|
||||
:io.format "Sum of recipr. factors of ~6w = ~w exactly ~s~n",
|
||||
[candidate, sum.numerator, (if sum.numerator == 1, do: "perfect!", else: "")]
|
||||
end
|
||||
end)
|
||||
11
Task/Arithmetic-Rational/Frink/arithmetic-rational.frink
Normal file
11
Task/Arithmetic-Rational/Frink/arithmetic-rational.frink
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
1/2 + 2/3
|
||||
// 7/6 (approx. 1.1666666666666667)
|
||||
|
||||
1/2 + 1/2
|
||||
// 1
|
||||
|
||||
5/sextillion + 3/quadrillion
|
||||
// 600001/200000000000000000000 (exactly 3.000005e-15)
|
||||
|
||||
8^(1/3)
|
||||
// 2 (note the exact integer result.)
|
||||
|
|
@ -1,2 +1,4 @@
|
|||
3r4*2r5
|
||||
3r10
|
||||
(x: 3) % (x: -4)
|
||||
_3r4
|
||||
3 %&x: -4
|
||||
_3r4
|
||||
|
|
|
|||
2
Task/Arithmetic-Rational/J/arithmetic-rational-10.j
Normal file
2
Task/Arithmetic-Rational/J/arithmetic-rational-10.j
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
(#~ is_perfect_rational"0) (* <:@+:) 2^i.10x
|
||||
6 28 496 8128
|
||||
|
|
@ -1 +1,28 @@
|
|||
is_perfect_rational=: 2 = (1 + i.) +/@:%@([ #~ 0 = |) ]
|
||||
| _3r4 NB. absolute value
|
||||
3r4
|
||||
-2r5 NB. negation
|
||||
_2r5
|
||||
3r4+2r5 NB. addition
|
||||
23r20
|
||||
3r4-2r5 NB. subtraction
|
||||
7r20
|
||||
3r4*2r5 NB. multiplication
|
||||
3r10
|
||||
3r4%2r5 NB. division
|
||||
15r8
|
||||
3r4 <.@% 2r5 NB. integer division
|
||||
1
|
||||
3r4 (-~ <.)@% 2r5 NB. remainder
|
||||
_7r8
|
||||
3r4 < 2r5 NB. less than
|
||||
0
|
||||
3r4 <: 2r5 NB. less than or equal
|
||||
0
|
||||
3r4 > 2r5 NB. greater than
|
||||
1
|
||||
3r4 >: 2r5 NB. greater than or equal
|
||||
1
|
||||
3r4 = 2r5 NB. equal
|
||||
0
|
||||
3r4 ~: 2r5 NB. not equal
|
||||
1
|
||||
|
|
|
|||
|
|
@ -1,2 +1,4 @@
|
|||
factors=: */&>@{@((^ i.@>:)&.>/)@q:~&__
|
||||
is_perfect_rational=: 2= +/@:%@,@factors
|
||||
x: 3%4
|
||||
3r4
|
||||
x:inv 3%4
|
||||
0.75
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
I.is_perfect_rational@"0 i.2^19
|
||||
6 28 496 8128
|
||||
I.is_perfect_rational@x:@"0 i.2^19x
|
||||
6 28 496 8128
|
||||
>: 3r4
|
||||
7r4
|
||||
<: 3r4
|
||||
_1r4
|
||||
|
|
|
|||
|
|
@ -1,2 +1,7 @@
|
|||
(#~ is_perfect_rational"0) (* <:@+:) 2^i.10x
|
||||
6 28 496 8128
|
||||
mutadd=:adverb define
|
||||
(m)=: (".m)+y
|
||||
)
|
||||
|
||||
mutsub=:adverb define
|
||||
(m)=: (".m)-y
|
||||
)
|
||||
|
|
|
|||
7
Task/Arithmetic-Rational/J/arithmetic-rational-6.j
Normal file
7
Task/Arithmetic-Rational/J/arithmetic-rational-6.j
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
n=: 3r4
|
||||
'n' mutadd 1
|
||||
7r4
|
||||
'n' mutsub 1
|
||||
3r4
|
||||
'n' mutsub 1
|
||||
_1r4
|
||||
1
Task/Arithmetic-Rational/J/arithmetic-rational-7.j
Normal file
1
Task/Arithmetic-Rational/J/arithmetic-rational-7.j
Normal file
|
|
@ -0,0 +1 @@
|
|||
is_perfect_rational=: 2 = (1 + i.) +/@:%@([ #~ 0 = |) ]
|
||||
2
Task/Arithmetic-Rational/J/arithmetic-rational-8.j
Normal file
2
Task/Arithmetic-Rational/J/arithmetic-rational-8.j
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
factors=: */&>@{@((^ i.@>:)&.>/)@q:~&__
|
||||
is_perfect_rational=: 2= +/@:%@,@factors
|
||||
4
Task/Arithmetic-Rational/J/arithmetic-rational-9.j
Normal file
4
Task/Arithmetic-Rational/J/arithmetic-rational-9.j
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
I.is_perfect_rational@"0 i.2^19
|
||||
6 28 496 8128
|
||||
I.is_perfect_rational@x:@"0 i.2^19x
|
||||
6 28 496 8128
|
||||
21
Task/Arithmetic-Rational/OCaml/arithmetic-rational-3.ocaml
Normal file
21
Task/Arithmetic-Rational/OCaml/arithmetic-rational-3.ocaml
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
(* interface *)
|
||||
module type RATIO =
|
||||
sig
|
||||
type t
|
||||
(* construct *)
|
||||
val frac : int -> int -> t
|
||||
val from_int : int -> t
|
||||
|
||||
(* integer test *)
|
||||
val is_int : t -> bool
|
||||
|
||||
(* output *)
|
||||
val to_string : t -> string
|
||||
|
||||
(* arithmetic *)
|
||||
val cmp : t -> t -> int
|
||||
val ( +/ ) : t -> t -> t
|
||||
val ( -/ ) : t -> t -> t
|
||||
val ( */ ) : t -> t -> t
|
||||
val ( // ) : t -> t -> t
|
||||
end
|
||||
58
Task/Arithmetic-Rational/OCaml/arithmetic-rational-4.ocaml
Normal file
58
Task/Arithmetic-Rational/OCaml/arithmetic-rational-4.ocaml
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
(* implementation conforming to signature *)
|
||||
module Frac : RATIO =
|
||||
struct
|
||||
open Big_int
|
||||
|
||||
type t = { num : big_int; den : big_int }
|
||||
|
||||
(* short aliases for big_int values and functions *)
|
||||
let zero, one = zero_big_int, unit_big_int
|
||||
let big, to_int, eq = big_int_of_int, int_of_big_int, eq_big_int
|
||||
let (+~), (-~), ( *~) = add_big_int, sub_big_int, mult_big_int
|
||||
|
||||
(* helper function *)
|
||||
let rec norm ({num=n;den=d} as k) =
|
||||
if lt_big_int d zero then
|
||||
norm {num=minus_big_int n;den=minus_big_int d}
|
||||
else
|
||||
let rec hcf a b =
|
||||
let q,r = quomod_big_int a b in
|
||||
if eq r zero then b else hcf b r in
|
||||
let f = hcf n d in
|
||||
if eq f one then k else
|
||||
let div = div_big_int in
|
||||
{ num=div n f; den = div d f } (* inefficient *)
|
||||
|
||||
(* public functions *)
|
||||
let frac a b = norm { num=big a; den=big b }
|
||||
|
||||
let from_int a = norm { num=big a; den=one }
|
||||
|
||||
let is_int {num=n; den=d} =
|
||||
eq d one ||
|
||||
eq (mod_big_int n d) zero
|
||||
|
||||
let to_string ({num=n; den=d} as r) =
|
||||
let r1 = norm r in
|
||||
let str = string_of_big_int in
|
||||
if is_int r1 then
|
||||
str (r1.num)
|
||||
else
|
||||
str (r1.num) ^ "/" ^ str (r1.den)
|
||||
|
||||
let cmp a b =
|
||||
let a1 = norm a and b1 = norm b in
|
||||
compare_big_int (a1.num*~b1.den) (b1.num*~a1.den)
|
||||
|
||||
let ( */ ) {num=n1; den=d1} {num=n2; den=d2} =
|
||||
norm { num = n1*~n2; den = d1*~d2 }
|
||||
|
||||
let ( // ) {num=n1; den=d1} {num=n2; den=d2} =
|
||||
norm { num = n1*~d2; den = d1*~n2 }
|
||||
|
||||
let ( +/ ) {num=n1; den=d1} {num=n2; den=d2} =
|
||||
norm { num = n1*~d2 +~ n2*~d1; den = d1*~d2 }
|
||||
|
||||
let ( -/ ) {num=n1; den=d1} {num=n2; den=d2} =
|
||||
norm { num = n1*~d2 -~ n2*~d1; den = d1*~d2 }
|
||||
end
|
||||
14
Task/Arithmetic-Rational/OCaml/arithmetic-rational-5.ocaml
Normal file
14
Task/Arithmetic-Rational/OCaml/arithmetic-rational-5.ocaml
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
(* use the module to calculate perfect numbers *)
|
||||
let () =
|
||||
for i = 2 to 1 lsl 19 do
|
||||
let sum = ref (Frac.frac 1 i) in
|
||||
for factor = 2 to truncate (sqrt (float i)) do
|
||||
if i mod factor = 0 then
|
||||
Frac.(
|
||||
sum := !sum +/ frac 1 factor +/ frac 1 (i / factor)
|
||||
)
|
||||
done;
|
||||
if Frac.is_int !sum then
|
||||
Printf.printf "Sum of reciprocal factors of %d = %s exactly %s\n%!"
|
||||
i (Frac.to_string !sum) (if Frac.to_string !sum = "1" then "perfect!" else "")
|
||||
done
|
||||
|
|
@ -5,7 +5,7 @@ for 2..2**19 -> $candidate {
|
|||
$sum += 1 / $factor + 1 / ($candidate / $factor);
|
||||
}
|
||||
}
|
||||
if $sum.denominator == 1 {
|
||||
if $sum.nude[1] == 1 {
|
||||
say "Sum of reciprocal factors of $candidate = $sum exactly", ($sum == 1 ?? ", perfect!" !! ".");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
133
Task/Arithmetic-Rational/Rust/arithmetic-rational.rust
Normal file
133
Task/Arithmetic-Rational/Rust/arithmetic-rational.rust
Normal file
|
|
@ -0,0 +1,133 @@
|
|||
use std::cmp::Ordering;
|
||||
use std::ops::{Add, AddAssign, Sub, SubAssign, Mul, MulAssign, Div, DivAssign, Neg};
|
||||
|
||||
fn gcd(a: i64, b: i64) -> i64 {
|
||||
match b {
|
||||
0 => a,
|
||||
_ => gcd(b, a % b),
|
||||
}
|
||||
}
|
||||
|
||||
fn lcm(a: i64, b: i64) -> i64 {
|
||||
a / gcd(a, b) * b
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash, Ord)]
|
||||
pub struct Rational {
|
||||
numerator: i64,
|
||||
denominator: i64,
|
||||
}
|
||||
|
||||
impl Rational {
|
||||
fn new(numerator: i64, denominator: i64) -> Self {
|
||||
let divisor = gcd(numerator, denominator);
|
||||
Rational {
|
||||
numerator: numerator / divisor,
|
||||
denominator: denominator / divisor,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Add for Rational {
|
||||
type Output = Self;
|
||||
|
||||
fn add(self, other: Self) -> Self {
|
||||
let multiplier = lcm(self.denominator, other.denominator);
|
||||
Rational::new(self.numerator * multiplier / self.denominator +
|
||||
other.numerator * multiplier / other.denominator,
|
||||
multiplier)
|
||||
}
|
||||
}
|
||||
|
||||
impl AddAssign for Rational {
|
||||
fn add_assign(&mut self, other: Self) {
|
||||
*self = *self + other;
|
||||
}
|
||||
}
|
||||
|
||||
impl Sub for Rational {
|
||||
type Output = Self;
|
||||
|
||||
fn sub(self, other: Self) -> Self {
|
||||
self + -other
|
||||
}
|
||||
}
|
||||
|
||||
impl SubAssign for Rational {
|
||||
fn sub_assign(&mut self, other: Self) {
|
||||
*self = *self - other;
|
||||
}
|
||||
}
|
||||
|
||||
impl Mul for Rational {
|
||||
type Output = Self;
|
||||
|
||||
fn mul(self, other: Self) -> Self {
|
||||
Rational::new(self.numerator * other.numerator,
|
||||
self.denominator * other.denominator)
|
||||
}
|
||||
}
|
||||
|
||||
impl MulAssign for Rational {
|
||||
fn mul_assign(&mut self, other: Self) {
|
||||
*self = *self * other;
|
||||
}
|
||||
}
|
||||
|
||||
impl Div for Rational {
|
||||
type Output = Self;
|
||||
|
||||
fn div(self, other: Self) -> Self {
|
||||
self *
|
||||
Rational {
|
||||
numerator: other.denominator,
|
||||
denominator: other.numerator,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl DivAssign for Rational {
|
||||
fn div_assign(&mut self, other: Self) {
|
||||
*self = *self / other;
|
||||
}
|
||||
}
|
||||
|
||||
impl Neg for Rational {
|
||||
type Output = Self;
|
||||
|
||||
fn neg(self) -> Self {
|
||||
Rational {
|
||||
numerator: -self.numerator,
|
||||
denominator: self.denominator,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialOrd for Rational {
|
||||
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
||||
(self.numerator * other.denominator).partial_cmp(&(self.denominator * other.numerator))
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Into<i64>> From<T> for Rational {
|
||||
fn from(value: T) -> Self {
|
||||
Rational::new(value.into(), 1)
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let max = 1 << 19;
|
||||
for candidate in 2..max {
|
||||
let mut sum = Rational::new(1, candidate);
|
||||
for factor in 2..(candidate as f64).sqrt().ceil() as i64 {
|
||||
if candidate % factor == 0 {
|
||||
sum += Rational::new(1, factor);
|
||||
sum += Rational::new(1, candidate / factor);
|
||||
}
|
||||
}
|
||||
|
||||
if sum == 1.into() {
|
||||
println!("{} is perfect", candidate);
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue