Traducerea lucrurilor între limbi dezvăluie modul în care fiecare limbă abordează diferite compromisuri de design și cred că este un exercițiu util. Să ai ceva de tradus este primul pas. Am găsit un complot pe care voiam să-l generez și un cod care îl reproducea, așa că mergem!
Nu-mi amintesc cum am găsit inițial această pagină (se pare că nu am păstrat o notă pe ea) și aceasta a stat prea mult timp pe teancul meu despre care urmează să fie postat, așa că iată postarea pe care am vrut să o scriu.
Acea postare detaliază un cod ALGOL care generează arta generată de computer a lui Georg Nees „Schotter” din 1968, care arată o grilă de pătrate care sunt din ce în ce mai deplasate în poziție și rotație.
1 'BEGIN''COMMENT'SCHOTTER., 2 'REAL'R,PIHALB,PI4T., 3 'INTEGER'I., 4 'PROCEDURE'QUAD., 5 'BEGIN' 6 'REAL'P1,Q1,PSI.,'INTEGER'S., 7 JE1.=5*1/264.,JA1.=-JE1., 8 JE2.=PI4T*(1+I/264).,JA2.=PI4T*(1-I/264)., 9 P1.=P+5+J1.,Q1.=Q+5+J1.,PS1.=J2., 10 LEER(P1+R*COS(PSI),Q1+R*SIN(PSI))., 11 'FOR'S.=1'STEP'1'UNTIL'4'DO' 12 'BEGIN'PSI.=PSI+PIHALB., 13 LINE(P1+R*COS(PSI),Q1+R*SIN(PSI))., 14 'END".,I.=I+1 15 'END'QUAD., 16 R.=5*1.4142., 17 PIHALB.=3.14159*.5.,P14T.=PIHALB*.5., 18 I.=0., 19 SERIE(10.0,10.0,22,12,QUAD) 20 'END' SCHOTTER., 1 'REAL'P,Q,P1,Q1,XM,YM,HOR,VER,JLI,JRE,JUN,JOB., 5 'INTEGER'I,M,M,T., 7 'PROCEDURE'SERIE(QUER,HOCH,XMAL,YMAL,FIGUR)., 8 'VALUE'QUER,HOCH,XMAL,YMAL., 9 'REAL'QUER,HOCH., 10 'INTEGER'XMAL,YMAL., 11 'PROCEDURE'FIGUR., 12 'BEGIN' 13 'REAL'YANF., 14 'INTEGER'COUNTX,COUNTY., 15 P.=-QUER*XMAL*.5., 16 Q.=YANF.=-HOCH*YMAL*.5., 17 'FOR'COUNTX.=1'STEP'1'UNTIL'XMAL'DO' 18 'BEGIN'Q.=YANF., 19 'FOR'COUNTY.=1'STEP'1'UNTIL'YMAL'DO' 20 'BEGIN'FIGUR.,Q.=Q+HOCH 21 'END'.,P.=P+QUER 22 'END'., 23 LEER(-148.0,-105.0).,CLOSE., 24 SONK(11)., 25 OPBEN(X,Y) 26 'END'SERIE.,
Schotter
Ceea ce lipsește din acest cod ALGOL sunt semințele necesare pentru a reproduce parcela. Autorul a coborât într-o groapă de iepure investigând și calculând diferite valori, dar a reușit să determine că acestea sunt „(1922110153) pentru sămânța de schimbare x și y și (1769133315) pentru sămânța de rotație”. Ei au oferit și o traducere în Python
import math
import drawsvg as draw
class Random:
def __init__(self, seed):
self.JI = seed
def next(self, JA, JE):
self.JI = (self.JI * 5) % 2147483648
return self.JI / 2147483648 * (JE-JA) + JA
def draw_square(g, x, y, i, r1, r2):
r = 5 * 1.4142
pi = 3.14159
move_limit = 5 * i / 264
twist_limit = pi/4 * i / 264
y_center = y + 5 + r1.next(-move_limit, move_limit)
x_center = x + 5 + r1.next(-move_limit, move_limit)
angle = r2.next(pi/4 - twist_limit, pi/4 + twist_limit)
p = draw.Path()
p.M(x_center + r * math.sin(angle), y_center + r * math.cos(angle))
for step in range(4):
angle += pi / 2
p.L(x_center + r * math.sin(angle), y_center + r * math.cos(angle))
g.append(p)
def draw_plot(x_size, y_size, x_count, y_count, s1, s2):
r1 = Random(s1)
r2 = Random(s2)
d = draw.Drawing(180, 280, origin='center', style="background-color:#eae6e2")
g = draw.Group(stroke='#41403a', stroke_width='0.4', fill='none',
stroke_linecap="round", stroke_linejoin="round")
y = -y_size * y_count * 0.5
x0 = -x_size * x_count * 0.5
i = 0
for _ in range(y_count):
x = x0
for _ in range(x_count):
draw_square(g, x, y, i, r1, r2)
x += x_size
i += 1
y += y_size
d.append(g)
return d
d = draw_plot(10.0, 10.0, 12, 22, 1922110153, 1769133315).set_render_size(w=500)
print(d.as_svg())
Am vrut să văd dacă pot traduce și asta în R – bază plot pot desena segmente de linie foarte bine și eram curios să colorez pătratele în felul meu.
Majoritatea acestui cod se traduce simplu, cu excepția faptului că „aleatorie” este de fapt o secvență de valori, începând cu o anumită sămânță. Am spus recent despre o postare mai veche de-a mea care (ab)folosește set.seed() funcția de a genera anumite cuvinte „aleatoare”.
printStr <- function(str) paste(str, collapse="") set.seed(2505587); x <- sample(LETTERS, 5, replace=TRUE) set.seed(11135560);y <- sample(LETTERS, 5, replace=TRUE) paste(printStr(x), printStr(y)) ## (1) "HELLO WORLD"
pe care am fost inspirat să o revăd pe baza unei postări a lui Andrew Heiss.
The Random clasa din acea traducere Python produce un iterator care returnează o valoare „următoarea” de fiecare dată când este apelată cu o „sămânță” specifică și două valori
class Random:
def __init__(self, seed):
self.JI = seed
def next(self, JA, JE):
self.JI = (self.JI * 5) % 2147483648
return self.JI / 2147483648 * (JE-JA) + JA
r = Random(1)
r.next(2, 3)
## 2.0000000023283064
r.next(2, 3)
## 2.000000011641532
r.next(2, 3)
## 2.000000058207661
cu complexitatea adăugată pe care apelurile ulterioare actualizați sămânța în sine.
Când am văzut asta prima dată, mintea mea s-a întors să citească lucrarea „originală” R „R: A Language for Data Analysis and Graphics” de Ross Ihaka și Robert Gentleman, în care mi-am amintit că am văzut exemplul cool al unui sistem OO care menține o stare (non-globală) prin intermediul <<-

