Data commit

This commit is contained in:
Ingy döt Net 2023-07-01 11:58:00 -04:00
parent 7387c8f97b
commit cb5bb5e222
199093 changed files with 3378972 additions and 0 deletions

View file

@ -0,0 +1,67 @@
:- module('bt_convert.pl', [bt_convert/2,
op(950, xfx, btconv),
btconv/2]).
:- use_module(library(clpfd)).
:- op(950, xfx, btconv).
X btconv Y :-
bt_convert(X, Y).
% bt_convert(?X, ?L)
bt_convert(X, L) :-
( (nonvar(L), \+is_list(L)) ->string_to_list(L, L1); L1 = L),
convert(X, L1),
( var(L) -> string_to_list(L, L1); true).
% map numbers toward digits +, - 0
plus_moins( 1, 43).
plus_moins(-1, 45).
plus_moins( 0, 48).
convert(X, [48| L]) :-
var(X),
( L \= [] -> convert(X, L); X = 0, !).
convert(0, L) :-
var(L), !, string_to_list(L, [48]).
convert(X, L) :-
( (nonvar(X), X > 0)
; (var(X), X #> 0,
L = [43|_],
maplist(plus_moins, L1, L))),
!,
convert(X, 0, [], L1),
( nonvar(X) -> maplist(plus_moins, L1, LL), string_to_list(L, LL)
; true).
convert(X, L) :-
( nonvar(X) -> Y is -X
; X #< 0,
maplist(plus_moins, L2, L),
maplist(mult(-1), L2, L1)),
convert(Y, 0, [], L1),
( nonvar(X) ->
maplist(mult(-1), L1, L2),
maplist(plus_moins, L2, LL),
string_to_list(L, LL)
; X #= -Y).
mult(X, Y, Z) :-
Z #= X * Y.
convert(0, 0, L, L) :- !.
convert(0, 1, L, [1 | L]) :- !.
convert(N, C, LC, LF) :-
R #= N mod 3 + C,
R #> 1 #<==> C1,
N1 #= N / 3,
R1 #= R - 3 * C1, % C1 #= 1,
convert(N1, C1, [R1 | LC], LF).

View file

@ -0,0 +1,123 @@
:- module('bt_add.pl', [bt_add/3,
bt_add1/3,
op(900, xfx, btplus),
op(900, xfx, btmoins),
btplus/2,
btmoins/2,
strip_nombre/3
]).
:- op(900, xfx, btplus).
:- op(900, xfx, btmoins).
% define operator btplus
A is X btplus Y :-
bt_add(X, Y, A).
% define operator btmoins
% no need to define a predicate for the substraction
A is X btmoins Y :-
X is Y btplus A.
% bt_add(?X, ?Y, ?R)
% R is X + Y
% X, Y, R are strings
% At least 2 args must be instantiated
bt_add(X, Y, R) :-
( nonvar(X) -> string_to_list(X, X1); true),
( nonvar(Y) -> string_to_list(Y, Y1); true),
( nonvar(R) -> string_to_list(R, R1); true),
bt_add1(X1, Y1, R1),
( var(X) -> string_to_list(X, X1); true),
( var(Y) -> string_to_list(Y, Y1); true),
( var(R) -> string_to_list(R, R1); true).
% bt_add1(?X, ?Y, ?R)
% R is X + Y
% X, Y, R are lists
bt_add1(X, Y, R) :-
% initialisation : X and Y must have the same length
% we add zeros at the beginning of the shortest list
( nonvar(X) -> length(X, LX); length(R, LR)),
( nonvar(Y) -> length(Y, LY); length(R, LR)),
( var(X) -> LX is max(LY, LR) , length(X1, LX), Y1 = Y ; X1 = X),
( var(Y) -> LY is max(LX, LR) , length(Y1, LY), X1 = X ; Y1 = Y),
Delta is abs(LX - LY),
( LX < LY -> normalise(Delta, X1, X2), Y1 = Y2
; LY < LX -> normalise(Delta, Y1, Y2), X1 = X2
; X1 = X2, Y1 = Y2),
% if R is instancied, it must have, at least, the same length than X or Y
Max is max(LX, LY),
( (nonvar(R), length(R, LR), LR < Max) -> Delta1 is Max - LR, normalise(Delta1, R, R2)
; nonvar(R) -> R = R2
; true),
bt_add(X2, Y2, C, R2),
( C = 48 -> strip_nombre(R2, R, []),
( var(X) -> strip_nombre(X2, X, []) ; true),
( var(Y) -> strip_nombre(Y2, Y, []) ; true)
; var(R) -> strip_nombre([C|R2], R, [])
; ( select(C, [45,43], [Ca]),
( var(X) -> strip_nombre([Ca | X2], X, [])
; strip_nombre([Ca | Y2], Y, [])))).
% here we actually compute the sum
bt_add([], [], 48, []).
bt_add([H1|T1], [H2|T2], C3, [R2 | L]) :-
bt_add(T1, T2, C, L),
% add HH1 and H2
ternary_sum(H1, H2, R1, C1),
% add first carry,
ternary_sum(R1, C, R2, C2),
% add second carry
ternary_sum(C1, C2, C3, _).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% ternary_sum
% @arg1 : V1
% @arg2 : V2
% @arg3 : R is V1 + V2
% @arg4 : Carry
ternary_sum(43, 43, 45, 43).
ternary_sum(43, 45, 48, 48).
ternary_sum(45, 43, 48, 48).
ternary_sum(45, 45, 43, 45).
ternary_sum(X, 48, X, 48).
ternary_sum(48, X, X, 48).
% if L has a length smaller than N, complete L with 0 (code 48)
normalise(0, L, L) :- !.
normalise(N, L1, L) :-
N1 is N - 1,
normalise(N1, [48 | L1], L).
% contrary of normalise
% remove leading zeros.
% special case of number 0 !
strip_nombre([48]) --> {!}, "0".
% enlève les zéros inutiles
strip_nombre([48 | L]) -->
strip_nombre(L).
strip_nombre(L) -->
L.

View file

@ -0,0 +1,170 @@
:- module('bt_mult.pl', [op(850, xfx, btmult),
btmult/2,
multiplication/3
]).
:- use_module('bt_add.pl').
:- op(850, xfx, btmult).
A is B btmult C :-
multiplication(B, C, A).
neg(A, B) :-
maplist(opp, A, B).
opp(48, 48).
opp(45, 43).
opp(43, 45).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% the multiplication (efficient)
% multiplication(+BIn, +QIn, -AOut)
% Aout is BIn * QIn
% BIn, QIn, AOut are strings
multiplication(BIn, QIn, AOut) :-
string_to_list(BIn, B),
string_to_list(QIn, Q),
% We work with positive numbers
( B = [45 | _] -> Pos0 = false, neg(B,BP) ; BP = B, Pos0 = true),
( Q = [45 | _] -> neg(Q, QP), select(Pos0, [true, false], [Pos1]); QP = Q, Pos1 = Pos0),
multiplication_(BP, QP, [48], A),
( Pos1 = false -> neg(A, A1); A1 = A),
string_to_list(AOut, A1).
multiplication_(_B, [], A, A).
multiplication_(B, [H | T], A, AF) :-
multiplication_1(B, H, B1),
append(A, [48], A1),
bt_add1(B1, A1, A2),
multiplication_(B, T, A2, AF).
% by 1 (digit '+' code 43)
multiplication_1(B, 43, B).
% by 0 (digit '0' code 48)
multiplication_1(_, 48, [48]).
% by -1 (digit '-' code 45)
multiplication_1(B, 45, B1) :- neg(B, B1).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% the division (efficient)
% division(+AIn, +BIn, -QOut, -ROut)
%
division(AIn, BIn, QOut, ROut) :-
string_to_list(AIn, A),
string_to_list(BIn, B),
length(B, LB),
length(A, LA),
Len is LA - LB,
( Len < 0 -> Q = [48], R = A
; neg(B, NegB), division_(A, B, NegB, LB, Len, [], Q, R)),
string_to_list(QOut, Q),
string_to_list(ROut, R).
division_(A, B, NegB, LenB, LenA, QC, QF, R) :-
% if the remainder R is negative (last number A), we must decrease the quotient Q, annd add B to R
( LenA = -1 -> (A = [45 | _] -> positive(A, B, QC, QF, R) ; QF = QC, A = R)
; extract(LenA, _, A, AR, AF),
length(AR, LR),
( LR >= LenB -> ( AR = [43 | _] ->
bt_add1(AR, NegB, S), Q0 = [43],
% special case : R has the same length than B
% and his first digit is + (1)
% we must do another one substraction
( (length(S, LenB), S = [43|_]) ->
bt_add1(S, NegB, S1),
bt_add1(QC, [43], QC1),
Q00 = [45]
; S1 = S, QC1 = QC, Q00 = Q0)
; bt_add1(AR, B, S1), Q00 = [45], QC1 = QC),
append(QC1, Q00, Q1),
append(S1, AF, A1),
strip_nombre(A1, A2, []),
LenA1 is LenA - 1,
division_(A2, B, NegB, LenB, LenA1, Q1, QF, R)
; append(QC, [48], Q1), LenA1 is LenA - 1,
division_(A, B, NegB, LenB, LenA1, Q1, QF, R))).
% extract(+Len, ?N1, +L, -Head, -Tail)
% remove last N digits from the list L
% put them in Tail.
extract(Len, Len, [], [], []).
extract(Len, N1, [H|T], AR1, AF1) :-
extract(Len, N, T, AR, AF),
N1 is N-1,
( N > 0 -> AR = AR1, AF1 = [H | AF]; AR1 = [H | AR], AF1 = AF).
positive(R, _, Q, Q, R) :- R = [43 | _].
positive(S, B, Q, QF, R ) :-
bt_add1(S, B, S1),
bt_add1(Q, [45], Q1),
positive(S1, B, Q1, QF, R).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% "euclidian" division (inefficient)
% euclide(?A, +BIn, ?Q, ?R)
% A = B * Q + R
euclide(A, B, Q, R) :-
mult(A, B, Q, R).
mult(AIn, BIn, QIn, RIn) :-
( nonvar(AIn) -> string_to_list(AIn, A); A = AIn),
( nonvar(BIn) -> string_to_list(BIn, B); B = BIn),
( nonvar(QIn) -> string_to_list(QIn, Q); Q = QIn),
( nonvar(RIn) -> string_to_list(RIn, R); R = RIn),
% we use positive numbers
( B = [45 | _] -> Pos0 = false, neg(B,BP) ; BP = B, Pos0 = true),
( (nonvar(Q), Q = [45 | _]) -> neg(Q, QP), select(Pos0, [true, false], [Pos1])
; nonvar(Q) -> Q = QP , Pos1 = Pos0
; Pos1 = Pos0),
( (nonvar(A), A = [45 | _]) -> neg(A, AP)
; nonvar(A) -> AP = A
; true),
% is R instancied ?
( nonvar(R) -> R1 = R; true),
% multiplication ? we add B to A and substract 1 (digit '-') to Q
( nonvar(Q) -> BC = BP, Ajout = [45],
( nonvar(R) -> bt_add1(BC, R, AP) ; AP = BC)
% division ? we substract B to A and add 1 (digit '+') to Q
; neg(BP, BC), Ajout = [43], QP = [48]),
% do the real job
mult_(BC, QP, AP, R1, Resultat, Ajout),
( var(QIn) -> (Pos1 = false -> neg(Resultat, QT); Resultat = QT), string_to_list(QIn, QT)
; true),
( var(AIn) -> (Pos1 = false -> neg(Resultat, AT); Resultat = AT), string_to_list(AIn, AT)
; true),
( var(RIn) -> string_to_list(RIn, R1); true).
% @arg1 : divisor
% @arg2 : quotient
% @arg3 : dividend
% @arg4 : remainder
% @arg5 : Result : receive either the dividend A
% either the quotient Q
mult_(B, Q, A, R, Resultat, Ajout) :-
bt_add1(Q, Ajout, Q1),
bt_add1(A, B, A1),
( Q1 = [48] -> Resultat = A % a multiplication
; ( A1 = [45 | _], Ajout = [43]) -> Resultat = Q, R = A % a division
; mult_(B, Q1, A1, R, Resultat, Ajout)) .