prolog convert numbers into roman numerals - numbers

i have this code that converts integers into roman numerals
i need to add a function that compares an integer with a roman numeral input and show if it's try or false, for example:
roman(v,5).
true
toroman(0).
toroman(N) :- N < 4, put("I"), M is N - 1, toroman(M).
toroman(N) :- N = 4, put("I"), put("V").
toroman(N) :- N = 5, put("V").
toroman(N) :- N < 9, put("V"), M is N - 5, toroman(M).
toroman(N) :- N = 9, put("I"), put("X").
toroman(N) :- N < 40, put("X"), M is N - 10, toroman(M).
toroman(N) :- N < 50, put("X"), put("L"), M is N - 40, toroman(M).
toroman(N) :- N < 90, put("L"), M is N - 50, toroman(M).
toroman(N) :- N < 100, put("X"), put("C"), M is N - 90, toroman(M).
toroman(N) :- N < 400, put("C"), M is N - 100, toroman(M).
toroman(N) :- N < 500, put("C"), put("D"), M is N - 400, toroman(M).
toroman(N) :- N < 900, put("D"), put("D"), M is N - 500, toroman(M).
toroman(N) :- N < 1000, put("C"), put("M"), M is N - 900, toroman(M).
toroman(N) :- N < 4000, put("M"), M is N - 1000, toroman(M).
roman(N) :- toroman(N).