Mentinerea starii echilibrului total intern functiei
Cu același truc putem scrie un echivalent al lui Random clasă care actualizează, de asemenea, sămânța intern
random <- function(seed) {
list(
nextval = function(a, b) {
seed <<- (seed * 5) %% 2147483648
seed / 2147483648 * (b-a) + a
}
)
}
r <- random(1)
print(r$nextval(2, 3), digits = 16)
## (1) 2.000000002328306
print(r$nextval(2, 3), digits = 16)
## (1) 2.000000011641532
print(r$nextval(2, 3), digits = 16)
## (1) 2.000000058207661
Rece!
Restul traducerii se aliniază în mare parte la sintaxa de bază a graficului.
Cu asta am ajuns
draw_square <- function(x, y, i, r1, r2, col) {
r = 5 * 1.4142
move_limit = 5 * i / 264
twist_limit = pi/4 * i / 264
y_center = y + 5 + r1$nextval(-move_limit, move_limit)
x_center = x + 5 + r1$nextval(-move_limit, move_limit)
angle = r2$nextval(pi/4 - twist_limit, pi/4 + twist_limit)
x0 <- x_center + r * sin(angle)
y0 <- y_center + r * cos(angle)
for (step in 1:4) {
angle <- angle + pi / 2
x1 <- x_center + r * sin(angle)
y1 <- y_center + r * cos(angle)
segments(x0, y0, x1, y1, lwd = 1.75, col = col)
x0 <- x1
y0 <- y1
}
}
draw_plot <- function(x_size, y_size, x_count, y_count, s1, s2) {
r1 = random(s1)
r2 = random(s2)
plot(NULL, NULL, xlim = c(-60, 60), ylim = c(120, -120), axes = FALSE, ann = FALSE)
y = -y_size * y_count * 0.5
x0 = -x_size * x_count * 0.5
i = 0
for (z in 1:y_count) {
x = x0
for (zz in 1:x_count) {
draw_square(x, y, i, r1, r2, "black")
x <- x + x_size
i <- i + 1
}
y <- y + y_size
}
}
draw_plot(10.0, 10.0, 12, 22, 1922110153, 1769133315)

