Algol: correct syntax leads to problems in compilation? - syntax

Here is a relatively simple code for "Evaluation of pi using the Mid-ordinate Rule on a quadrant of circle with radius 2 units."
main.alg
BEGIN
REAL x, y, sumy, pi;
INT n := lowerlimit, p := 1, lowerlimit := 10, upperlimit := 100, interval := 10;
FOR n BY interval TO upperlimit DO
sumy := 0.0;
FOR p BY 2 TO n+n-1 DO
x := p/n;
y := sqrt(4.0 - x**2);
sumy := sumy + y;
OD
pi := sumy * (2.0 / n);
print((n,pi))
OD
END
I'm getting the following errors:
a68g: syntax error: 1: possibly a missing or erroneous separator nearby.
sh-4.3$ a68g main.alg
13 sumy := sumy + y;
1
a68g: warning: 1: skipped superfluous semi-symbol.
15 pi := sumy * (2.0 / n);
1
a68g: syntax error: 1: possibly a missing or erroneous separator nearby.
Try it live here.
What am I doing wrong? How to correct it?

The short answer:
The following code has your specific problem fixed...
The thing to remember is that a ";" is a "statement separator"... so all "compound statement" should have each statement separated by a ";".. eg consider:
statement; statement; statement # is a valid program #
statement; statement statement; # is not valid #
(statement; statement; statement) # is a valid program #
(statement; statement; statement;) # is not valid #
(statement; statement; statement); # is not valid #
The moral is... separate all statements with a ";" and dont put a ";" after the last statement. (eg before an END, FI, DO, ")" or ESAC)
BEGIN
REAL x, y, sumy, pi;
INT n := lowerlimit, p := 1, lowerlimit := 10, upperlimit := 100, interval := 10;
FOR n BY interval TO upperlimit DO
sumy := 0.0;
FOR p BY 2 TO n+n-1 DO
x := p/n;
y := sqrt(4.0 - x**2);
sumy := sumy + y
OD;
pi := sumy * (2.0 / n);
print((n,pi))
OD
END
It is interesting to note that you can often use a "," instead of a ";", this tells the compiler you dont care what order the statements are run. It is called a GOMMA. (A contraction of go on and comma)
e.g. The GOMMA should be used sparingly as the compiler is not required to warn you about side effects... for example (in theory)
#!/usr/bin/a68g --script #
# -*- coding: utf-8 -*- #
INT x:=0;
(x+:=1, x+:=2); # allow the compiler the choice of threading #
PAR(x+:=10, x+:=20); # force statements into different threads #
printf(($"Answer="gl$,x))
What is the Answer? ... it could be 33, but it might also be 21 or 12 etc. depending on your compiler.
In this case the +:= operation is so small and fast that the answer will probably be 33.
The long answer:
The location of the statement separators in languages cause caused grief through the years. For example consider the following FORTRAN code with a missing comma:
DO 999 I=1 1000
PRINT *,I
999 CONTINUE
This bug was found and corrected before the launch of Project Mercury. Urban myth has it that the Mariner Program had a similar bug causing it to crash.
Note that it is often useful to have "Fake" statements, this is used to fulfill syntax/semantic requirements. Python as various examples, eg: "None", "NoneType" and "pass". Algol68 has "VOID", "SKIP" and "~"
To demonstrate the usage of SKIP (or "~").
BEGIN
REAL x, y, sumy, pi;
INT n := lowerlimit, p := 1, lowerlimit := 10, upperlimit := 100, interval := 10;
FOR n BY interval TO upperlimit DO
sumy := 0.0;
FOR p BY 2 TO n+n-1 DO
x := p/n;
y := sqrt(4.0 - x**2);
sumy := sumy + y; SKIP # insert a "fake statement after the ";" #
OD; # the ";" is still needed #
pi := sumy * (2.0 / n);
print((n,pi))
OD
END
SKIP is often used to permit code to be cleanly commented out:
statement1;
statement2;
SKIP COMMENT
statement3;
statement4 # eg. no ";" on the last statement #
END COMMENT
Without the SKIP the program would not compile.
In the case of Algol68, there is a weird case Yoneda's ambiguity. This ambiguity has haunted numerous programming languages ever since, including Ada and python, and maybe even C...
To find out more go to your university library and read: "A History of ALGOL 68" - by C. H. Lindsey - [Includes a candid reflection of the language design process "Revision by mail", language feature struggles "The Bend" and included/excluded ambiguities (eg Yoneda's ambiguity and incestuous unions)]
In python they tries to side step the "Separator" by making it optional and hiding it with indentation... but the comma ambiguity remained.. eg. spot the syntax/semantic error, and run time error in the following...
print [i for i in ()]
print [i for i in (1)]
print [i for i in (1,2)]
print [i for i in (1,2,3)]
ab="ab etc etc etc"
print "first 2 only: %c,%c"%ab[0:2]
C also suffers a little from "where do I put a semicolon and comma"... the logic is that the ";" need never follow a "}", eg always ";}" but never "};"... It turns out that sometimes you do need ";};"
Then C completely throws a spanner in the works for commas with never ",)" but sometimes "),".
1968's Algol68 does produce an error message for this class of ambiguities. The moral to the story might be: if your compiler does not pick up this kind of ambiguity at compile time, then (just maybe) you should pick another language.
BTW: You can find some sample Algol68 Programs here... And next is your code with the sharp edges removed.
INT lower limit = 10, upper limit = 100, interval = 10;
PROC circle = (REAL x)REAL: sqrt(4 - x**2);
FOR n FROM lower limit BY interval TO upper limit DO
REAL sum y := 0;
FOR p FROM 1 BY 2 TO 2*n DO
REAL x = p/n;
REAL y = circle(x);
sum y +:= y
OD;
REAL pi := sum y * 2 / n;
printf(($g(0)": "g(-real width,real width-2)l$,n,pi))
OD
Compare the code changes to see if you can figure out the effect and what hints they provide... :-)
Or... here is how a standard numerical quadrature program might be coded for sharing. Note the use of passing functions as arguments, in particular there is a concept called Currying here circle(2,) ... where the comma is significant!
INT lower limit = 10, upper limit = 100, interval = 10;
PROC circle = (REAL radius, x)REAL: sqrt(radius**2 - x**2);
PROC mid point integrate = (PROC(REAL)REAL f, REAL lwb, upb, INT num steps)REAL: (
REAL dx := (upb - lwb ) / num steps;
REAL x := lwb + dx/2;
REAL sum y := 0;
FOR p TO num steps DO
REAL y = f(x);
sum y +:= y;
x +:= dx
OD;
sum y * dx
);
FOR num steps FROM lower limit BY interval TO upper limit DO
REAL pi := mid point integrate(circle(2,),0,2,num steps);
printf(($g(0)": "g(-real width,real width-2)l$,num steps,pi))
OD

Related

subscript indices must be either positiveintegers less than 2^31 or logicals

SOS i keep getting errors in the loop solving by finite difference method.
I either get the following error when i start with i = 2 : N :
diffusion: A(I,J): row index out of bounds; value 2 out of bound 1
error: called from
diffusion at line 37 column 10 % note line change due to edit!
or, I get the following error when i do i = 2 : N :
subscript indices must be either positive integers less than 2^31 or logicals
error: called from
diffusion at line 37 column 10 % note line change due to edit!
Please help
clear all; close all;
% mesh in space
dx = 0.1;
x = 0 : dx : 1;
% mesh in time
dt = 1 / 50;
t0 = 0;
tf = 10;
t = t0 : dt : tf;
% diffusivity
D = 0.5;
% number of nodes
N = 11;
% number of iterations
M = 10;
% initial conditions
if x <= .5 && x >= 0 % note, in octave, you don't need parentheses around the test expression
u0 = x;
elseif
u0 = 1-x;
endif
u = u0;
alpha = D * dt / (dx^2);
for j = 1 : M
for i = 1 : N
u(i, j+1) = u(i, j ) ...
+ alpha ...
* ( u(i-1, j) ...
+ u(i+1, j) ...
- 2 ...
* u(i, j) ...
) ;
end
u(N+1, j+1) = u(N+1, j) ...
+ alpha ...
* ( ...
u(N, j) ...
- 2 ...
* u(N+1, j) ...
+ u(N, j) ...
) ;
% boundary conditions
u(0, :) = u0;
u(1, :) = u1;
u1 = u0;
u0 = 0;
end
% exact solution with 14 terms
%k=14 % COMMENTED OUT
v = (4 / ((k * pi) .^ 2)) ...
* sin( (k * pi) / 2 ) ...
* sin( k * pi * x ) ...
* exp .^ (D * ((k * pi) ^ 2) * t) ;
exact = symsum( v, k, 1, 14 );
error = exact - u;
% plot stuff
plot( t, error );
xlabel( 'time' );
ylabel( 'error' );
legend( 't = 1 / 50' );
Have a look at the edited code I cleaned up for you above and study it.
Don't underestimate the importance of clean, readable code when hunting for bugs.
It will save you more time than it will cost. Especially a week from now when you will need to revisit this code and you will not remember at all what you were trying to do.
Now regarding your errors. (all line references are with respect to the cleaned up code above)
Scenario 1:
In line 29 you initialise u as a single value.
If you start your loop in line 35 starting with i = 2, then as soon as you try to do u(i, j+1), i.e. u(2,2) in the next line, octave will complain that you're trying to index the second row, in an array that so far only contains one row. (in fact, the same will apply for j at this point, since at this point you only have one column as well)
Scenario 2:
I assume the second scenario was a typo and you meant to say i = 1 : N.
If you start with i=1 in the loop, then have a look at line 38: you are trying to get element u(i-1, j), i.e. u(0,1). Therefore octave will complain that you're trying to get the zero element, but in octave arrays start from one and zero is not defined. Attempting to access any array with a zero will result in the error you see (try it in a terminal!).
UPDATE
Also, now that the code is clean, you can spot another bug, which octave helpfully warns you about if you try to run the code.
Look at line 26. There is NO condition in the elseif leg, so octave looks for the next statement as the test condition.
This means that the elseif condition will always succeed as long as the result of u0 = 1-x is non-zero.
This is clearly a bug. Either you forgot to put the condition for the elseif, or more likely, you probably just meant to say else, rather than elseif.

Fatal: Syntax error, "." expected but ";" found

program Hello;
var
a,b,c,x,d: integer;
x1,x2: real;
begin
readln(a,b,c);
if a = 0 then
begin
if b = 0 then
begin
if c = 0 then
begin
writeln('11');
end
else
writeln('21');
end;
end
else
writeln('31');
end;
end
else
d := b^2 - 4*a*c;
if d < 0 then
begin
writeln('Нет Вещественных корней!');
end
else
x1 := (-b + sqrt(d))/(2*a);
x2 := (-b - sqrt(d))/(2*a);
writeln('Первый Корень:' + x1 + ' ' + 'Второй Корень:' + x2);
end;
end;
end.
The reason for this is that your begins and ends are not balanced; disregarding the opening begin and closing end. for the program's syntax to be correct, you should have equal numbers of each, but you have 4 begins and 8 ends.
Obviously, your code is to compute the solutions of a quadratic equation. What I think you should do is to adjust the layout of your code so that it reflects that and then correctly the begins and ends. In particular, your program is trying to detect whether any of a, b and d is zero and, if so, write a diagnostic message, otherwise calculate the roots by the usual formula.
Unfortunately, your begins and ends do not reflect that. Either the whole of the block starting d := ... needs to be executed or none of it does, so the else on the line before needs to be followed by a begin, as in
else begin
d := b*b - 4*a*c; //b^2 - 4*a*c;
if d < 0 then begin
writeln('Нет Вещественных корней!');
end
else begin
x1 := (-b + sqrt(d))/(2*a);
x2 := (-b - sqrt(d))/(2*a);
// writeln('Первый Корень:' + x1 + ' ' + 'Второй Корень:' + x2);
writeln('Первый Корень:', x1, ' Второй Корень:' , x2);
end;
end;
(You don't say which Pascal compiler you are using, but the above fixes two points which are flagged as errors in FreePascal.
If you need more help than that, please ask in a comment.
Btw, there are some grammatical constructs in Pascal implementations where an end can appear without a matching preceding begin such as case ... of ...end.

Obtaining the complex roots of a 2nd degree polynomial in pascal

I have to code a program in pascal that, given the three coefficients of a polynomial(ax²+bx+c), outputs its roots.
Here's what I have right now:
program poly;
type
polynomial = record
a, b, c : real;
end;
procedure readPolynomial (var p : polynomial);
begin
writeln ('Input 1st coefficient: ');
readln (p.a);
writeln ('Input 2nd coefficient: ');
readln (p.b);
writeln ('Input 3rd coefficient: ');
readln (p.c);
end;
function square (x : real) : real;
begin
square := x * x;
end;
procedure roots (p : polynomial; var rP, rN : real);
begin
rP := (-p.b + (sqrt((square(p.b)) - (4 * p.a * p.c)))) / (2 * p.a);
rN := (-p.b - (sqrt((square(p.b)) - (4 * p.a * p.c)))) / (2 * p.a);
writeln('The roots are: ', rP:0:3, ' y ' ,rN:0:3);
end;
var
myPolynomial : polynomial;
r1, r2 : real;
begin
writeln ('Enter the coefficients: ');
readPolynomial (myPolynomial);
roots (myPolynomial, r1, r2);
end.
It works fine for real roots but I don't know how to make it work with complex numbers.
I am assuming your coefficients are real numbers (they user can't enter complex numbers as coefficients). That would add a whole new level of complexity (no pun intended) to the problem.
You need to check the discriminant ((square(p.b)) - (4 * p.a * p.c)) to see if it's less than 0. Currently, your code just does, sqrt((square(p.b)) - (4 * p.a * p.c)) but you aren't checking if you are taking the square root of a negative number (which you can't do using the Pascal sqrt library function).
If the discriminant is negative, then you have a complex root and you can separate the real and imaginary parts as you wish in your program. It's basic quadratic formula.
For example:
procedure roots (p : polynomial; var rP, rN : real);
var disc: real;
begin
disc := square(p.b) - 4*p.a*p.c;
if disc >= 0 then begin
rP := (-p.b + sqrt(disc)) / (2 * p.a);
rN := (-p.b - sqrt(disc)) / (2 * p.a);
writeln('The roots are: ', rP:0:3, ' y ' ,rN:0:3);
end
else begin
// Roots are:
// -p.b/(2*p.a) + (sqrt(-disc)/(2*p.a))i
// -p.b/(2*p.a) - (sqrt(-disc)/(2*p.a))i
end
end;
Here you use the fact that sqrt(x) if x is negative would be, (sqrt(-x))i where i is sqrt(-1). Note that you could also split out the disc = 0 case to avoid repeating a double root.
Since your roots function prints out the results and your main program doesn't use the returned arguments rN and rP, it's not clear to me if you need to pass back the roots at all. But if want to pass the roots back as arguments (the way you have your function currently designed), I'll leave that as an exercise. You just have to decide on a representation for complex roots. One way is to use the Complex number type for the results (if your compiler library supports them), and when the results are real, the imaginary parts will just be zero. Alternatively, if you need to create your own, just make a type which is a record consisting of a real and imaginary part.
type complex = record
re: real;
im: real;
end;

Sum of numbers with approximation and no repetition

For an app I'm working on, I need to process an array of numbers and return a new array such that the sum of the elements are as close as possible to a target sum. This is similar to the coin-counting problem, with two differences:
Each element of the new array has to come from the input array (i.e. no repetition/duplication)
The algorithm should stop when it finds an array whose sum falls within X of the target number (e.g., given [10, 12, 15, 23, 26], a target of 35, and a sigma of 5, a result of [10, 12, 15] (sum 37) is OK but a result of [15, 26] (sum 41) is not.
I was considering the following algorithm (in pseudocode) but I doubt that this is the best way to do it.
function (array, goal, sigma)
var A = []
for each element E in array
if (E + (sum of rest of A) < goal +/- sigma)
A.push(E)
return A
For what it's worth, the language I'm using is Javascript. Any advice is much appreciated!
This is not intended as the best answer possible, just maybe something that will work well enough. All remarks/input is welcome.
Also, this is taking into mind the answers from the comments, that the input is length of songs (usually 100 - 600), the length of the input array is between 5 to 50 and the goal is anywhere between 100 to 7200.
The idea:
Start with finding the average value of the input, and then work out a guess on the number of input values you're going to need. Lets say that comes out x.
Order your input.
Take the first x-1 values and substitute the smallest one with the any other to get to your goal (somewhere in the range). If none exist, find a number so you're still lower than the goal.
Repeat step #3 using backtracking or something like that. Maybe limit the number of trials you're gonna spend there.
x++ and go back to step #3.
I would use some kind of divide and conquer and a recursive implementation. Here is a prototype in Smalltalk
SequenceableCollection>>subsetOfSum: s plusOrMinus: d
"check if a singleton matches"
self do: [:v | (v between: s - d and: s + d) ifTrue: [^{v}]].
"nope, engage recursion with a smaller collection"
self keysAndValuesDo: [:i :v |
| sub |
sub := (self copyWithoutIndex: i) subsetOfSum: s-v plusOrMinus: d.
sub isNil ifFalse: [^sub copyWith: v]].
"none found"
^nil
Using like this:
#(10 12 15 23 26) subsetOfSum: 62 plusOrMinus: 3.
gives:
#(23 15 12 10)
With limited input this problem is good candidate for dynamic programming with time complexity O((Sum + Sigma) * ArrayLength)
Delphi code:
function FindCombination(const A: array of Integer; Sum, Sigma: Integer): string;
var
Sums: array of Integer;
Value, idx: Integer;
begin
Result := '';
SetLength(Sums, Sum + Sigma + 1); //zero-initialized array
Sums[0] := 1; //just non-zero
for Value in A do begin
idx := Sum + Sigma;
while idx >= Value do begin
if Sums[idx - Value] <> 0 then begin //(idx-Value) sum can be formed from array]
Sums[idx] := Value; //value is included in this sum
if idx >= Sum - Sigma then begin //bingo!
while idx > 0 do begin //unwind and extract all values for this sum
Result := Result + IntToStr(Sums[idx]) + ' ';
idx := idx - Sums[idx];
end;
Exit;
end;
end;
Dec(idx); //idx--
end;
end;
end;
Here's one commented algorithm in JavaScript:
var arr = [9, 12, 20, 23, 26];
var target = 35;
var sigma = 5;
var n = arr.length;
// sort the numbers in ascending order
arr.sort(function(a,b){return a-b;});
// initialize the recursion
var stack = [[0,0,[]]];
while (stack[0] !== undefined){
var params = stack.pop();
var i = params[0]; // index
var s = params[1]; // sum so far
var r = params[2]; // accumulating list of numbers
// if the sum is within range, output sum
if (s >= target - sigma && s <= target + sigma){
console.log(r);
break;
// since the numbers are sorted, if the current
// number makes the sum too large, abandon this thread
} else if (s + arr[i] > target + sigma){
continue;
}
// there are still enough numbers left to skip this one
if (i < n - 1){
stack.push([i + 1,s,r]);
}
// there are still enough numbers left to add this one
if (i < n){
_r = r.slice();
_r.push(arr[i]);
stack.push([i + 1,s + arr[i],_r]);
}
}
/* [9,23] */

Number distribution

Problem: We have x checkboxes and we want to check y of them evenly.
Example 1: select 50 checkboxes of 100 total.
[-]
[x]
[-]
[x]
...
Example 2: select 33 checkboxes of 100 total.
[-]
[-]
[x]
[-]
[-]
[x]
...
Example 3: select 66 checkboxes of 100 total:
[-]
[x]
[x]
[-]
[x]
[x]
...
But we're having trouble to come up with a formula to check them in code, especially once you go 11/111 or something similar. Anyone has an idea?
Let's first assume y is divisible by x. Then we denote p = y/x and the solution is simple. Go through the list, every p elements, mark 1 of them.
Now, let's say r = y%x is non zero. Still p = y/x where / is integer devision. So, you need to:
In the first p-r elements, mark 1 elements
In the last r elements, mark 2 elements
Note: This depends on how you define evenly distributed. You might want to spread the r sections withx+1 elements in between p-r sections with x elements, which indeed is again the same problem and could be solved recursively.
Alright so it wasn't actually correct. I think this would do though:
Regardless of divisibility:
if y > 2*x, then mark 1 element every p = y/x elements, x times.
if y < 2*x, then mark all, and do the previous step unmarking y-x out of y checkboxes (so like in the previous case, but x is replaced by y-x)
Note: This depends on how you define evenly distributed. You might want to change between p and p+1 elements for example to distribute them better.
Here's a straightforward solution using integer arithmetic:
void check(char boxes[], int total_count, int check_count)
{
int i;
for (i = 0; i < total_count; i++)
boxes[i] = '-';
for (i = 0; i < check_count; i++)
boxes[i * total_count / check_count] = 'x';
}
total_count is the total number of boxes, and check_count is the number of boxes to check.
First, it sets every box to unchecked. Then, it checks check_count boxes, scaling the counter to the number of boxes.
Caveat: this is left-biased rather than right-biased like in your examples. That is, it prints x--x-- rather than --x--x. You can turn it around by replacing
boxes[i * total_count / check_count] = 'x';
with:
boxes[total_count - (i * total_count / check_count) - 1] = 'x';
Correctness
Assuming 0 <= check_count <= total_count, and that boxes has space for at least total_count items, we can prove that:
No check marks will overlap. i * total_count / check_count increments by at least one on every iteration, because total_count >= check_count.
This will not overflow the buffer. The subscript i * total_count / check_count
Will be >= 0. i, total_count, and check_count will all be >= 0.
Will be < total_count. When n > 0 and d > 0:
(n * d - 1) / d < n
In other words, if we take n * d / d, and nudge the numerator down, the quotient will go down, too.
Therefore, (check_count - 1) * total_count / check_count will be less than total_count, with the assumptions made above. A division by zero won't happen because if check_count is 0, the loop in question will have zero iterations.
Say number of checkboxes is C and the number of Xes is N.
You example states that having C=111 and N=11 is your most troublesome case.
Try this: divide C/N. Call it D. Have index in the array as double number I. Have another variable as counter, M.
double D = (double)C / (double)N;
double I = 0.0;
int M = N;
while (M > 0) {
if (checkboxes[Round(I)].Checked) { // if we selected it, skip to next
I += 1.0;
continue;
}
checkboxes[Round(I)].Checked = true;
M --;
I += D;
if (Round(I) >= C) { // wrap around the end
I -= C;
}
}
Please note that Round(x) should return nearest integer value for x.
This one could work for you.
I think the key is to keep count of how many boxes you expect to have per check.
Say you want 33 checks in 100 boxes. 100 / 33 = 3.030303..., so you expect to have one check every 3.030303... boxes. That means every 3.030303... boxes, you need to add a check. 66 checks in 100 boxes would mean one check every 1.51515... boxes, 11 checks in 111 boxes would mean one check every 10.090909... boxes, and so on.
double count = 0;
for (int i = 0; i < boxes; i++) {
count += 1;
if (count >= boxes/checks) {
checkboxes[i] = true;
count -= count.truncate(); // so 1.6 becomes 0.6 - resetting the count but keeping the decimal part to keep track of "partial boxes" so far
}
}
You might rather use decimal as opposed to double for count, or there's a slight chance the last box will get skipped due to rounding errors.
Bresenham-like algorithm is suitable to distribute checkboxes evenly. Output of 'x' corresponds to Y-coordinate change. It is possible to choose initial err as random value in range [0..places) to avoid biasing.
def Distribute(places, stars):
err = places // 2
res = ''
for i in range(0, places):
err = err - stars
if err < 0 :
res = res + 'x'
err = err + places
else:
res = res + '-'
print(res)
Distribute(24,17)
Distribute(24,12)
Distribute(24,5)
output:
x-xxx-xx-xx-xxx-xx-xxx-x
-x-x-x-x-x-x-x-x-x-x-x-x
--x----x----x---x----x--
Quick html/javascript solution:
<html>
<body>
<div id='container'></div>
<script>
var cbCount = 111;
var cbCheckCount = 11;
var cbRatio = cbCount / cbCheckCount;
var buildCheckCount = 0;
var c = document.getElementById('container');
for (var i=1; i <= cbCount; i++) {
// make a checkbox
var cb = document.createElement('input');
cb.type = 'checkbox';
test = i / cbRatio - buildCheckCount;
if (test >= 1) {
// check the checkbox we just made
cb.checked = 'checked';
buildCheckCount++;
}
c.appendChild(cb);
c.appendChild(document.createElement('br'));
}
</script>
</body></html>
Adapt code from one question's answer or another answer from earlier this month. Set N = x = number of checkboxes and M = y = number to be checked and apply formula (N*i+N)/M - (N*i)/M for section sizes. (Also see Joey Adams' answer.)
In python, the adapted code is:
N=100; M=33; p=0;
for i in range(M):
k = (N+N*i)/M
for j in range(p,k-1): print "-",
print "x",
p=k
which produces
- - x - - x - - x - - x - - [...] x - - x - - - x where [...] represents 25 --x repetitions.
With M=66 the code gives
x - x x - x x - x x - x x - [...] x x - x x - x - x where [...] represents mostly xx- repetitions, with one x- in the middle.
Note, in C or java: Substitute for (i=0; i<M; ++i) in place of for i in range(M):. Substitute for (j=p; j<k-1; ++j) in place of for j in range(p,k-1):.
Correctness: Note that M = x boxes get checked because print "x", is executed M times.
What about using Fisher–Yates shuffle ?
Make array, shuffle and pick first n elements. You do not need to shuffle all of them, just first n of array. Shuffling can be find in most language libraries.

Resources