edit: added comments to the code to make it easier to understand
Turing: |
const RUN_UPTO := 500 %The largest x-coordinate of the graph we will create
var count := 0
%Array that will hold the number of primes up to the index number of the array.
%For example, arrPrimesUpto (8) will be 4 because 2, 3, 5, and 7 are prime.
var arrPrimesUpto : array 1 .. RUN_UPTO of int
%Function that will take in the array to plotted, and coordinates describing the rectangle it will fit in, and whether it
%should connect the points with lines, or just draw dots.
proc plotArray (arr : array 1 .. * of int, Temp_x1, Temp_y1, Temp_x2, Temp_y2 : int, drawLine : boolean)
const AXIS_DISTANCE := 20 %How far from the bottom-left corner of the graph rectangle the axis will be.
var x1, x2, y1, y2 : int %The coordinates describing the rectangle of the graph.
var maxNum : int := minint %Used to find the largest y-value in the array so that the graph can be fitted accordingly
var xDiv, yDiv : real %What ratio the x and y must be multiplied by to fit the pixels of the screen.
var mx, my, mb : int
var dragx1, dragy1, dragx2, dragy2 : int %The coordinates of the rectangle the user drags
var newArray : flexible array 1 .. 0 of int %Used to recurse the function/zoom in
var count : int := 0 %Used when assigning newArray's values
%To make things easier, we make sure the user inputted x1,y1 as the bottom-left and x2,y2 as top-right
x1 := min (Temp_x1, Temp_x2 )
x2 := max (Temp_x1, Temp_x2 )
y1 := min (Temp_y1, Temp_y2 )
y2 := max (Temp_y1, Temp_y2 )
drawbox (x1, y1, x2, y2, 7) %Draw a box which the graph should fit in
%Draw the axes
drawline (x1 + AXIS_DISTANCE, y1 + AXIS_DISTANCE, x1 + AXIS_DISTANCE, y2, 7)
drawline (x1 + AXIS_DISTANCE, y1 + AXIS_DISTANCE, x2, y1 + AXIS_DISTANCE, 7)
%Find the maximum y-value
for i : 1 .. upper (arr )
maxNum := max (arr (i ), maxNum )
end for
%abs (x2 - x1) - AXIS_DISTANCE) is the width in pixels of the graphing area. We divide that by the maximum x-value
%To find the ratio between array and x-coordinate
xDiv := (abs (x2 - x1 ) - AXIS_DISTANCE ) / (upper (arr ))
%Same thing for y
yDiv := (abs (y2 - y1 ) - AXIS_DISTANCE ) / (maxNum )
%The actual drawing of the graph
for xCount : 1 .. upper (arr ) %Loop through each element
if drawLine then %If true was entered as a parameter for drawing a line
if xCount ~ = 1 then %Since we check arr(xCount - 1) to draw the line
%Draw a line between the previous index and this index, the coordinate is found by multiplying by the ratio
%and adding the axis distance
drawline (round ((xCount - 1) * xDiv ) + AXIS_DISTANCE, AXIS_DISTANCE + round (yDiv * arr (xCount - 1)), round (xCount * xDiv ) + AXIS_DISTANCE, AXIS_DISTANCE + round (yDiv *
arr (xCount )), 7)
end if
else
%Same as before, except we're not checking arr(xCount - 1), and just drawing a dot
drawdot (round (xCount * xDiv ) + AXIS_DISTANCE, AXIS_DISTANCE + round (yDiv * arr (xCount )), 7)
end if
end for
%The interactive portion of the graph
loop
delay (10)
Mouse.Where (mx, my, mb )
%Check if the mouse is within the graph, and inside the axis
if ~ (mx < x1 + AXIS_DISTANCE + 1 or mx > x2 or my < y1 + AXIS_DISTANCE or my > y2 ) then
%Put the (x,y) at their mouse's x-position
locate (1, 1)
put "(", ceil ((mx - x1 - AXIS_DISTANCE ) / xDiv ), ",", arr (ceil ((mx - x1 - AXIS_DISTANCE ) / xDiv )), ")"
if mb = 1 then %If they click, allow them to drag
%set the coordinates for one corner of the rectangle
dragx1 := mx
dragy1 := my
%Allow them to move their mouse, and pick the other corner
loop
delay (10)
Mouse.Where (mx, my, mb )
exit when mb = 0
end loop
%Set the other coordinate of the rectangle
dragx2 := mx
dragy2 := my
%If the rectangle they described is within the graph area and it isn't just a point
if (dragx1 ~ = dragx2 ) and ~ (dragx2 < x1 + AXIS_DISTANCE + 1 or dragx2 > x2 or dragy2 < y1 + AXIS_DISTANCE or dragy2 > y2 ) then
drawbox (dragx1, dragy1, dragx2, dragy2, 7) %Draw a box around where they chose
%THe new array should go up to the difference between the x-values of the rectangle, fitted to the graph
new newArray, round (abs (dragx1 - dragx2 ) / xDiv )
%I suspect this is what is causing the problems in my program.
%Go from the left to the right, fitted to the screen
for i : round ((min (dragx1, dragx2 ) - x1 - AXIS_DISTANCE ) / xDiv ) .. round ((max (dragx1, dragx2 ) - x1 - AXIS_DISTANCE ) / xDiv ) - 1
count + = 1
%Assign the new array to the rectangle's array values
newArray (count ) := arr (i )
end for
count := 0
cls
%Plot a new array with the new Array, and the same other parameters.
plotArray (newArray, x1, x2, y1, y2, drawLine )
end if
end if
else
%Erase the (x,y)
locate (1, 1)
put ""
end if
end loop
end plotArray
%Simple function that outputs true if the inputted number is prime, and false if it isn't
fcn isPrime (n : int) : boolean
if n mod 2 = 0 and n ~ = 2 then
result false
end if
for i : 3 .. round (sqrt (n )) by 2
if n mod i = 0 then
result false
end if
end for
result true
end isPrime
arrPrimesUpto (1) := 0
%This is necessary since 1 isn't really a prime number, but our isPrime function thinks it is.
%It also allows us to check the index number - 1 in our for loop.
%Fill the array.
%Rather than checking every number, up to each index, we check if it should have one more than the one before it.
for i : 2 .. RUN_UPTO
if isPrime (i ) then
count + = 1
end if
arrPrimesUpto (i ) := count
end for
plotArray (arrPrimesUpto, 0, 0, maxx div 2, maxy div 2, true)
|
All the stuff about primes, and GCD has nothing to do with my problem, that is just to generate sample data to graph. The main procedure takes the array as a parameter and plots the array value vs. the index number. I tried making the graph somewhat interactive. When you drag a box over the graph, it should zoom in into that section. For some reason some weird stuff is drawn, or sometimes, there's an array out of bounds error.
I believe the problem code lies in here:
code: |
if (dragx1 ~= dragx2 and dragy1 ~= dragy2) and ~ (dragx2 < x1 + AXIS_DISTANCE + 1 or dragx2 > x2 or dragy2 < y1 + AXIS_DISTANCE or dragy2 > y2) then
drawbox (dragx1, dragy1, dragx2, dragy2, 7)
new newArray, round (abs (dragx1 - dragx2) / xDiv)
for i : round ((min (dragx1, dragx2) - x1 - AXIS_DISTANCE) / xDiv) .. round ((max (dragx1, dragx2) - x1 - AXIS_DISTANCE) / xDiv) - 1
count += 1
newArray (count) := arr (i)
end for
count := 0
cls
plotArray (newArray, x1, x2, y1, y2, drawLine)
end if
|
|