Figura 1: „Schotter” în R
Care folosește semințele speciale descoperite în acea postare originală. Verificând rotațiile, acest lucru pare într-adevăr să se potrivească cu arta originală.
De ce să te oprești acolo, totuși? Acum că pot să-l complotez, pot schimba lucrurile… ce se întâmplă dacă aș folosi un alt set de semințe, de exemplu, le-am schimbat?
draw_plot(10.0, 10.0, 12, 22, 1769133315, 1922110153)

Figura 2: „Schotter” în R cu semințe schimbate
sau valori complet diferite?
draw_plot(10.0, 10.0, 12, 22, 12345, 67890)

Figura 3: „Schotter” în R cu semințe noi
Ce zici de schimbarea culorilor? Aș putea reprezenta culoarea în funcție de progresia în jos pe grilă, ceea ce cred că arată destul de bine.
draw_plot <- function(x_size, y_size, x_count, y_count, s1, s2) {
r1 = random(s1)
r2 = random(s2)
plot(NULL, NULL, xlim = c(-60, 60), ylim = c(120, -120), axes = FALSE, ann = FALSE)
y = -y_size * y_count * 0.5
x0 = -x_size * x_count * 0.5
i = 0
for (z in 1:y_count) {
x = x0
rcol <- scales::viridis_pal(option = "viridis")(y_count)(z)
for (zz in 1:x_count) {
draw_square(x, y, i, r1, r2, rcol)
x <- x + x_size
i <- i + 1
}
y <- y + y_size
}
}
draw_plot(10.0, 10.0, 12, 22, 1922110153, 1769133315)

Figura 4: „Schotter” în R cu culori viridis
De când am redactat pentru prima dată această postare, am văzut alte exemple de lucrări similare. Acest toot a demonstrat o versiune simplificată
suppressPackageStartupMessages(library(tidyverse))
crossing(x=0:10, y=x) |>
mutate(dx = rnorm(n(), 0, (y/20)^1.5),
dy = rnorm(n(), 0, (y/20)^1.5)) |>
ggplot() +
geom_tile(aes(x=x+dx, y=y+dy, fill=y), colour='black',
lwd=2, width=1, height=1, alpha=0.8, show.legend=FALSE) +
scale_fill_gradient(high='#9f025e', low='#f9c929') +
scale_y_reverse() + theme_void()
în timp ce acesta a arătat o carte „Inginerie de criză” cu o idee similară