Try to formulate the problem differently: Write a grammar (dcg) to relate an integer and a list of characters denoting roman numerals. Here is a start:
:- use_module(library(clpfd)).
roman(0) --> "".
roman(N0) --> "I", { 1 #=< N0, N0 #=< 3, N1 #= N0-1}, roman(N1).
You can use it like so:
?- phrase(roman(3), L).
L = "III"
; false.
or
?- phrase(roman(N), "II").
N = 2
; false.
or, if you don't know what to ask, simply ask the most general question:
?- phrase(roman(N), L).
N = 0, L = []
; N = 1, L = "I"
; N = 2, L = "II"
; N = 3, L = "III"
; false.
To get answers compactly like L = "III", use :- set_prolog_flag(double_quotes,chars). See this answer for more.

You should change your toroman/1 procedure to something like toroman/2 that returns the roman numeral instead of just printing it.
Then you would be able to easily compare a roman numeral with the result from calling toroman/2 to the integer.
Note also that your current procedure will loop until getting a stack overflow if you backtrack for another solution. You should either guard each clause that recursively calls itself to recurse only if the parameter of the call is non-negative or add as the first clause a check that fails safely, e.g.:
roman(N):- N < 0, !, fail.
After changing toroman/1 to return the roman literal you would get something like this (just modified a bit your code to return the literal as the second argument):
toroman(N, _):- N < 0, !, fail.
toroman(0, []).
toroman(N, ['I'|Roman]) :- N < 4, M is N - 1, toroman(M, Roman).
toroman(4, ['IV']).
toroman(5, ['V']).
toroman(N, ['V'|Roman]) :- N < 9, M is N - 5, toroman(M, Roman).
toroman(9, ['IX']).
toroman(N, ['X'|Roman]) :- N < 40, M is N - 10, toroman(M, Roman).
toroman(N, ['XL'|Roman]) :- N < 50, M is N - 40, toroman(M, Roman).
toroman(N, ['L'|Roman]) :- N < 90, M is N - 50, toroman(M, Roman).
toroman(N, ['XC'|Roman]) :- N < 100, M is N - 90, toroman(M, Roman).
toroman(N, ['C'|Roman]) :- N < 400, M is N - 100, toroman(M, Roman).
toroman(N, ['CD'|Roman]) :- N < 500, M is N - 400, toroman(M, Roman).
toroman(N, ['DD'|Roman]) :- N < 900, M is N - 500, toroman(M, Roman).
toroman(N, ['CM'|Roman]) :- N < 1000, M is N - 900, toroman(M, Roman).
toroman(N, ['M'|Roman]) :- N < 4000, M is N - 1000, toroman(M, Roman).
roman(N, R) :- toroman(N, L), atomic_list_concat(L, R).
roman(N) :- roman(N, R), write(R).
Then you could simply call roman(N, R) and test whether R unifies with your roman numeral of interest.

Related

MiniZinc does not find a solution to the scheduling problem

I have a problem finding a solution using MiniZinc.
The task:
It is necessary to make a schedule of shifts for employees.
In one day there are three shifts: day (D), evening (E) and night (N).
It is necessary to draw up an optimal schedule, if possible avoiding undesirable situations:
Avoid single shifts (one shift between two breaks)
Avoid single breaks (shift, break, shift)
Avoid double breaks (shift, break, break, shift)
After a night shift should be a full day off (three breaks in a row)
To find a solution, I minimize the number of undesirable situations.
When I start the calculation, MiniZinc displays several intermediate variants, but does not find a final solution.
Is it possible to somehow optimize the calculations?
include "regular.mzn";
int: n = 21;
int: m = 6;
set of int: D = 1..n;
set of int: E = 1..m;
% Number of employees per shift
%|Sun |Mon |Tue |Wen |Thur |Fri |Sat |
array[D] of int: SHIFTS = [2, 2, 2, 2, 2, 1, 2, 2, 1, 2, 2, 1, 2, 2, 1, 2, 2, 1, 2, 2, 1];
/*2, 2, 1, 2, 2, 1, 2, 2, 1, 2, 2, 1, 2, 2, 1, 2, 2, 1, 2, 2, 1,
2, 2, 1, 2, 2, 1, 2, 2, 1, 2, 2, 1, 2, 2, 1, 2, 2, 1, 2, 2, 1,
2, 2, 1, 2, 2, 1, 2, 2, 1, 2, 2, 1, 2, 2, 1, 2, 2, 1, 2, 2, 2];*/
% The range of the number of shifts per employee for the period ([|from, to)
array[E, 1..2] of int: DC_SHIFTS = [|0, 10 %emp1
|0, 10 %emp2
|0, 10 %emp3
|0, 10 %emp4
|0, 10 %emp5
|0, 10 %emp6
|];
%-------------------------------------------------
% Variables
%-------------------------------------------------
array[E, D] of var 1..4: X;
% Counters of avoidable situations
var int: OS_PENALTY; % break, shift, break (single shift)
var int: NS_PENALTY; % night shift, not break, not break, not break (full day off after a night shift)
var int: DS_PENALTY; % shift, break, break, shift (two breaks between shifts)
var int: OO_PENALTY; % shift, break, shift (one break between shifts)
%-------------------------------------------------
% Constraints
%-------------------------------------------------
constraint
forall(d in D)(
sum(e in E)(bool2int(X[e, d] != 4)) = SHIFTS[d]
);
constraint
forall(e in E)(
sum(d in D)(bool2int(X[e, d] != 4)) >= DC_SHIFTS[e, 1]
/\
sum(d in D)(bool2int(X[e, d] != 4)) < DC_SHIFTS[e, 2]
);
constraint
forall(d in D)(
if d mod 3 = 1 then forall(e in E)(X[e, d] = 1 \/ X[e, d] = 4) else
if d mod 3 = 2 then forall(e in E)(X[e, d] = 2 \/ X[e, d] = 4) else
forall(e in E)(X[e, d] = 3 \/ X[e, d] = 4) endif endif
);
NS_PENALTY = sum(e in E, d in D where d < max(D) - 2)(bool2int(
X[e, d] = 3 \/ (X[e,d+1] != 4 /\ X[e,d + 2] != 4 /\ X[e,d + 3] != 4)
));
DS_PENALTY = sum(e in E, d in D where d < max(D) - 2)(bool2int(X[e, d] != 4 \/ X[e, d + 1] = 4 \/ X[e, d + 2] = 4 \/ X[e, d + 3] != 4));
OS_PENALTY = sum(e in E, d in D where d < max(D) - 1)(bool2int(X[e, d] = 4 /\ X[e, d + 1] != 4 /\ X[e, d + 2] = 4));
OO_PENALTY = sum(e in E, d in D where d < max(D) - 1)(bool2int(X[e, d] != 4 \/ X[e, d + 1] = 4 \/ X[e, d + 2] != 4));
%-------------------------------------------------
% Solve
%-------------------------------------------------
solve minimize OS_PENALTY + NS_PENALTY + DS_PENALTY + OO_PENALTY;
%-------------------------------------------------
% Output
%-------------------------------------------------
array[1..4] of string: rest_view = ["D", "E", "N", "-"];
output
[
rest_view[fix(X[e, d])] ++
if d = n then "\n" else "" endif
| e in E, d in D
];
I suggest the following changes to your model:
Change the declaration of X to array[E, D] of var 0..1: X; where 0 means break and 1 shift. Whether it's a day, evening or night shift is handled in the output section, where the results are transformed to show the shift type like if fix(X[e, d]) == 0 then "-" else rest_view[1 + (d-1) mod 3] endif.
Rewrite the constraints using globals like:
import "globals.mzn";
constraint
forall(d in D)(
exactly(SHIFTS[d], col(X, d), 1)
%sum(e in E)(bool2int(X[e, d] != 0)) = SHIFTS[d]
);
constraint
forall(e in E)(
global_cardinality_low_up(row(X, e), [1], [DC_SHIFTS[e, 1]], [DC_SHIFTS[e, 2] - 1])
%sum(d in D)(bool2int(X[e, d] != 0)) >= DC_SHIFTS[e, 1]
%/\
%sum(d in D)(bool2int(X[e, d] != 0)) < DC_SHIFTS[e, 2]
);
%constraint
% forall(d in D)(
% if d mod 3 = 1 then forall(e in E)(X[e, d] = 1 \/ X[e, d] = 4) else
% if d mod 3 = 2 then forall(e in E)(X[e, d] = 2 \/ X[e, d] = 4) else
% forall(e in E)(X[e, d] = 3 \/ X[e, d] = 4) endif endif
% );
Rewrite the penalties like:
NS_PENALTY = sum(e in E, d in 1..n - 3 where d mod 3 = 0)(bool2int(
X[e, d] = 1 /\ (sum(i in 1..3)(X[e,d+i]) > 0)
));
DS_PENALTY = sum(e in E, d in 1..n - 3)(bool2int(X[e, d] != 0 /\ X[e, d + 1] = 0 /\ X[e, d + 2] = 0 /\ X[e, d + 3] != 0));
OS_PENALTY = sum(e in E, d in 1..n - 2)(bool2int(X[e, d] = 0 /\ X[e, d + 1] != 0 /\ X[e, d + 2] = 0));
OO_PENALTY = sum(e in E, d in 1..n - 2)(bool2int(X[e, d] != 0 /\ X[e, d + 1] = 0 /\ X[e, d + 2] != 0));

Pumping Lemma problems for determining Regular Language and CFL

{a^p b^p; p is a prime number}
{a^p b^p; p is a prime number, m is a fixed number and m≥p≥0}
How do I prove if this is a regular language/context free language (or not)?
1) L = {a^n b^n; n is a prime number} :
So the prove can be done by contradiction. Suppose L is regular, and p is the pumping length.
The test string is w = a^p b^p, w belongs to L, and |w| = 2p >= p
We subdivide w=xyz. There are 3 conditions to prove the pumping lemma:
from the third condition, |xy| < p, so xy contains only a's
from the second condition, |y| > 0, so y has the form y = a^k, where 1 <= k <= p
from the first condition, xy^iz belongs to L for i = 0, 1, 2, ... So if you pump down (i = 0) you got:
w = a^(p - k) b^p , and w does not belongs to L (Because the quantity of a's and b's are different)
So you prove that L is not regular.

Summing up special columns of two matrix in Matlab

How can I do below calculations (finding C) without using "for loop"?
[4, 2, 1, 7;
A = 0, 3, 4, 0;
8, 0, 10, 12;
11, 6, 2, 5];
[1, 0, 0, 4;
B = 0, 3, 2, 0;
5, 0, 8, 10;
7, 2, 1, 2];
C(i,j)= B(i,j-1) - B(i,j+1) + A(i,j+1); %if j is not equal to 4(number of columns) and it is not equal to 1
C(i,j)= B(i,4) - B(i,j+1) + A(i,j+1); %if j is equal to 1
C(i,j)= B(i,j-1) - B(i,1) + A(i,1); %if j is equal to 4(number of columns)
You can specify an array as index to work on multiple element at the same time:
A=[4,2,1,7;0,3,4,0;8,0,10,12;11,6,2,5];
B=[1,0,0,4;0,3,2,0;5,0,8,10;7,2,1,2];
C = zeros(size(A));
C(:,2:end-1) = B(:,1:end-2) - B(:,3:end) + A(:,3:end); %if j is not equal to 4(number of columns) and it is not equal to 1
j = 1;
C(:,j)= B(:,4) - B(:,j+1) + A(:,j+1); %if j is equal to 1
j = 4;
C(:,j)= B(:,j-1) - B(:,1) + A(:,1); %if j is equal to 4(number of columns)

What does scipy.interpolate.InterpolatedUnivariateSpline.get_coeffs return?

I tried the following:
spline= interpolate.InterpolatedUnivariateSpline(X, Y, k=3)
coefs= spline.get_coeffs()
With five values in each of X and Y, I ended up with coefs also having
five values. Given that five data points implies four spline sections, and
that a cubic polynomial has four coefficients, I would have expected to get
four times four= 16 coefficients. Does anyone know how to interpret the values that are returned by the get_coeffs method? Is there any place where this is documented?
These are not the coefficients of x, x**2, and so forth: such monomials are ill-suited to representing splines. Rather, they are coefficients of B-splines which are computed for the specific grid on which interpolation is done. The number of B-splines involved is equal to the number of data points, and so is the number of coefficients. As an example, suppose we want to interpolate these data:
xv = [0, 1, 2, 3, 4, 5]
yv = [3, 6, 5, 7, 9, 1]
Begin with the simpler case of degree k=1 (piecewise linear spline). Then the B-splines are these "triangular hat" functions:
There are 6 of them. Each of them is equal to 1 at "its" grid point, and 0 at all other grid points. This makes it really easy to write the interpolating spline: it is y[0]*b[0] + ... + y[5]*b[5]. And indeed, get_coeffs shows the coefficients are the the y-values themselves.
InterpolatedUnivariateSpline(xv, yv, k=1).get_coeffs() # [ 3., 6., 5., 7., 9., 1.]
Cubic splines
Now it gets hairy, because we need "hats" that are smooth, rather than pointy as those above. The smoothness requirement forces them to be wider, so each B-spline has nonzero values on several grid points. (Technicality: a cubic B-spline has nonzero values at up to 3 knots, but on the chart below, 1 and 4, despite being grid points, are not knots due to so-called "not a knot" condition. Never mind this.) Here are the B-splines for our grid:
To get these, I used older methods splrep and splev of scipy.interpolate, which call the same fitpack routines under the hood. The coefficient vector here is the second entry of the tuple tck; I modify it to have one 1 and the rest 0, thus creating a basis spline (b-spline).
k = 3
tck = splrep(xv, yv, s=0, k=k)
xx = np.linspace(min(xv), max(xv), 500)
bsplines = []
for j in range(len(xv)):
tck_mod = (tck[0], np.arange(len(xv)+2*k-2) == j, k)
bsplines.append(splev(xx, tck_mod))
plt.plot(xx, bsplines[-1])
Now that we have a list bsplines, we can use the coefficients returned by get_coeffs to put them together ourselves into an interpolating spline:
coeffs = InterpolatedUnivariateSpline(xv, yv, k=3).get_coeffs()
interp_spline = sum([coeff*bspline for coeff, bspline in zip(coeffs, bsplines)])
plt.plot(xx, interp_spline)
If you want a formula for the pieces of these B-splines, the Cox-de Boor recursion formula on B-splines can help but these are a chore to compute by hand.
SymPy can give formulas for B-splines, but there is a little twist. One should pass in a padded set of knots, by repeating the end values like
[0, 0, 0, 0, 2, 3, 5, 5, 5, 5]
This is because at 0 and 5 all four coefficients change values, while at 1 and 4 none of them do, so they are omitted ("not a knot"). (Also, the current version of SymPy (1.1.1) has an issue with repeated knots, but this will be fixed in the next version.)
from sympy import symbols, bspline_basis_set, plot
x = symbols('x')
xv_padded = [0, 0, 0, 0, 2, 3, 5, 5, 5, 5]
bs = bspline_basis_set(3, xv_padded, x)
Now bs is an array of scary-looking piecewise formulas:
[Piecewise((-x**3/8 + 3*x**2/4 - 3*x/2 + 1, (x >= 0) & (x <= 2)), (0, True)),
Piecewise((19*x**3/72 - 5*x**2/4 + 3*x/2, (x >= 0) & (x <= 2)), (-x**3/9 + x**2 - 3*x + 3, (x >= 2) & (x <= 3)), (0, True)),
Piecewise((-31*x**3/180 + x**2/2, (x >= 0) & (x <= 2)), (11*x**3/45 - 2*x**2 + 5*x - 10/3, (x >= 2) & (x <= 3)), (-x**3/30 + x**2/2 - 5*x/2 + 25/6, (x >= 3) & (x <= 5)), (0, True)),
Piecewise((x**3/30, (x >= 0) & (x <= 2)), (-11*x**3/45 + 5*x**2/3 - 10*x/3 + 20/9, (x >= 2) & (x <= 3)), (31*x**3/180 - 25*x**2/12 + 95*x/12 - 325/36, (x >= 3) & (x <= 5)), (0, True)),
Piecewise((x**3/9 - 2*x**2/3 + 4*x/3 - 8/9, (x >= 2) & (x <= 3)), (-19*x**3/72 + 65*x**2/24 - 211*x/24 + 665/72, (x >= 3) & (x <= 5)), (0, True)),
Piecewise((x**3/8 - 9*x**2/8 + 27*x/8 - 27/8, (x >= 3) & (x <= 5)), (0, True))]

Macro unexpectedly redefined

I have the following:
#define PAD ( 4 - ( (WIDTH*BPP)%4 ) )
#if PAD == 4
#define PAD 0
#endif
and PAD is redefined even though it is equal to 3 after the first definition. However if I explicitly define it as 3 then it isn't redefined. Therefore I assume there is a problem with the way I have written the expression, but I'm not sure what.
What you want is
(PAD + (WIDTH * BPP)) % 4 == 0
right? (Of course 0 <= PAD < 4)
Then you can define PAD in this way:
#define PAD (3 - ((WIDTH * BPP + 3) % 4))
Example Python session:
>>> def f(x): return 3 - (x+3)%4
...
>>> [ (x, f(x), x + f(x)) for x in xrange(100,108) ]
[(100, 0, 100), (101, 3, 104), (102, 2, 104), (103, 1, 104), (104, 0, 104), (105, 3, 108), (106, 2, 108), (107, 1, 108)]
In general,
#define PAD ((N-1) - (X + (N-1)) % N))
makes PAD + X a multiple of N under a constraint of 0 <= PAD < N (Though I didn't check negative cases...)