How to insert the probability of randomizing a specific number in pascal - pascal

I've been trying lately to write a program(a text based game) but I only know some commands and don't understand every command very well.
What I am trying to do is a hit chance. Lets say that I want the program to have
90% chance of choosing number 1 (which means hit) and
10% to choose number 0 (which means miss).
I saw the same question Here but I don't understand the commands because I've never used them (I'm talking about set.seed and sample). Could someone explain to me how do they work? Is there another way (easier to understand? I don't mind if it consumes more resource)

program Project1;
{$ASSERTIONS ON}
function getProb(aProbability: Integer): boolean;
begin
result := aProbability > (100 - random(100));
end;
procedure miss;
begin
writeln('miss');
end;
procedure hit;
begin
writeln('hit');
end;
var
i, success, probability, errorMarge: Integer;
const
combat: array[boolean] of procedure = (#miss, #hit);
begin
// show that getProb() is reliable
errorMarge := 4;
success := 0;
probability := 80;
for i in [0..99] do
Inc(success, Byte(getProb(probability)));
assert(success >= probability - errorMarge);
success := 0;
probability := 50;
for i in [0..99] do
Inc(success, Byte(getProb(probability)));
assert(success >= probability - errorMarge);
// example usage
combat[getProb(20)];
combat[getProb(80)];
combat[getProb(90)];
readln;
end.

Not knowing what "commands" you know, this is hard to answer w/o generalizing.
If you only need to choose between two values, then generate a random value in whatever range you know how to, and compute the dividing line based on your probability. So, for your example, if you can generate a value between 0 and 1, if it is <= 0.9, hit.
This can be extended to multiple values by adding the successive probabilities. So if you have 4 values to choose between, each with 25% probability, get you random value between 0 and 1: if it is less than 0.25, choose 0 else if less than 0.5, choose 1 else if less than 0.75 choose 2 otherwise choose 3.

Related

I'm having some problems with even and odd numbers in Pascal

I'm having some problems with my program in Pascal. I need to create a program which will calculate even and odd sums of a number's decomposition. For example, if my number is 10 the program should write that sum of even numbers is 30 (since 2,4,6,8,10 are the even numbers) and it should write that sum of odd numbers is 25 (since 1,3,5,7,9 are odd numbers). Here is what i tried
program odd_even;
var
a,sumeven,sumodd,even,odd : integer;
begin
writeln('Enter a number : ');
readln(a);
if a mod 2 = 0 then a=even;
if a mod 2 not=0 then a=odd;
for a:1 to a do begin
sumeven:=0;
sumeven:=sumeven+even
writeln('Sum of even numbers is : ',sumeven);
sumodd:=0;
sumodd:=sumodd+odd;
writeln('Sum of odd numbers is : ',sumodd),
end;
readln
end.
The compiler says that my if part is illegal but I don't understand how I can fix it, I also tried with else but it says the same thing. If someone could help me out I would be really thankful.
First of all, welcome to the world of programming!
There are several errors in your code:
The initialization of your result variables
sumEven:=0;
sumOdd:=0;
should be before your for loop
checking odd/even
if a mod 2 = 0 then a=even;
if a mod 2 not=0 then a=odd;
should be inside your loop and you should check not whether a (your input number) is odd/even but the value of your loop variable:
for i := 1 to a do
begin
if (i mod 2 <> 0) then sumOdd := sumOdd+1 else sumEven := sumEven+1 ;
end;
Printing the results should be of course after your loop.
Good luck!

Division by 0 in TurboPascal7

I am working on my school project and I am (almost) furious about this issue. My solution's validity is 95 %, but I have 1 input wrong – I don't know the input, but I know, that the input failed because of the error code 200, which is divison by 0.
My project is this:
„The digit sum of an integer is defined to be the sum of the digits in the integer's written form. Usually we calculate the digit sum using a number's decimal (base 10) representation, but in this exercise we will compute it in a given base. Write a function that computes a natural number's digit sum when the number is written in a given base. Using this function, write a program that reads two natural numbers (each on its own line, and both in decimal representation): a base B and a number N. The output should be N's digit sum in base B (written in decimal representation).“
I have tried to fix the problem by adding 2 conditions, but it did nothing, mistake still exists.
I am using a formula, which can be found here https://en.wikipedia.org/wiki/Digit_sum .
Here is the code itself, it is not long.
program CifernySoucetZobecneny;
var
Soustava, Cislo, i: longint;
HorniMez: longint;
Soucet: real;
function Mocnina(Zaklad: longint; Exponent: longint): longint;
var
i, Pomoc: longint;
begin
Pomoc := 1;
for i := 1 to Exponent do
begin
Pomoc := Pomoc * Zaklad;
end;
Mocnina := Pomoc;
end;
begin
readLn(Soustava);
readLn(Cislo);
if (Soustava = 0) then
begin
writeLn('0');
exit;
end;
if (Soustava = 1) then
begin
writeLn(Cislo);
exit;
end;
HorniMez := Trunc(Ln(Cislo)/Ln(Soustava));
Soucet := 0;
for i := 0 to HorniMez do
begin
Soucet := Soucet + ((1/Mocnina(Soustava, (i)))*((Cislo mod Mocnina(Soustava, (i+1))) - (Cislo mod Mocnina(Soustava, i))));
end;
writeLn(Soucet:0:0);
end.
I would be grateful if someone could look at the code and told me, where am I dividing by 0, because I tried many inputs, spend many hours on this and did not come with the correct solution. Thank you all.
PS: I am Czech, so the names of the variables and functions are not in English, sorry for that, but I hope, that it will not be a problem.
When Cislo = 0, a following calculation of Ln(Cislo) gives the runtime error 200. That is because Ln(0) is undefined (outside the allowed range of Ln()).

How can I speed up a primality checker?

I have a function FIsPrime which takes a int64 and returns a boolean True or False depending on whether the given int64 is prime or not.
function FIsPrime(P:int64):boolean;
var
I:int64;
RSqrtP:Extended;
begin
I:= 3;
RSqrtP := sqrt(P) + 1;
while ((P mod I) <> 0) AND (I <= RSqrtP) AND ((P mod 2) <> 0) do
I := I + 2;
if I < RSqrtP then
FIsPrime := False
else
FIsPrime := True;
end;
However, while this works, it's quite slow. To check the numbers from 106 to 5×106 takes 4 seconds.
I'm testing numbers on the order of 1012 and 1015 - the whole code picks a random number and × it by 1012 to get a large random number.
This random number is run through the FIsPrime function and incremented by 1 untill it is prime:
function FFirstPrimeAbove(P:int64):int64;
var
BIsPrime: boolean;
begin
if P mod 2 = 0 then
inc(P);
repeat
BIsPrime := FIsPrime(P);
P := P + 2;
until (BIsPrime);
FFirstPrimeAbove := P;
end;
This can take a while - around 6 seconds for 1012 and 7 for 1015.
While 14 seconds isn't much, it is annoying. Is there a way to reduce this time with a more efficient algorithm?
I'm fairly new to Pascal, but have been programming for years - so any more efficient algorithm would be useful.
I looked at the AKS Test but there is a lot of jargon to overcome - "polynomial congruence relation", "generalization to polynomials" and "binomial coefficient" to pick a few.
Any basic hints as to how I could implement something in Delphi would be appreciated.
Changing RSqrtP to Int64 would most likely improve preformance. I didn't test it, but I'd expect comparing a float value to an int64 value not to be the fastest.
Take ((P mod 2) <> 0) out of the loop.
Also, if you don't mind having a longer initialisation time for your application, you could load a list of all prime between 2 and X and start with them before going to the I+2 routine. You don't need to try to divide by non prime number, as this is already taken care of by prime one (i.e. Anything that can be divided by 4 will be divided by 2, anything that can be divided by 49 will also be by 7, etc)
I posted an article about optimisation using primes as an example a while ago. Maybe you'll see some more information there that could help you.
I suspect that the most effective simple way to improve the speed is to create a table of known primes.
There are probably too many primes to store all that fit in a 64 bit integer. But you can store all primes less that sqrt(high(int64)). Then when you loop throw possible divisors you can check only against primes. That should provide a very significant benefit.
So, the algorithm is, in outline:
Fill an array with all the primes less than sqrt(high(int64)). This should be pre-calculated.
To test a value N for being prime, first find its root, sqrt(N).
Then try to divide primes into the value under test until you reach a prime greater than sqrt(N).
If you get that far, N is prime. Otherwise if you find a prime divisor, it is not prime.

Summation loop program in Pascal

I am having a bit of an issue with this problem. I am taking a Pascal programming class and this problem was in my logic book. I am required to have the user enter a series of (+) numbers and once he/she enters a (-) number, the program should find the sum of all the (+) numbers. I accomplished this, but now I am attempting part two of this problem, which requires me to utilize a nested loop to run the program x amount of times based on the user's input.
I do not know how to rerun the summation process based on a number the user enters. In other words, the program is required to
1) Ask the user how many times he/she would like to run the program
2) Begin the nested loop that prompts the user for a series of positive numbers
3) User enters numbers as loop asks for them
4) A negative number then signals the end of the series
5) After the repeat until loop, the program should then add all of the positive numbers together
steps 2-4 is one iteration of the program. I need this to run x amount of times, of course, based on user input.
The following code is what I have so far and honestly I am stumped:
program summation;
var num, sum, counter, userValue : integer;
begin
writeln('Run program how many times?');
readln(userValue);
for counter := 1 to userValue do
begin
sum := 0;
repeat
writeln('Enter a number: ');
readln(num);
if num >= 0 then
begin
sum := num + sum;
end;
until num < 0;
writeln('The sum is: ', sum);
readln();
end;
end.
Update [6/27] 3:40 Pacific Time
Output:
I attempted to upload an image of the output, but I require 10 rep points. Anyway, the program's output is as follows:
How many times would you like the program to run?
2
Enter a number:
1
Enter a number:
1
Enter a number:
-1 <-- negative number signals one iteration of the nested loop
Enter a number:
2
Enter a number:
-3 <-- negative number signals one iteration of the nested loop
The sum is: 6
The negative number signals the program to stop an iteration. However, I would like the program to repeat the summation of a sequence three times.
Update [6/27] 7:25PM Pacific Time
Currently my program executes correctly. By correctly I mean it (1) Asks the user how many times he/she would like to run it. (2) The nested loop begins and prompts user for a series of numbers. (3) Once a negative number is entered it signals the end of the series. (4) The program sums the positive numbers. (5) The program restarts by asking the user for another series of numbers. (6) Once again a negative number ends the series. (7) Error begins here: Once the program iterates (series of number prompts) according to the user defined number, it adds all of the sums from previous iterations to the final sum. This is not my goal. My goal is to have separate sums (one for each run) not all sums "summed" at the final iteration.
In summary (pun intended), your final corrected listing is:
program summation;
var num, sum, counter, userValue : integer;
begin
{ Prompt the user for how many times they wish to sum up a list of numbers }
writeln('Run program how many times?');
readln(userValue);
{ For each time the user wants to sum numbers, prompt them for the numbers }
for counter := 1 to userValue do
begin
sum := 0; { start with a sum of 0 for this list }
{ Repeatedly request a number from the user until they enter a negative to end }
repeat
{ Prompt for and get the number }
writeln('Enter a number: ');
readln(num);
if num >= 0 then
sum := num + sum; { add the number to the sum if it's not negative }
until num < 0; { finish with this sum if the number entered is negative }
{ Write out the last calculated sum }
writeln('The sum is: ', sum);
readln; { Let the user press enter to go around and request another sum }
end;
end.
In numPromptLoop change the name of the NUM parameter to SUM

How to get a random number in pascal?

I want to get a random number in pascal from between a range. Basically something like this:
r = random(100,200);
The above code would then have a random number between 100 and 200.
Any ideas?
The built in pascal function only lets you get a number from between 0-your range, while i need to specify the minimum number to return
Just get a random number with the correct range (ie 100 to 200 would be range 100) then add the starting value to it
So: random(100) + 100 for your example
As already pointed out, you should use
myrandomnumber := random(span) + basenumber;
However, to get better quality random numbers, you should call
randomize();
once, on start of your application, to initialize the random number generator.
Couldn't you just declare a starting variable and an end variable and pass random those? e.g.
var
varMyRandomNumber, x, y := extended;
begin
x := 100;
y := 200;
varMyRandomNumber := random(x,y);
ShowMessage(IntToStr(varMyRandomNumber));
end;
?
There's a good example here of using a for loop to set starting and end values : http://www.freepascal.org/docs-html/rtl/system/random.html
Use RandomRange or RandomFrom:
function RandomRange(const aFrom: Integer; const aTo: Integer): Integer;
RandomFrom returns a random element from the array AValues. The return value has the same type as the type of the array elements.
first of all, i recommend you to use Randomize at the beginning of the program (it changes the algorithm of selecting the number).
To get a random number between some two numbers you need this:
Result:=Min+random(10000)mod max + 1;
I don't remember the maximum value for random, so you can change it (it don't changes anything).
By using 'mod' you get module from division Random and max. +1 is needed, because you never get the number that = max, only the number that =max-1, so you need to write +1.
Good luck!
You can make it like
Int:=Random(100);
it give's 100 random numbers.
then when you display it or use it just add 101 to that integer so its between 100 and 200

Resources