A Dutch bank account consists of 9 digits e.g.: 1334.36.915.
To check whether the bank account is valid we use the so called ‘11-proef’ (11-test).
In this test each digit is multiplied with its place in the row.The result of this multiplication is added up.
(1*9)+(3*8)+(3*7)+(4*6)+(3*5)+(6*4)+(9*3)+(1*2)+(5*1) = R
This result has to be dividable by 11. That means the remainder of the division must be 0.
If the R is dividable by 11 the bank account number is valid!
Can someone help with this question?
A Dutch bank account number does not consist of 9 digits anymore, we now use Iban Numbers. If you want to do a check on it, you should have a look at https://en.wikipedia.org/wiki/International_Bank_Account_Number#Validating_the_IBAN and implement that check.
For now, you can however still to the 11-check on the last 9 or 10 digits, but it's not guaranteed that will still work for new bank accounts in the future.
If you still want to do a 11-check, you can create a function like this:
CREATE OR REPLACE FUNCTION elfproof (accountnummer IN varchar2)
RETURN VARCHAR2
AS
multiplier int:= 10;
outcome varchar2(10);
total int := 0;
BEGIN
FOR i IN 1 .. 9
LOOP
multiplier := multiplier - 1;
total := total + (multiplier * TO_NUMBER (SUBSTR (accountnummer, i, 1)));
END LOOP;
IF MOD (total, 11) = 0
THEN
outcome := 'good';
ELSE
outcome := 'bad';
END IF;
return outcome;
END;
This gives the remainder of division on 11:
SELECT
MOD (SUM (TO_NUMBER (SUBSTR (str, LEVEL, 1)) * (10 - LEVEL)), 11) remdiv11
FROM
(
SELECT
REPLACE ('1334.36.915', '.') str
FROM
DUAL
) d
CONNECT BY LEVEL <= LENGTH (str)
and IBAN check;) :
SELECT
DECODE (MOD (TO_NUMBER (LISTAGG (n, '') WITHIN GROUP (ORDER BY l)), 97), 1, 'OK', 'Fail') AS iban_check
FROM
(
SELECT
TO_CHAR (CASE
WHEN ASCII (c) >= 65 THEN ASCII (c) - 55
ELSE ASCII (c) - 48 END) n, c, l
FROM
(
SELECT
SUBSTR (str, LEVEL, 1) c, LEVEL l
FROM
(
SELECT
SUBSTR (s, 5) || SUBSTR (s, 1, 4) str
FROM
(
SELECT
REPLACE ('GB82 WEST 1234 5698 7654 32', ' ') s
FROM
DUAL
)
)
CONNECT BY LEVEL <= LENGTH (str)
)
)
Related
This function is a school practice problem (it is running but does not work properly).
My task is to call for a integer from the user.
When the number arrives, my task is to write out (with a recursive algorithm)
what is the sum of the number with the numbers before the given number.
For example if our number is 10 then the upshot is 55 because 1+2+3+4+5+6+7+8+9+10 = 55, etc.
I've already tried to write this code:
function egesszamosszeg(n:integer) : integer;
begin
egesszamosszeg:=0
if n=1 then
egesszamosszeg:=1
else
for n:=1 to egesszamosszeg do
begin
egesszamosszeg:=egesszamosszeg+1;
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
var egesszam:integer;
begin
egesszam:=strtoint(Inputbox('','Give an integer please!',''));
Showmessage(inttostr(Egesszamosszeg(egesszam)));
end;
My problem is that I do not know what is the main problem with this code.
I do not know what is the main problem with this code.
There are several problems with your code: it's iterative, not recursive; it's way too complicated; this loop:
for n:=1 to egesszamosszeg do
is effectively:
for n:=1 to 0 do
Consider this simple function which effectively implements the gist of your problem:
function egesszamosszeg(n:integer) : integer;
begin
egesszamosszeg := n;
if (n > 1) then
egesszamosszeg := egesszamosszeg + egesszamosszeg(n - 1);
end;
begin
writeln(egesszamosszeg(10));
end.
You are simply trying to increment egesszamosszeg (couldn't you use an easier name?), instead of adding the consecutive numbers to it. But your loop is wrong: eggesszamosszeg is 0, so you are in fact doing for n := 1 to 0 do. That loop will never run. Don't re-use n, use another variable for the loop index:
for i := 1 to n do
egesszamosszeg := egesszamosszeg + i;
But you say it must be recursive, so it must call itself with a different parameter value. Then do something like:
function egesszamosszeg(n: integer): integer;
begin
if n = 1 then // terminating condition
egesszamosszeg := 1
else
egesszamosszeg := n + egesszamosszeg(n - 1); // recursion
end;
In most Pascals, you can use the pseudo-variable Result instead of the function name. Often, that makes typing a little easier.
FWIW, did you know that you could make this a little simpler and do not need recursion or iteration at all? The result can be calculated directly:
function egesszamosszeg(n: Integer): Integer;
begin
result := n * (n + 1) div 2;
end;
For 1..10, that will give 10 * 11 div 2 = 55 too.
See: https://www.wikihow.com/Sum-the-Integers-from-1-to-N
In effect, you count (1+10) + (2+9) + (3+8) + (4+7) + (5+6) = 5 * 11 = 55. You can do the same for any positive number. Same with 1..6: (1+6) + (2+5) + (3+4) = 3 * 7 = 21.
That leads to the formula:
sum = n * (n + 1) div 2
(or actually:
n div 2 * (n+1) // mathematically: n/2 * (n+1)
which is the same).
I have the following program:
procedure Main with SPARK_Mode is
F : array (0 .. 10) of Integer := (0, 1, others => 0);
begin
for I in 2 .. F'Last loop
F (I) := F (I - 1) + F (I - 2);
end loop;
end Main;
If I run gnatprove, I get the following result, pointing to the + sign:
medium: overflow check might fail
Does this mean that F (I - 1) could be equal to Integer'Last, and adding anything to that would overflow? If so, then is it not clear from the flow of the program that this is impossible? Or do I need to specify this with a contract? If not, then what does it mean?
A counterexample shows that indeed gnatprove in this case worries about the edges of Integer:
medium: overflow check might fail (e.g. when F = (1 => -1, others => -2147483648) and I = 2)
Consider adding a loop invariant to your code. The following is an example from the book "Building High Integrity Applications with Spark".
procedure Copy_Into(Buffer : out Buffer_Type;
Source : in String) is
Characters_To_Copy : Buffer.Count_Type := Maximum_Buffer_Size;
begin
Buffer := (Others => ' '); -- Initialize to all blanks
if Source'Length < Characters_To_Copy then
Characters_To_Copy := Source'Length;
end if;
for Index in Buffer.Count_Type range 1..Characters_To_Copy loop
pragma Loop_Invariant
(Characters_To_Copy <= Source'Length and
Characters_To_Copy = Characters_To_Copy'Loop_Entry);
Buffer (Index) := Source(Source'First + (Index - 1));
end loop;
end Copy_Into;
This is already an old question, but I would like to add an answer anyway (just for future reference).
With the advancement of provers, the example as stated in the question now proves out-the-box in GNAT CE 2019 (i.e. no loop invariant needed). A somewhat more advanced example can also be proven:
main.adb
procedure Main with SPARK_Mode is
-- NOTE: The theoretical upper bound for N is 46 as
--
-- Fib (46) < 2**31 - 1 < Fib (47)
-- 1_836_311_903 < 2_147_483_647 < 2_971_215_073
-- NOTE: Proved with Z3 only. Z3 is pretty good in arithmetic. Additional
-- options for gnatprove:
--
-- --prover=Z3 --steps=0 --timeout=10 --report=all
type Seq is array (Natural range <>) of Natural;
function Fibonacci (N : Natural) return Seq with
Pre => (N in 2 .. 46),
Post => (Fibonacci'Result (0) = 0)
and then (Fibonacci'Result (1) = 1)
and then (for all I in 2 .. N =>
Fibonacci'Result (I) = Fibonacci'Result (I - 1) + Fibonacci'Result (I - 2));
---------------
-- Fibonacci --
---------------
function Fibonacci (N : Natural) return Seq is
F : Seq (0 .. N) := (0, 1, others => 0);
begin
for I in 2 .. N loop
F (I) := F (I - 1) + F (I - 2);
pragma Loop_Invariant
(for all J in 2 .. I =>
F (J) = F (J - 1) + F (J - 2));
-- NOTE: The loop invariant below helps the prover to proof the
-- absence of overflow. It "reminds" the prover that all values
-- from iteration 3 onwards are strictly monotonically increasing.
-- Hence, if absence of overflow is proven in this iteration,
-- then absence is proven for all previous iterations.
pragma Loop_Invariant
(for all J in 3 .. I =>
F (J) > F (J - 1));
end loop;
return F;
end Fibonacci;
begin
null;
end Main;
This loop invariant should work - since 2^(n-1) + 2^(n-2) < 2^n - but I can't convince the provers:
procedure Fibonacci with SPARK_Mode is
F : array (0 .. 10) of Natural := (0 => 0,
1 => 1,
others => 0);
begin
for I in 2 .. F'Last loop
pragma Loop_Invariant
(for all J in F'Range => F (J) < 2 ** J);
F (I) := F (I - 1) + F (I - 2);
end loop;
end Fibonacci;
You can probably convince the provers with a bit of manual assistance (showing how 2^(n-1) + 2^(n-2) = 2^(n-2) * (2 + 1) = 3/4 * 2^n < 2^n).
I have read a lot of XQuery position, but all examples are about >, <, or =. But you can also use x - y and I am confused as to what is inclusive and what is not.
[position() = $startPosition to $endPosition]
Let's say $startPosition is 1 (as I have read that position does not start with 0 but with 1), what will return the first hit? $endPosition set to 1 as well, or to 2?
In other words, given an expected return of n, what would be the formula for both variables? To make things more clear, we can add an incrementing loop ($iteration). Basically we are generating a search that will find all subsequent hits with position. (As an example.)
$endPosition = 1 + ($iteration * n);
$startPosition = $endPosition - n;
This is what I came up with. This will result in the following outcome, for $iteration starting from 1 and incrementing, and n of 3.
1:
$endPosition = 1 + (1 * 3); // 4
$startPosition = 4 - 3; // 1
2:
$endPosition = 1 + (2 * 3); // 7
$startPosition = 7 - 3; // 4
3:
$endPosition = 1 + (3 * 3); // 10
$startPosition = 10 - 3; // 7
But, is this correct? I am not sure. Is the $endPosition included? If not, my code is correct, if not - it isn't, and then I am interested in the correct formula.
The expression $sequence[position() = $a to $b] is equivalent to the following FLWOR expression (where $position start at 1):
for $x at $position in $seq
where $position >= $a and $position <= $b
return $x
So to skip the first two items and then return the following five, you need $seq[position() = 3 to 7].
Here is how you can go from this to a subsequence function that uses a 0-based offset and the number of items to return:
declare function local:subsequence(
$seq as item()*,
$offset as xs:integer,
$length as xs:integer
) as item()* {
let $start := $offset + 1,
$end := $offset + $length
return $seq[position() = $start to $end]
};
local:subsequence(1 to 100, 0, 5), (: returns (1, 2, 3, 4, 5) :)
local:subsequence(1 to 100, 13, 3) (: returns (14, 15, 16) :)
It's unclear the specific problem you're trying to solve, so I don't know if this answers your question, but let's unpack that expression first:
[position() = $startPosition to $endPosition]
Say $startPosition is 1 and $endPosition is 3. That will evaluate to:
[position() = (1, 2, 3)]
That predicate will return true any time position() equals any of the values in the sequence on the right.
I am trying to find the greatest common factor for some numbers that i have put into a table. So far I have the function that is suppose to calculate the gcf
CREATE FUNCTION gcd (x INTEGER, y INTEGER) RETURN INTEGER AS
ans INTEGER;
BEGIN
IF (y <= x) AND (x MOD y = 0) THEN
ans := y;
ELSIF x < y THEN
ans := gcd(y, x);
ELSE
ans := gcd(y, x MOD y);
END IF;
RETURN ans;
END;
and here I create and random populate my table
DROP TABLE numere
/
CREATE TABLE numbers (number NUMBER(3) NOT NULL)
/
set serveroutput on
DECLARE
number NUMBER(3);
cursor c1 is
SELECT * FROM note;
BEGIN
FOR i IN 1 .. 10 LOOP
number:=dbms_random.value(20,100);
insert into numbers values(number);
end loop;
commit;
END;
/
How can I integrate the gcf into my code? I want to display the numbers followed by their gcf.
I am not sure about your gcd function. It seems to me not working. There are many on the web. This is one of them:
CREATE OR REPLACE FUNCTION find_gcd (
p_n1 IN POSITIVE
, p_n2 IN POSITIVE
)
RETURN POSITIVE
IS
l_n1 POSITIVE := p_n1;
l_n2 POSITIVE := p_n2;
BEGIN
WHILE NOT (l_n1 = l_n2)
LOOP
CASE SIGN(l_n1 - l_n2)
WHEN +1
THEN l_n1 := l_n1 - l_n2;
ELSE l_n2 := l_n2 - l_n1;
END CASE;
END LOOP;
RETURN (l_n1);
END find_gcd;
/
You can simply amend your PL/SQL block to call the gcd function and print out the results (I here assumed you want to find the gcd for each number and the following number in your table, so I used LEAD function):
DECLARE
lv_number NUMBER(3);
lv_gcd INTEGER;
BEGIN
FOR i IN 1 .. 10 LOOP
lv_number:=dbms_random.value(20,100);
insert into numbers values(lv_number);
end loop;
commit;
FOR i in (select COL_VAL, lead(COL_VAL) over (order by rowid) nxt_val from numbers)
LOOP
lv_gcd := find_gcd(i.COL_VAL, i.nxt_val);
DBMS_OUTPUT.PUT_LINE('GCD for '||TO_CHAR(i.COL_VAL)||' and '|| TO_CHAR(i.nxt_val) ||' is '||TO_CHAR(lv_gcd));
END LOOP;
END;
/
I've been learning Pascal (using the Free Pascal compiler) for a week now, and came across a seemingly easy exercise. Given a structure as shown below, find the maximal weighted branch:
1
4 9
7 0 2
4 8 6 3
A branch is any sequence of numbers, starting from the top (in this case: 1), when for every number the branch can expand either down-left or down-right. For example, the branch 1-4-0 can expand into either 1-4-0-8 or 1-4-0-6. All branches must start from the top and end at the bottom.
In this example, the maximal branch is 1-4-7-8, which gives us 20. In order to solve this question, I tried to use backtracking. The triangular structure was stored in an array of type 'triangle':
type triangle = array[1..MAX_NUM_OF_ROWS, 1..MAX_NUM_OF_ROWS] of integer;
Here's my implementation:
function findAux(data: triangle; dim: integer; i: integer; j:integer) : integer;
begin
if i = dim then
findAux := data[i][j]
else
if findAux(data, dim, i + 1, j + 1) > findAux(data, dim, i + 1, j) then
findAux := data[i+1][j+1] + findAux(data, dim, i + 1, j + 1);
else
findAux := data[i+1][j] + findAux(data, dim, i + 1, j);
end;
function find_heaviest_path(data: triangle; dim: integer) : integer;
begin
find_heaviest_path := findAux(data, dim, 1, 1);
end;
As you can see, I've used an auxiliary function. Unfortunately, it doesn't seem to give the right result. For the structure seen above, the result I get is 27, which is 7 points off. What am I missing? How does the implementation look overall? I should add that the maximal number of rows is 100, for this exercise. If clarification is needed, please don't hesitate to ask.
Your findAux is adding the wrong value to the recursively obtained result. As an aside, you can neaten the code a bit using some local variables. A corrected version of findAux:
uses math;
...
function findAux(data: triangle; dim: integer; i: integer; j:integer) : integer;
var
left, right: integer;
begin
if i = dim then
findAux := data[i][j]
else begin
left := findAux(data, dim, i + 1, j);
right := findAux(data, dim, i + 1, j + 1);
findAux := data[i][j] + Max(left, right);
end;
end;