Coperta „Crisis Engineering”
Sunt sigur că i-am văzut și pe alții în jur.
Aceasta a fost o explorare distractivă a unor traduceri de cod inspirate artistic și am ajuns să-mi întind puțin mușchii „menținerea stării interne”. Nu mă îndoiesc că cineva mai artistic decât mine ar putea face mult mai mult cu el.
Ca întotdeauna, pot fi găsit pe Mastodon și secțiunea de comentarii de mai jos.
devtools::session_info()
## ─ Session info ─────────────────────────────────────────────────────────────── ## setting value ## version R version 4.5.3 (2026-03-11) ## os macOS Tahoe 26.3.1 ## system aarch64, darwin20 ## ui X11 ## language (EN) ## collate en_US.UTF-8 ## ctype en_US.UTF-8 ## tz Australia/Adelaide ## date 2026-04-17 ## pandoc 3.6.3 @ /Applications/RStudio.app/Contents/Resources/app/quarto/bin/tools/aarch64/ (via rmarkdown) ## quarto 1.7.31 @ /usr/local/bin/quarto ## ## ─ Packages ─────────────────────────────────────────────────────────────────── ## package * version date (UTC) lib source ## blogdown 1.23 2026-01-18 (1) CRAN (R 4.5.2) ## bookdown 0.46 2025-12-05 (1) CRAN (R 4.5.2) ## bslib 0.10.0 2026-01-26 (1) CRAN (R 4.5.2) ## cachem 1.1.0 2024-05-16 (1) CRAN (R 4.5.0) ## cli 3.6.5 2025-04-23 (1) CRAN (R 4.5.0) ## devtools 2.4.6 2025-10-03 (1) CRAN (R 4.5.0) ## digest 0.6.39 2025-11-19 (1) CRAN (R 4.5.2) ## dplyr * 1.2.0 2026-02-03 (1) CRAN (R 4.5.2) ## ellipsis 0.3.2 2021-04-29 (1) CRAN (R 4.5.0) ## evaluate 1.0.5 2025-08-27 (1) CRAN (R 4.5.0) ## farver 2.1.2 2024-05-13 (1) CRAN (R 4.5.0) ## fastmap 1.2.0 2024-05-15 (1) CRAN (R 4.5.0) ## forcats * 1.0.1 2025-09-25 (1) CRAN (R 4.5.0) ## fs 1.6.7 2026-03-06 (1) CRAN (R 4.5.2) ## generics 0.1.4 2025-05-09 (1) CRAN (R 4.5.0) ## ggplot2 * 4.0.2 2026-02-03 (1) CRAN (R 4.5.2) ## glue 1.8.0 2024-09-30 (1) CRAN (R 4.5.0) ## gtable 0.3.6 2024-10-25 (1) CRAN (R 4.5.0) ## hms 1.1.4 2025-10-17 (1) CRAN (R 4.5.0) ## htmltools 0.5.9 2025-12-04 (1) CRAN (R 4.5.2) ## jquerylib 0.1.4 2021-04-26 (1) CRAN (R 4.5.0) ## jsonlite 2.0.0 2025-03-27 (1) CRAN (R 4.5.0) ## knitr 1.51 2025-12-20 (1) CRAN (R 4.5.2) ## labeling 0.4.3 2023-08-29 (1) CRAN (R 4.5.0) ## lattice 0.22-9 2026-02-09 (1) CRAN (R 4.5.3) ## lifecycle 1.0.5 2026-01-08 (1) CRAN (R 4.5.2) ## lubridate * 1.9.5 2026-02-04 (1) CRAN (R 4.5.2) ## magrittr 2.0.4 2025-09-12 (1) CRAN (R 4.5.0) ## Matrix 1.7-4 2025-08-28 (1) CRAN (R 4.5.3) ## memoise 2.0.1 2021-11-26 (1) CRAN (R 4.5.0) ## otel 0.2.0 2025-08-29 (1) CRAN (R 4.5.0) ## pillar 1.11.1 2025-09-17 (1) CRAN (R 4.5.0) ## pkgbuild 1.4.8 2025-05-26 (1) CRAN (R 4.5.0) ## pkgconfig 2.0.3 2019-09-22 (1) CRAN (R 4.5.0) ## pkgload 1.5.0 2026-02-03 (1) CRAN (R 4.5.2) ## png 0.1-9 2026-03-15 (1) CRAN (R 4.5.2) ## purrr * 1.2.1 2026-01-09 (1) CRAN (R 4.5.2) ## R6 2.6.1 2025-02-15 (1) CRAN (R 4.5.0) ## RColorBrewer 1.1-3 2022-04-03 (1) CRAN (R 4.5.0) ## Rcpp 1.1.1 2026-01-10 (1) CRAN (R 4.5.2) ## readr * 2.2.0 2026-02-19 (1) CRAN (R 4.5.2) ## remotes 2.5.0 2024-03-17 (1) CRAN (R 4.5.0) ## reticulate 1.45.0 2026-02-13 (1) CRAN (R 4.5.2) ## rlang 1.1.7 2026-01-09 (1) CRAN (R 4.5.2) ## rmarkdown 2.30 2025-09-28 (1) CRAN (R 4.5.0) ## rstudioapi 0.18.0 2026-01-16 (1) CRAN (R 4.5.2) ## S7 0.2.1 2025-11-14 (1) CRAN (R 4.5.2) ## sass 0.4.10 2025-04-11 (1) CRAN (R 4.5.0) ## scales 1.4.0 2025-04-24 (1) CRAN (R 4.5.0) ## sessioninfo 1.2.3 2025-02-05 (1) CRAN (R 4.5.0) ## stringi 1.8.7 2025-03-27 (1) CRAN (R 4.5.0) ## stringr * 1.6.0 2025-11-04 (1) CRAN (R 4.5.0) ## tibble * 3.3.1 2026-01-11 (1) CRAN (R 4.5.2) ## tidyr * 1.3.2 2025-12-19 (1) CRAN (R 4.5.2) ## tidyselect 1.2.1 2024-03-11 (1) CRAN (R 4.5.0) ## tidyverse * 2.0.0 2023-02-22 (1) CRAN (R 4.5.0) ## timechange 0.4.0 2026-01-29 (1) CRAN (R 4.5.2) ## tzdb 0.5.0 2025-03-15 (1) CRAN (R 4.5.0) ## usethis 3.2.1 2025-09-06 (1) CRAN (R 4.5.0) ## vctrs 0.7.1 2026-01-23 (1) CRAN (R 4.5.2) ## viridisLite 0.4.3 2026-02-04 (1) CRAN (R 4.5.2) ## withr 3.0.2 2024-10-28 (1) CRAN (R 4.5.0) ## xfun 0.56 2026-01-18 (1) CRAN (R 4.5.2) ## yaml 2.3.12 2025-12-10 (1) CRAN (R 4.5.2) ## ## (1) /Library/Frameworks/R.framework/Versions/4.5-arm64/Resources/library ## * ── Packages attached to the search path. ## ## ─ Python configuration ─────────────────────────────────────────────────────── ## python: /Users/jono/.cache/uv/archive-v0/3n3euDImmjsw3EYTJjfeY/bin/python ## libpython: /Users/jono/.local/share/uv/python/cpython-3.12.12-macos-aarch64-none/lib/libpython3.12.dylib ## pythonhome: /Users/jono/.cache/uv/archive-v0/3n3euDImmjsw3EYTJjfeY:/Users/jono/.cache/uv/archive-v0/3n3euDImmjsw3EYTJjfeY ## virtualenv: /Users/jono/.cache/uv/archive-v0/3n3euDImmjsw3EYTJjfeY/bin/activate_this.py ## version: 3.12.12 (main, Oct 28 2025, 11:52:25) (Clang 20.1.4 ) ## numpy: /Users/jono/.cache/uv/archive-v0/3n3euDImmjsw3EYTJjfeY/lib/python3.12/site-packages/numpy ## numpy_version: 2.4.4 ## ## NOTE: Python version was forced by VIRTUAL_ENV ## ## ──────────────────────────────────────────────────────────────────────────────
