Pascal - Sum of odd numbers between 0 and X - pascal

I've beeng having some trouble with this code... I need to create an algorithm which makes the user input a number (X), and then the program calculates the sum of all the odd numbers below (x).
This what I've tried so far, but can't really wrap my head around the logic behind it:
Program odd_numbers;
Var
Num, Limite, Soma: integer;
Begin;
Soma := 0;
Writeln('Choose a limit:');
Readln(Limite);
While (Limite / 2 > 0) do
Begin;
Soma := ((Num < Limite) mod 2 > 0);
Writeln('The sum of odd numbers from 0 to ', Limite, ' é ', Soma);
End;
if (Limite mod 2 = 0) then
Begin;
Soma := ((Num < Limite) mod 2 = 0);
Writeln('The sum of odd numbers from 0 to ', Limite, ' é ', Soma);
End;
End.
*PS: Been writing the code with variables in Portuguese, so don't mind the variables appearing weird to understand. *

I see that everyone is happily looping, but this is not necessary. This is a simple arithmetic sequence, and the sum can be calculated without a loop.
Just think of the following:
1 + 3 = 2 * (1 + 3) / 2 = 2 * 2 = 4 ; limits 3 and 4
1 + 3 + 5 = 3 * (1 + 5) / 2 = 3 * 3 = 9 ; limits 5 and 6
1 + 3 + 5 + 7 = 4 * (1 + 7) / 2 = 4 * 4 = 16 ; limits 7 and 8
1 + 3 + 5 + 7 + 9 = 5 * (1 + 9) / 2 = 5 * 5 = 25 ; limits 9 and 10
1 + 3 + 5 + 7 + 9 + 11 = 6 * (1 + 11) / 2 = 6 * 6 = 36 ; limits 11 and 12
But not only that, you'll see that it is in fact always a perfect square: Sqr((n+1) div 2).
So just calculate:
program odd_numbers;
var
Num, Limite, Soma: Integer;
begin
Write('Choose a limit: ');
Readln(Limite);
Num := (Limite + 1) div 2;
Soma := Num * Num;
Writeln('The sum of odd numbers from 0 to ', Limite, ' is ', Soma);
end.
Looks a little simpler than what the others propose.

The loop While (Limite / 2 > 0) do ... uses real arithmetic and not integer arithmetic. I guess you mean While (Limite div 2 > 0) do ... And you should change Limite in the loop otherwise you get stuck because the exit condition can never be reached.

After you have asked the user to enter a number, Limite, you need to keep that unchanged, because you need it in the final message. You also need a loop where you go through all numbers from Limite towards 0.
You started with a while loop which is ok, you are just missing the loop control variable. That is a variable that eventually gets a terminating value which then stops the loop. Use for example the Num variable you already have declared. You can use the same variable to investigate the numbers between user input and 0, for being odd values.
num := limite-1; // give num a start value based on user input (-1 because of "... numbers below (x)")
while num > 0 do // stop the loop when 0 is reached
begin
// here you investigate if `num` is a odd number (e.g. using `mod` operator or
// possibly your pascal has a built in `function Odd(value: integer): boolean;`)
// and add it to `Soma` if it is
num := num - 1;// decrement num at every iteration
end;
Finally you need to consider changes to the above, to handle negative input from the user.

To test if an integer is an odd value, you could use following function:
function IsOdd( value : Integer) : Boolean;
begin
IsOdd := (value mod 2) <> 0;
end;
Many pascal compilers have a built-in function called Odd(), which you could use.
A while loop works well to solve this problem. If you start with lowest odd number above zero, i.e. one and continue upwards so long we do not exceed the limit value we have a simple start:
function GetOddSumBelowX( X : Integer) : Integer;
var
i,sum: Integer;
begin
i := 1; // Start with first odd number
sum := 0;
while (i < X) do begin // as long as i less than X, loop
if IsOdd(i) then begin
sum := sum + i; // add to sum
end;
i := i + 1; // Increment i
end;
GetOddSumBelowX := sum;
end;
Now, that was simple enough. Next step to simplify the loop is to increment the i variable by two instead, just to jump between all odd numbers:
function GetOddSumBelowX( X : Integer) : Integer;
var
i,sum: Integer;
begin
i := 1; // Start with first odd number
sum := 0;
while (i < X) do begin // as long as i less than X, loop
sum := sum + i; // add to sum
i := i + 2; // Increment to next odd number
end;
GetOddSumBelowX := sum;
end;

