Introduction
I was
reading an article about how to graph the "prime parallelograms" in J using verbs, which is based on the second part of video by Numberphile.
The
idea is to take the nth prime and subtract the number that is obtained by
inverting the order of its representation in base 2. For example, the 16th
prime is 53 = 1101012, when we reverse it we get 1010112
= 43, so the value is 53 - 43 = 10. If we graph this function, parallelograms
appear.
I
wondered what would happen if we graph all the numbers instead of only the
primes. Also, I wanted to understand where these parallelograms come from.
Additional
modules
To
graph them in Racket we will need to use some additional modules, so we start
with
#lang
racket
(require
math/number-theory)
(require
plot)
#;(plot-new-window?
#t)
I also
like to change how the numbers appear on the axes. It is a technical part, and it
almost doesn’t change the result. The code is at the bottom.
Rebuilding
the graph
First,
we define the function that reverses the order of the bits in the binary
representation of the number.
(define
(binary-reverse x)
(let loop ([x x] [r 0])
(if (zero? x)
r
(loop (quotient x 2) (+ (* 2 r) (remainder x 2))))))
Let's
see some examples
(for
([i (in-range 16)])
(define r (binary-reverse i))
(displayln (list i r (number->string i 2) (number->string r 2))))
>
(0 0 0 0)
>
(1 1 1 1)
>
(2 1 10 1)
>
(3 3 11 11)
>
(4 1 100 1)
>
(5 5 101 101)
>
(6 3 110 11)
>
(7 7 111 111)
>
(8 1 1000 1)
>
(9 9 1001 1001)
>
(10 5 1010 101)
>
(11 13 1011 1101)
>
(12 3 1100 11)
>
(13 11 1101 1011)
> (14 7 1110 111)
>
(15 15 1111 1111)
Note:
It is possible to define this function using strings, but using strings is
always much slower than operating directly with integers.
To
simplify the notation, let's call inv this
function that reverses the order of the bits, p the
function that calculates the nth prime
and let's call f the function f(n)
= n - inv(n).
Now we
can make a list with the points (n, f(p(n))) = (n, p(n) -
inv(p(n))) as vectors.
(define
prim/original (for/list ([i (in-naturals 1)]
[p (in-list (next-primes 1 10000))])
(vector i (- p (binary-reverse p)))))
Note:
We could write our own functions to test primality, but the build-in next-primes and prime? are better.
And we
draw it with plot
(plot (points prim/original))
We fix
the color and opacity to make the drawing more nice
(plot #:title "Prime Paralelograms
(original)"
(points prim/original
#:sym 'dot
#:color 'blue #:alpha .5)
#:x-label "n" #:y-label "f(p(n))"
#:x-min 0)
To
save the image we use plot-file
(plot-file #:title "Prime Paralelograms
(original)"
(points prim/original
#:sym 'dot
#:color 'blue #:alpha .5)
"prime-paralelograms(original).png"
#:x-label "n" #:y-label "f(p(n))"
#:x-min 0)
In
order to compare it with the next graph, we draw it again. But with the labels
of the values of the x-axis aligned to the left (so that the edge
of the graph is the edge of the image).
(parameterize ([plot-x-tick-label-anchor 'top-right])
(plot #:title "Prime Paralelograms (original)"
(points prim/original
#:sym 'dot
#:color 'blue #:alpha .5)
#:x-label "n" #:y-label "f(p(n))"
#:x-min 0))
Now we
change what we graph. We change the x part of the points, instead of using in
which position of the list of prime it is, we use the value of the prime, that
is, instead of drawing (n, f(p(n)) we draw (p(n),
f(p(n)) = (p, f(p)).
(define prim/new (for/list ([i (in-naturals 1)]
[p (in-list (next-primes 1 10000))])
(vector p (- p (binary-reverse p)))))
(parameterize
([plot-x-tick-label-anchor 'top-right])
(plot #:title "Prime Paralelograms"
(points prim/new
#:sym 'dot
#:color 'blue #:alpha .5)
#:x-label "p(n)" #:y-label "f(p(n))"
#:x-min 0))
We can compare it with the previous one:
We get
a very similar drawing if we ignore the scale of the x-axis. The parallelograms
are cut at slightly different positions, but they are very similar.
What
happens is that if we draw the nth prime we get almost a line.
(define prim/scale (for/list ([i (in-naturals 1)]
[p (in-list (next-primes 1 10000))])
(vector i p)))
(plot
#:title "Primes"
(points prim/scale
#:sym 'dot)
#:x-label "n" #:y-label "p(n) = nth prime"
#:x-min 0)
The
inverse is the function that counts the number of primes that in
general is called pi(n) and its slope is slowly
changing, more or less like 1/log(n), but log(n) is a
function that grows very slowly. So the change between the graphs is almost a
linear transformation. Therefore, when we use it to change the x-axis in the
previous drawings we see that the shape of the parallelograms changes very little.
(We should be able to notice more distortion in the first parallelograms.)
Comparing
with all numbers
Now
let's see how the graph looks when we use all the numbers instead of just the
primes. To be able to compare the graph better, we fix the same range for the y-axis
in all the graphs. Also, I like to choose a chart size so that the line y=x has
approximately 45°. (In Excel you make a graph and then with the mouse you fix
all the details of the axes and scales. Here you have to put all that fixes in
the program so that the scales are exactly as you want.)
(define all (for/list ([i (in-range 1 131072)])
(vector i (- i (binary-reverse i)))))
(plot
#:title "All Paralelograms"
(points all
#:sym 'dot
#:color 'black #:alpha .1)
#:x-label "n" #:y-label "f(n)"
#:y-min -65536 #:y-max 131072
#:x-min 0
#:width 400 #:height 600)
Let’s repeat
one of the previous graph, but on these new scales. We will create the list of
primes in a slightly different way.
(define prim (for/list ([i (in-range 1 131072)]
#:when (prime? i))
(vector i (- i (binary-reverse i)))))
(plot
#:title "Prime Paralelograms"
(points prim
#:sym 'dot
#:color 'blue #:alpha .5)
#:x-label "p" #:y-label "f(p)"
#:y-min -65536 #:y-max 131072
#:x-min 0
#:width 400 #:height 600)
And we
superimpose the last two graphs
(plot #:title "All vs Prime Paralelograms"
(list (points all
#:sym 'dot
#:color 'black #:alpha .1)
(points prim
#:sym 'dot
#:color 'blue #:alpha .5))
#:x-label "n" #:y-label "f(n)"
#:y-min -65536 #:y-max 131072
#:x-min 0
#:width 400 #:height 600)
What
we see is that the prime parallelograms occupy the bottom half of
the parallelograms that are formed when we graph all the numbers.
Even
and odd
Almost
all primes are odd. As they are odd, when you invert the order of
the bits in binary you get a number with the same number of figures in binary.
So the result has about the same size. You can bound the result and formalize
this idea, but it is nicer to compare in a graphic what happens when we replace
prime numbers with odd numbers.
(define odd (for/list ([i (in-range 1 131072 2)])
(vector i (- i (binary-reverse i)))))
(plot
#:title "All vs Odd Paralelograms"
(list (points all
#:sym 'dot
#:color 'black #:alpha .1)
(points odd
#:sym 'dot
#:color 'red #:alpha .1))
#:x-label "n" #:y-label "f(n)"
#:y-min -65536 #:y-max 131072
#:x-min 0
#:width 400 #:height 600)
We see
that the odd number occupy essentially the same parallelograms, although there
are fewer gaps.
On the
other hand, the even numbers end in 0 in binary, so by reversing the order of
their bits in binary they lose at least one figure, so the result is smaller.
When we draw them we get this graph.
(define even (for/list ([i (in-range 2 131072 2)])
(vector i (- i (binary-reverse i)))))
(plot
#:title "All vs Even Paralelograms"
(list (points all
#:sym 'dot
#:color 'black #:alpha .1)
(points even
#:sym 'dot
#:color 'green #:alpha .1))
#:x-label "n" #:y-label "f(n)"
#:y-min -65536 #:y-max 131072
#:x-min 0
#:width 400 #:height 600)
We see
that the even numbers essentially occupy the upper halves, that is, they do not
overlap with what is painted by the primes. So the holes in the prime parallelograms
are due to non-prime odd numbers.
Some ideas
to try
- What
happens in base 3? Do we get the obvious generalization? In base 4, do we get
flags?
- Redraw
to see only the first parallelograms. The change of scale is not so linear at
the beginning, so when drawing the parallelograms of the original article (n, f(p(n)) they should be more distorted.
- Redraw
everything with the x-axis in logarithmic scale, so that all parallelograms
have the same width and you can see the first ones easier. I don't know what
scale to use for the y-axis. Maybe you have to draw each parallelogram
separately?
- The
prime numbers are not random, but they look quite random. It
might be interesting to generate a list of fake-primes, filtering the odd
numbers with a distribution similar to that of the primes and see
how the graph looks.
Changing
the format of the labels
I like
to change how the numbers appear on the axes, I don't like that 100000
appears as 105. This part is technical and
almost does not change the result, so I will not explain the details. (Seems
like a good idea for a PR as an additional option for linear-ticks.)
(require plot/utils)
(define
((linear-ticks-format/no-sc) min max pre-ticks)
(define digits (digits-for-range min max))
(map (lambda (pt)
(real->plot-label (pre-tick-value pt) digits #f))
pre-ticks))
(define
(linear-ticks/no-sc) (ticks (linear-ticks-layout) (linear-ticks-format/no-sc)))
(plot-x-ticks
(linear-ticks/no-sc)) ; almost global change
(plot-y-ticks
(linear-ticks/no-sc)) ; almost global change
Full
code
#lang racket
(require
math/number-theory)
(require
plot)
#;(plot-new-window?
#t)
(require
plot/utils)
(define
((linear-ticks-format/no-sc) min max pre-ticks)
(define digits (digits-for-range min max))
(map (lambda (pt)
(real->plot-label (pre-tick-value pt) digits #f))
pre-ticks))
(define
(linear-ticks/no-sc) (ticks (linear-ticks-layout) (linear-ticks-format/no-sc)))
(plot-x-ticks
(linear-ticks/no-sc)) ; almost global change
(plot-y-ticks
(linear-ticks/no-sc)) ; almost global change
(define
(binary-reverse x)
(let loop ([x x] [r 0])
(if (zero? x)
r
(loop (quotient x 2) (+ (* 2 r) (remainder x 2))))))
(for
([i (in-range 16)])
(define r (binary-reverse i))
(displayln (list i r (number->string i 2) (number->string r 2))))
#;(for
([i (in-range 128)]
#:when (prime? i))
(define r (binary-reverse i))
(displayln (list i r (number->string i 2) (number->string r 2))))
;ORIGINAL
(define
prim/original (for/list ([i (in-naturals 1)]
[p (in-list (next-primes 1 10000))])
(vector i (- p (binary-reverse p)))))
(plot
(points prim/original))
(plot
#:title "Prime Paralelograms (original)"
(points prim/original
#:sym 'dot
#:color 'blue #:alpha .5)
#:x-label "n" #:y-label "f(p(n))"
#:x-min 0)
(plot-file
#:title "Prime Paralelograms (original)"
(points prim/original
#:sym 'dot
#:color 'blue #:alpha .5)
"prime-paralelograms(original).png"
#:x-label "n" #:y-label "f(p(n))"
#:x-min 0)
(parameterize
([plot-x-tick-label-anchor 'top-right])
(plot #:title "Prime Paralelograms (original)"
(points prim/original
#:sym 'dot
#:color 'blue #:alpha .5)
#:x-label "n" #:y-label "f(p(n))"
#:x-min 0))
;NEW
(define
prim/new (for/list ([i (in-naturals 1)]
[p (in-list (next-primes 1 10000))])
(vector p (- p (binary-reverse p)))))
(parameterize
([plot-x-tick-label-anchor 'top-right])
(plot #:title "Prime Paralelograms"
(points prim/new
#:sym 'dot
#:color 'blue #:alpha .5)
#:x-label "p(n)" #:y-label "f(p(n))"
#:x-min 0))
;SCALE
(define
prim/scale (for/list ([i (in-naturals 1)]
[p (in-list (next-primes 1 10000))])
(vector i p)))
(plot
#:title "Primes"
(points prim/scale
#:sym 'dot)
#:x-label "n" #:y-label "p(n) = nth prime"
#:x-min 0)
;All
(define
all (for/list ([i (in-range 1 131072)])
(vector i (- i (binary-reverse i)))))
(plot
#:title "All Paralelograms"
(points all
#:sym 'dot
#:color 'black #:alpha .1)
#:x-label "n" #:y-label "f(n)"
#:y-min -65536 #:y-max 131072
#:x-min 0
#:width 400 #:height 600)
(define
prim (for/list ([i (in-range 1 131072)]
#:when (prime? i))
(vector i (- i (binary-reverse i)))))
(plot
#:title "Prime Paralelograms"
(points prim
#:sym 'dot
#:color 'blue #:alpha .5)
#:x-label "p" #:y-label "f(p)"
#:y-min -65536 #:y-max 131072
#:x-min 0
#:width 400 #:height 600)
(plot
#:title "All vs Prime Paralelograms"
(list (points all
#:sym 'dot
#:color 'black #:alpha .1)
(points prim
#:sym 'dot
#:color 'blue #:alpha .5))
#:x-label "n" #:y-label "f(n)"
#:y-min -65536 #:y-max 131072
#:x-min 0
#:width 400 #:height 600)
;
ODD and EVEN
(define
odd (for/list ([i (in-range 1 131072 2)])
(vector i (- i (binary-reverse i)))))
(plot
#:title "All vs Odd Paralelograms"
(list (points all
#:sym 'dot
#:color 'black #:alpha .1)
(points odd
#:sym 'dot
#:color 'red #:alpha .1))
#:x-label "n" #:y-label "f(n)"
#:y-min -65536 #:y-max 131072
#:x-min 0
#:width 400 #:height 600)
(define
even (for/list ([i (in-range 2 131072 2)])
(vector i (- i (binary-reverse i)))))
(plot
#:title "All vs Even Paralelograms"
(list
(points all
#:sym 'dot
#:color 'black #:alpha .1)
(points even
#:sym 'dot
#:color 'green #:alpha .1))
#:x-label "n" #:y-label "f(n)"
#:y-min -65536 #:y-max 131072
#:x-min 0
#:width 400 #:height 600)
Introducción
Estuve
leyendo un artículo sobre como graficar los “paralelogramos de primos” en J usando verbos (en ingés), que está basado en la segunda parte de un video de Numberphile (en ingés).
La
idea es tomar el n-ésimo primo y restarle el número que se obtiene invirtiendo
el orden de su representación en base 2. Por ejemplo, el 16-avo primo es
53=1101012, al darlo vuelta queda 1010112=43, así que el
valor es 53-43=10. Al graficar esta función aparecen unos paralelogramos.
La
duda que me surgió es qué pasaba si graficábamos todos los números en vez de
dibujar sólo los primos. Y además entender de dónde vienen estos
paralelogramos.
Módulos
adicionales
Para
graficarlos en Racket vamos a necesitar usar algunos modulos adicionales, así
que empezamos con
#lang
racket
(require
math/number-theory)
(require
plot)
#;(plot-new-window?
#t)
A
mí también me gusta modificar cómo aparecen los números en los ejes. Es medio
técnico y casi o cambia el resultado. El código está abajo.
Reconstruyendo
el dibujo
Primero
definimos la función que invierte el orden de los bits en la representación
binaria del número.
(define
(binary-reverse x)
(let loop ([x x] [r 0])
(if (zero? x)
r
(loop (quotient x 2) (+ (* 2 r) (remainder x 2))))))
Veamos
algunos ejemplos
(for
([i (in-range 16)])
(define r (binary-reverse i))
(displayln (list i r (number->string i 2) (number->string r 2))))
>
(0 0 0 0)
>
(1 1 1 1)
>
(2 1 10 1)
>
(3 3 11 11)
>
(4 1 100 1)
>
(5 5 101 101)
>
(6 3 110 11)
>
(7 7 111 111)
>
(8 1 1000 1)
>
(9 9 1001 1001)
>
(10 5 1010 101)
>
(11 13 1011 1101)
>
(12 3 1100 11)
>
(13 11 1101 1011)
> (14 7 1110 111)
>
(15 15 1111 1111)
Nota:
Es posible definirla usando strings, pero usar strings siempre es mucho más
lento que operar directamente con los números enteros.
Para
simplificar la notación, llamemos inv
a esta función que invierte el orden de los bits, p
a la función que calcula el n-esimo primo y f
a f(n)=n-inv(n).
Ahora
podemos hacernos una lista con los puntos (n,
f(p(n))) = (n, p(n) - inv(p(n))) en forma de vectores.
(define
prim/original (for/list ([i (in-naturals 1)]
[p (in-list (next-primes 1 10000))])
(vector i (- p (binary-reverse p)))))
Nota: Es posible escribir nuestra propia función para tertear primalidad, pero las funciones next-primes y prime? son mejores.
Y
la dibujamos con plot
(plot
(points prim/original))
Arreglamos
el color y la opacidad para que el dibujo sea más lindo
(plot
#:title "Prime Paralelograms (original)"
(points prim/original
#:sym 'dot
#:color 'blue #:alpha .5)
#:x-label "n" #:y-label "f(p(n))"
#:x-min 0)
Para
guardar la imagen usamos plot-file
(plot-file
#:title "Prime Paralelograms (original)"
(points prim/original
#:sym 'dot
#:color 'blue #:alpha .5)
"prime-paralelograms(original).png"
#:x-label "n" #:y-label "f(p(n))"
#:x-min 0)
Para
poder compararla con el próximo gráfico, la dibujamos de vuelta. Pero con las
etiquetas de los valores del eje x hacia la izquierda (para que el borde del
gráfico sea el borde de la imagen).
(parameterize
([plot-x-tick-label-anchor 'top-right])
(plot #:title "Prime Paralelograms (original)"
(points prim/original
#:sym 'dot
#:color 'blue #:alpha .5)
#:x-label "n" #:y-label "f(p(n))"
#:x-min 0))
Ahora
cambiamos lo que graficamos. Cambiamos la posición en x de los puntos, en vez
de tomar el número de primo tomamos el valor del primo, o sea que en vez de
dibujar (n, f(p(n))
dibujamos (p(n), f(p(n)) = (p, f(p)).
(define
prim/new (for/list ([i (in-naturals 1)]
[p (in-list (next-primes 1 10000))])
(vector p (- p (binary-reverse p)))))
(parameterize
([plot-x-tick-label-anchor 'top-right])
(plot #:title "Prime Paralelograms"
(points prim/new
#:sym 'dot
#:color 'blue #:alpha .5)
#:x-label "p(n)" #:y-label "f(p(n))"
#:x-min 0))
Podemos compararlo con el dibujo anterior:
El
dibujo que obtenemos es muy similar, si ignoramos la escala del eje x. Los
paralelogramos cortan en posiciones ligeramente diferentes, pero son muy
parecidos.
Lo
que pasa es que si dibujamos el n-esimo primo obtenemos casi una recta.
(define
prim/scale (for/list ([i (in-naturals 1)]
[p (in-list (next-primes 1 10000))])
(vector i p)))
(plot
#:title "Primes"
(points prim/scale
#:sym 'dot)
#:x-label "n" #:y-label "p(n) = nth prime"
#:x-min 0)
La
inversa es la función que cuenta la cantidad de primos que en general se llama pi(n) y su pendiente va cambiando lentamente, más
o menos como 1/log(n), pero
log(n) es una función que crece muy
lentamente. Así que el cambio entre los gráficos es casi una transformación
lineal y por eso a cambiar el eje en los dibujos anteriores vemos que la forma
de los paralelogramos cambia poco. (Deberíamos poder notar más distorsión en
los primeros paralelogramos.)
Comparando
con todos los números
Veamos
ahora como queda el gráfico cuando usamos todos los números en vez de sólo los
primos. Para poder comparar mejor los gráficos, fijamos el mismo rango para el
eje y en todos los gráficos. Además, me gusta elegir un tamaño de gráfico para
que la recta y=x tenga aproximadamente 45°. (En Excel uno hace un gráfico y
después con el mouse arregla todos los detalles de los ejes y escalas. Acá hay
que poner todo eso en el programa para que las escalas queden exactamente como
uno quiere.)
(define
all (for/list ([i (in-range 1 131072)])
(vector i (- i (binary-reverse i)))))
(plot
#:title "All Paralelograms"
(points all
#:sym 'dot
#:color 'black #:alpha .1)
#:x-label "n" #:y-label "f(n)"
#:y-min -65536 #:y-max 131072
#:x-min 0
#:width 400 #:height 600)
Repetimos
el gráfico de los primos en la misma escala, armando la lista de primos en este
rango de una manera ligeramente diferente.
(define
prim (for/list ([i (in-range 1 131072)]
#:when (prime? i))
(vector i (- i (binary-reverse i)))))
(plot
#:title "Prime Paralelograms"
(points prim
#:sym 'dot
#:color 'blue #:alpha .5)
#:x-label "p" #:y-label "f(p)"
#:y-min -65536 #:y-max 131072
#:x-min 0
#:width 400 #:height 600)
Y
los superponemos
(plot
#:title "All vs Prime Paralelograms"
(list (points all
#:sym 'dot
#:color 'black #:alpha .1)
(points prim
#:sym 'dot
#:color 'blue #:alpha .5))
#:x-label "n" #:y-label "f(n)"
#:y-min -65536 #:y-max 131072
#:x-min 0
#:width 400 #:height 600)
[Gráfico]
Lo
que vemos es que los paralelogramos de los primos ocupan la mitad de abajo de
los paralelogramos que se forman cuando graficamos todos los números.
Pares
e impares
Casi
todos los primos son impares. Por ser impares al invertir el orden de sus
cifras en binario se obtiene un número con la misma cantidad de cifras en
binario. Así que es aproximadamente del mismo tamaño. Se pueden hacer algunas
acotaciones y formalizar esta idea, pero es más lindo comparar en el gráfico que
pasa cuando reemplazamos los números primos por los números impares.
(define
odd (for/list ([i (in-range 1 131072 2)])
(vector i (- i (binary-reverse i)))))
(plot
#:title "All vs Odd Paralelograms"
(list (points all
#:sym 'dot
#:color 'black #:alpha .1)
(points odd
#:sym 'dot
#:color 'red #:alpha .1))
#:x-label "n" #:y-label "f(n)"
#:y-min -65536 #:y-max 131072
#:x-min 0
#:width 400 #:height 600)
Vemos
que los impares ocupan el esencialmente los mismos paralelogramos, aunque hay
menos huecos.
En
cambio, los números pares terminan en 0
en binario, así que al invertir el orden de sus cifras en binario al menos
pierden una cifra y son más chicos. Al dibujar tenemos
(define
even (for/list ([i (in-range 2 131072 2)])
(vector i (- i (binary-reverse i)))))
(plot
#:title "All vs Even Paralelograms"
(list (points all
#:sym 'dot
#:color 'black #:alpha .1)
(points even
#:sym 'dot
#:color 'green #:alpha .1))
#:x-label "n" #:y-label "f(n)"
#:y-min -65536 #:y-max 131072
#:x-min 0
#:width 400 #:height 600)
Vemos
que los pares ocupan esencialmente las mitades de arriba, o sea que no se
superponen con lo pintado por los primos. Entonces que los huequitos en los
paralelogramos de los primos se deben a números impares no primos.
Algunas
ideas para probar
- ¿Qué pasa en base 3? ¿Es la generalización
obvia? ¿En base 4 son banderitas?
- Redibujar para ver sólo los primeros paralelogramos.
El cambio de escala no es tan lineal al principio y al dibujar los
paralelogramos del artículo original (n, f(p(n))
deberían estar más deformados.
- Redibujar todo con el eje x en escala
logarítmica para que todos los paralelogramos tengan el mismo ancho y se pueda
ver bien los primeros. No sé qué escala usar para el eje y. ¿Quizás haya que
dibujar cada paralelogramo por separado?
- Los primos no son aleatorios, pero parecen
bastante aleatorios. Podría ser interesante generar una lista de truchi-primos,
filtrando los números impares con una distribución parecida a la de los primos
y ver cómo queda el gráfico.
Cambiando
el formato de las etiquetas
A
mí me gusta modificar cómo aparecen los números en los ejes, no me gusta que 100000 aparece como 105. Esta parte es medio técnica
y casi no cambia el resultado, así que no voy a explicar los detalles. (Parece
una buena idea para un PR como una opción adicional de linear-ticks.)
(require
plot/utils)
(define
((linear-ticks-format/no-sc) min max pre-ticks)
(define digits (digits-for-range min max))
(map (lambda (pt)
(real->plot-label (pre-tick-value pt) digits #f))
pre-ticks))
(define
(linear-ticks/no-sc) (ticks (linear-ticks-layout) (linear-ticks-format/no-sc)))
(plot-x-ticks
(linear-ticks/no-sc)) ; almost global change
(plot-y-ticks
(linear-ticks/no-sc)) ; almost global change
Código
completo
#lang
racket
(require
math/number-theory)
(require
plot)
#;(plot-new-window?
#t)
(require
plot/utils)
(define
((linear-ticks-format/no-sc) min max pre-ticks)
(define digits (digits-for-range min max))
(map (lambda (pt)
(real->plot-label (pre-tick-value pt) digits #f))
pre-ticks))
(define
(linear-ticks/no-sc) (ticks (linear-ticks-layout) (linear-ticks-format/no-sc)))
(plot-x-ticks
(linear-ticks/no-sc)) ; almost global change
(plot-y-ticks
(linear-ticks/no-sc)) ; almost global change
(define
(binary-reverse x)
(let loop ([x x] [r 0])
(if (zero? x)
r
(loop (quotient x 2) (+ (* 2 r) (remainder x 2))))))
(for
([i (in-range 16)])
(define r (binary-reverse i))
(displayln (list i r (number->string i 2) (number->string r 2))))
#;(for
([i (in-range 128)]
#:when (prime? i))
(define r (binary-reverse i))
(displayln (list i r (number->string i 2) (number->string r 2))))
;ORIGINAL
(define
prim/original (for/list ([i (in-naturals 1)]
[p (in-list (next-primes 1 10000))])
(vector i (- p (binary-reverse p)))))
(plot
(points prim/original))
(plot
#:title "Prime Paralelograms (original)"
(points prim/original
#:sym 'dot
#:color 'blue #:alpha .5)
#:x-label "n" #:y-label "f(p(n))"
#:x-min 0)
(plot-file
#:title "Prime Paralelograms (original)"
(points prim/original
#:sym 'dot
#:color 'blue #:alpha .5)
"prime-paralelograms(original).png"
#:x-label "n" #:y-label "f(p(n))"
#:x-min 0)
(parameterize
([plot-x-tick-label-anchor 'top-right])
(plot #:title "Prime Paralelograms (original)"
(points prim/original
#:sym 'dot
#:color 'blue #:alpha .5)
#:x-label "n" #:y-label "f(p(n))"
#:x-min 0))
;NEW
(define
prim/new (for/list ([i (in-naturals 1)]
[p (in-list (next-primes 1 10000))])
(vector p (- p (binary-reverse p)))))
(parameterize
([plot-x-tick-label-anchor 'top-right])
(plot #:title "Prime Paralelograms"
(points prim/new
#:sym 'dot
#:color 'blue #:alpha .5)
#:x-label "p(n)" #:y-label "f(p(n))"
#:x-min 0))
;SCALE
(define
prim/scale (for/list ([i (in-naturals 1)]
[p (in-list (next-primes 1 10000))])
(vector i p)))
(plot
#:title "Primes"
(points prim/scale
#:sym 'dot)
#:x-label "n" #:y-label "p(n) = nth prime"
#:x-min 0)
;All
(define
all (for/list ([i (in-range 1 131072)])
(vector i (- i (binary-reverse i)))))
(plot
#:title "All Paralelograms"
(points all
#:sym 'dot
#:color 'black #:alpha .1)
#:x-label "n" #:y-label "f(n)"
#:y-min -65536 #:y-max 131072
#:x-min 0
#:width 400 #:height 600)
(define
prim (for/list ([i (in-range 1 131072)]
#:when (prime? i))
(vector i (- i (binary-reverse i)))))
(plot
#:title "Prime Paralelograms"
(points prim
#:sym 'dot
#:color 'blue #:alpha .5)
#:x-label "p" #:y-label "f(p)"
#:y-min -65536 #:y-max 131072
#:x-min 0
#:width 400 #:height 600)
(plot
#:title "All vs Prime Paralelograms"
(list (points all
#:sym 'dot
#:color 'black #:alpha .1)
(points prim
#:sym 'dot
#:color 'blue #:alpha .5))
#:x-label "n" #:y-label "f(n)"
#:y-min -65536 #:y-max 131072
#:x-min 0
#:width 400 #:height 600)
;
ODD and EVEN
(define
odd (for/list ([i (in-range 1 131072 2)])
(vector i (- i (binary-reverse i)))))
(plot
#:title "All vs Odd Paralelograms"
(list (points all
#:sym 'dot
#:color 'black #:alpha .1)
(points odd
#:sym 'dot
#:color 'red #:alpha .1))
#:x-label "n" #:y-label "f(n)"
#:y-min -65536 #:y-max 131072
#:x-min 0
#:width 400 #:height 600)
(define
even (for/list ([i (in-range 2 131072 2)])
(vector i (- i (binary-reverse i)))))
(plot
#:title "All vs Even Paralelograms"
(list (points all
#:sym 'dot
#:color 'black #:alpha .1)
(points even
#:sym 'dot
#:color 'green #:alpha .1))
#:x-label "n" #:y-label "f(n)"
#:y-min -65536 #:y-max 131072
#:x-min 0
#:width 400 #:height 600)