Related

Pascal - How do i sum all the numbers that can be divided by 4, must use repeat

Cant obtain a correct answer it sums incorectly and multiplicates too, i must use repeat when solving this problem, i suppose the problem is in sum:=i+i but i dont know how to solve it
program SAD;
uses crt;
var a, i, sum, prod: integer;
begin
clrscr;
sum:=0;
prod:=0;
{Sum}
repeat
for i:=1 to 26 do
if i mod 4 = 0 then sum:=i+i;
until i = 26;
{Multiplication}
repeat
for a:=1 to 26 do
if a mod 4 = 0 then prod:=a*a;
until a = 26;
writeln('Suma numerelor divizate la 4 este:', sum);
writeln('Produsul numerelor divizate la 4 este:', prod);
end.
I think the instruction "use repeat" probably intends that you should avoid using for as well.
There are a few errors in your code:
In the sum loop, you should add i to sum, not to itself.
In the prod loop, since you set prod to zero at the start, it will stay as zero because zero times anything is zero. So you need to adjust the logic of your prod calculation so that if prod is zero, when the mod 4 condition is satisfied, you set prod to the current value of a, otherwise you multiply it by a.
Here is some code which fixes the above points and avoids the use of for.
program Sad;
uses crt;
var
a, i, sum, prod: integer;
begin
clrscr;
sum:=0;
prod:=0;
{Sum}
i := 0;
repeat
inc(i);
if (i mod 4) = 0 then
sum := sum + i;
until i = 26;
{Multiplication}
a :=0;
repeat
inc(a);
if a mod 4 = 0 then begin
if prod = 0 then
prod := a
else
prod := prod * a;
end;
until a = 26;
writeln('Suma numerelor divizate la 4 este:', sum);
writeln('Produsul numerelor divizate la 4 este:', prod);
readln;
end.

Optimize a perfect number check to O(sqrt(n))

Part of the program I have checks if an input number is a perfect number. We're supposed to find a solution that runs in O(sqrt(n)). The rest of my program runs in constant time, but this function is holding me back.
function Perfect(x: integer): boolean;
var
i: integer;
sum: integer=0;
begin
for i := 1 to x-1 do
if (x mod i = 0) then
sum := sum + i;
if sum = x then
exit(true)
else
exit(false);
end;
This runs in O(n) time, and I need to cut it down to O(sqrt(n)) time.
These are the options I've come up with:
(1) Find a way to make the for loop go from 1 to sqrt(x)...
(2) Find a way to check for a perfect number that doesn't use a for loop...
Any suggestions? I appreciate any hints, tips, instruction, etc. :)
You need to iterate the cycle not for i := 1 to x-1 but for i := 2 to trunc(sqrt(x)).
The highest integer divisor is x but we do not take it in into account when looking for perfect numbers. We increment sum by 1 instead (or initialize it with 1 - not 0).
The code if (x mod i = 0) then sum := sum + i; for this purpose can be converted to:
if (x mod i = 0) then
begin
sum := sum + i;
sum := sum + (x div i);
end;
And so we get the following code:
function Perfect(x: integer): boolean;
var
i: integer;
sum: integer = 1;
sqrtx: integer;
begin
sqrtx := trunc(sqrt(x));
i := 2;
while i <= sqrtx do
begin
if (x mod i = 0) then
begin
sum := sum + i;
sum := sum + (x div i) // you can also compare i and x div i
//to avoid adding the same number twice
//for example when x = 4 both 2 and 4 div 2 will be added
end;
inc(i);
end;
if sum = x then
exit(true)
else
exit(false);
end;

Divisibility of numbers in pascal

I want to write a pascal program that checks if particular number is divisible by 2, 3, 5, 7, 9 and 11 and whether the sum of the digits is even or odd. In the very end I want to write a statement like "This number is divisible by 5 and 9" and the sum of the numbers is even/odd. What should I do?
Use modulus:
program ModulusTest;
begin
if 8 mod 2 = 0 then
begin
write(8);
writeln(' is even');
end;
if 30 mod 5 = 0 then
begin
write(30);
writeln(' is divisible by 5');
end;
if 32 mod 5 <> 0 then
begin
write(32);
writeln(' is not divisible by 5');
end;
end.
Modulus is what remains after an integer division :)
This's my code, I separate into 2 sections :
program checkNumber;
var number : integer;
divider : string;
digit1, digit2, sum : integer;
begin
//First//
write('Number : '); readln(number);
if (number MOD 2 = 0) then divider := divider+'2, ';
if (number MOD 3 = 0) then divider := divider+'3, ';
if (number MOD 5 = 0) then divider := divider+'5, ';
if (number MOD 7 = 0) then divider := divider+'7, ';
if (number MOD 9 = 0) then divider := divider+'9, ';
if (number MOD 11 = 0) then divider := divider+'11, ';
write('This number is divisible by '); write(divider);
////////////////////////////////////////////////////////
//Second//
digit1 := number DIV 10;
digit2 := number MOD 10;
sum := digit1 + digit2;
write('and the sum of the numbers is ');
if (sum MOD 2 = 0) then write('even') else write('odd');
////////////////////////////////////////////////////////
end.
First part
You need MOD(modulus) operation to get the list of divider values:
write('Number : '); readln(number);
if (number MOD 2 = 0) then divider := divider+'2, ';
if (number MOD 3 = 0) then divider := divider+'3, '; //divider 2 3 5 7 9 11
.
.
Then save the divider into variable divider as string, and write it on monitor.
write('This number is divisible by '); write(divider);
Second part
You need to separate the digits into single variable using DIV(divide) and MOD(modulus) operation. In my code, I limit the number input for 2 digit (1 until 99):
digit1 := number DIV 10;
digit2 := number MOD 10;
sum := digit1 + digit2;
(You change the code use if..then.. function if you want input bigger number).
Then use MOD to check the number is even or odd:
if (sum MOD 2 = 0) then write('even') else write('odd');

A game with 100 oponnents, win as much money as possible

You play a game with 100 opponents. The game has k rounds. Every round you can eliminate some opponents (always atleast 1). You are rewarded for eliminating them.
The reward is: 100.000 * '# of eliminated opponents' / '# of opponents' <= in integers (rounded down)
I want to eliminate the opponents in a way, that gets me the largest amount of money possible.
Example game:
number of rounds = 3
first round we eliminate 50 opponents, so we get 100.000 * 50 / 100 = +50.000
second round we eliminate 30, so we get 100.000 * 30 / 50 = +60.000
last round we eliminate last 20 opponents, so we get 100.000 * 20 / 20 = +100.000
so the total winnings are: 210.000
I tried to write up something, but I don't think it's the most effective way to do it?
Program EliminationGame;
var
selectedHistory : array [1..10] of integer;
opponentCount,roundCount : integer;
maxOpponents,numberSelected : integer;
totalMoney : integer;
i : integer;
begin
totalMoney := 0;
maxOpponents := 100;
opponentCount := maxOpponents;
roundCount := 3; {test value}
for i:=1 to roundCount do begin
if (i = roundCount) then begin
numberSelected := opponentCount;
end else begin
numberSelected := floor(opponentCount / roundCount);
end;
selectedHistory[i] := numberSelected;
totalMoney := floor(totalMoney + (numberSelected / opponentCount * 100000));
opponentCount := opponentCount - numberSelected;
end;
writeln('Total money won:');
writeln(totalMoney);
writeln('Amount selected in rounds:');
for i:= 0 to Length(selectedHistory) do
write(selectedHistory[i],' ');
end.
Also it seems that floor function does not exist in pascal?
It seems the question has a maths answer that can be calculated in advance. As #Anton said it was obvious that the number of points given during the third round did not depend upon the number of eliminated enemies. So the third round should eliminate 1 enemy.
So We get the following function for a thre-round game.
f(x)=100000x/100+100000(99-x)/(100-x)+100000*1/1, where x- the number
of enemies eleminated at first round.
if we find the extrema (local maximum of the function) it appears equal to 90. That means the decision is the following: the first round eliminates 90 the second - 9, the third - 1 enemy.
Of course, for consideration: 90=100-sqrt(100).
In other words: the Pascal decision of the task is to loop a variable from 1 to 99 and see the maximum of this function. X-will be the answer.
program Project1;
var
x, xmax: byte;
MaxRes, tmp: real;
begin
xmax := 0;
MaxRes := 0;
for x := 1 to 99 do
begin
tmp := 100000 * x / 100 + 100000*(99 - x) / (100 - x) + 100000 * 1 / 1;
if tmp > MaxRes then
begin
MaxRes := tmp;
xmax := x;
end;
end;
writeln(xmax);
readln;
end.
The general decision for other number of enemies and rounds (using recursion) is the following (Delphi dialect):
program Project1;
{$APPTYPE CONSOLE}
{$R *.res}
Uses System.SysUtils;
var
s: string;
function Part(RemainingEnemies: byte; Depth: byte;
var OutputString: string): real;
var
i: byte;
tmp, MaxRes: real;
imax: byte;
DaughterString: string;
begin
OutputString := '';
if Depth = 0 then
exit(0);
imax := 0;
MaxRes := 0;
for i := 1 to RemainingEnemies - Depth + 1 do
begin
tmp := i / RemainingEnemies * 100000 + Part(RemainingEnemies - i, Depth - 1,
DaughterString);
if tmp > MaxRes then
begin
MaxRes := tmp;
imax := i;
OutputString := inttostr(imax) + ' ' + DaughterString;
end;
end;
result := MaxRes;
end;
begin
writeln(Part(100, 3, s):10:1);//first parameter-Enemies count,
//2-Number of rounds,
//3-output for eliminated enemies counter
writeln(s);
readln;
end.
This problem can be solved with a dynamic approach.
F(round,number_of_opponents_remained):
res = 0
opp // number_of_opponents_remained
for i in [1 opp]
res = max(res, opp/100 + F(round-1,opp - i) )
return res
I should say this not the complete solution and you add some details about it, and I am just giving you an idea. You should add some details such as base case and checking if opp>0 and some other details. The complexity of this algorithm is O(100*k).

0-1 Knapsack on infinite integer array?

Given an infinite positive integer array or say a stream of positive integers, find out the first five numbers whose sum is twenty.
By reading the problem statement, it first seems to be 0-1 Knapsack problem, but I am confused that can 0-1 Knapsack algo be used on a stream of integers. Let suppose I write a recursive program for the above problem.
int knapsack(int sum, int count, int idx)
{
if (sum == 0 && count == 0)
return 1;
if ((sum == 0 && count != 0) || (sum != 0 && count == 0))
return 0;
if (arr[idx] > 20) //element cann't be included.
return knapsack(sum, count idx + 1);
return max(knapsack(sum, count, idx +1), knapsack(sum - arr[idx], count -1, idx + 1));
}
Now when the above function will call on an infinite array, the first call in max function i.e. knapsack(sum, count, idx +1) will never return as it will keep on ignoring the current element. Even if we change the order of the call in max function, there is still possibility that the first call will never return. Is there any way to apply knapsack algo in such scenarios?
This works if you are working with only positive integers.
Basically keep a list of ways you can reach any of the first 20 numbers and whenever you process a new number process this list accordingly.
def update(dictlist, num):
dk = dictlist.keys()
for i in dk:
if i+num <=20:
for j in dictlist[i]:
listlen = len(dictlist[i][j]) + 1
if listlen >5:
continue
if i+num not in dictlist or listlen not in dictlist[i+num]:
dictlist[i+num][listlen] = dictlist[i][j]+[num]
if num not in dictlist:
dictlist[num]= {}
dictlist[num][1] = [num]
return dictlist
dictlist = {}
for x in infinite_integer_stream:
dictlist = update(dictlist,x)
if 20 in dictlist and 5 in dictlist[20]:
print dictlist[20][5]
break
This code might have some minor bugs and I do not have time now to debug it. But basically dictlist[i][j] stores a j length list that sums to i.
Delphi code:
var
PossibleSums: array[1..4, 0..20] of Integer;
Value, i, j: Integer;
s: string;
begin
s := '';
for j := 1 to 4 do
for i := 0 to 20 do
PossibleSums[j, i] := -1;
while True do begin
Value := 1 + Random(20); // stream emulation
Memo1.Lines.Add(IntToStr(Value));
if PossibleSums[4, 20 - Value] <> -1 then begin
//we just have found 5th number to make the full sum
s := IntToStr(Value);
i := 20 - Value;
for j := 4 downto 1 do begin
//unwind storage chain
s := IntToStr(PossibleSums[j, i]) + ' ' + s;
i := i - PossibleSums[j, i];
end;
Memo1.Lines.Add(s);
Break;
end;
for j := 3 downto 1 do
for i := 0 to 20 - Value do
if (PossibleSums[j, i] <> -1) and (PossibleSums[j + 1, i + Value] = -1) then
PossibleSums[j + 1, i + Value] := Value;
if PossibleSums[1, Value] = -1 then
PossibleSums[1, Value] := Value;
end;
end;
output:
4
8
9
2
10
2
17
2
4 2 10 2 2

Resources