Atari ST Charset

Nostalgique de la fonte système de l'ATARI-ST?

ATARI-ST font nostalgia?

 Fonte système de l'ATARI ST

Voici une petite application permettant de les afficher en mode console. La définition des caractères (8x16px) devrait vous permettre de les utiliser pour un affichage graphique (Tkinter). Au fait, existe-t-il des caractères UTF-8 qui affichent les chiffres LED (première colonne)?

This is an application to display each character on your console. You can use the character definitions (8x16px) to display them on a graphical interface, e.g. Tkinter. By the way, does UTF-8 provides LED digits, as in the first column?

UTF-8 obligatoire! - UTF-8 mandatory!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
 #! /usr/bin/python
# -*- coding: utf-8 -*-
 
# ATARI ST chartable - ver 0.10 GPL2 2014.12.01
# Jean-Christophe Beumier - www.jchr.be
# patterns to allow you to draw ATARI characters on graphics
 
# [character, html equivalent or description, [16 horizontal lines definition]]
# where each number represents 8 pixels: each bit set is "on" (foreground)
 
# 1 to 31, only in graphical mode:
char=[["⇧", "⇑ graph. mode", [0, 0, 0, 24, 60, 102, 195, 129, 231, 36, 36, 36, 60, 0, 0, 0]]]
char+=[["⇩", "⇓ - graph. mode", [0, 0, 0, 60, 36, 36, 36, 231, 129, 195, 102, 60, 24, 0, 0, 0]]]
char+=[["⇨", "⇒ - graph. mode", [0, 0, 48, 56, 44, 230, 131, 131, 230, 44, 56, 48, 0, 0, 0, 0]]]
char+=[["⇦", "⇐ - graph. mode", [0, 0, 12, 28, 52, 103, 193, 193, 103, 52, 28, 12, 0, 0, 0, 0]]]
char+=[["?", "dir out - graph. mode", [0, 0, 124, 56, 186, 146, 214, 198, 214, 146, 186, 56, 124, 0, 0, 0]]]
char+=[["?", "dir resize - graph. mode", [0, 0, 254, 254, 254, 252, 252, 248, 250, 242, 246, 230, 238, 0, 0, 0]]]
char+=[["?", "dir in - graph. mode", [0, 0, 238, 198, 214, 146, 186, 56, 186, 146, 214, 198, 238, 0, 0, 0]]]
char+=[["✓", "check - graph. mode", [0, 0, 1, 1, 3, 3, 6, 6, 140, 140, 216, 88, 112, 48, 32, 0]]]
char+=[["⌚", "watch - graph. mode", [0, 0, 0, 60, 102, 195, 145, 145, 157, 129, 195, 102, 60, 0, 0, 0]]]
char+=[["?", "bell - graph. mode", [0, 0, 0, 0, 24, 60, 60, 60, 60, 60, 126, 255, 16, 56, 16, 0]]]
char+=[["♪", "note ♪ - graph. mode", [0, 0, 8, 14, 15, 9, 8, 8, 120, 248, 112, 0, 0, 0, 0, 0]]]
char+=[["FF", "form feed - graph. mode", [0, 0, 120, 64, 112, 64, 64, 0, 30, 16, 28, 16, 16, 0, 0, 0]]]
char+=[["CR", "carriage return - graph. mode", [0, 0, 56, 64, 64, 64, 56, 0, 28, 18, 28, 20, 18, 0, 0, 0]]]
char+=[["?", "left atari logo - graph. mode", [0, 5, 5, 5, 5, 13, 13, 29, 57, 121, 113, 113, 97, 65, 0, 0]]]
char+=[["?", "right atari logo - graph. mode", [0, 160, 160, 160, 160, 176, 176, 184, 156, 158, 142, 142, 134, 130, 0, 0]]]
char+=[["LED 0", "digital 0 - graph. mode", [0, 124, 186, 198, 198, 198, 130, 0, 130, 198, 198, 198, 186, 124, 0, 0]]]
char+=[["LED 1", "digital 1 - graph. mode", [0, 0, 2, 6, 6, 6, 2, 0, 2, 6, 6, 6, 2, 0, 0, 0]]]
char+=[["LED 2", "digital 2 - graph. mode", [0, 124, 58, 6, 6, 6, 58, 124, 184, 192, 192, 192, 184, 124, 0, 0]]]
char+=[["LED 3", "digital 3 - graph. mode", [0, 124, 58, 6, 6, 6, 58, 124, 58, 6, 6, 6, 58, 124, 0, 0]]]
char+=[["LED 4", "digital 4 - graph. mode", [0, 0, 130, 198, 198, 198, 186, 124, 58, 6, 6, 6, 2, 0, 0, 0]]]
char+=[["LED 5", "digital 5 - graph. mode", [0, 124, 184, 192, 192, 192, 184, 124, 58, 6, 6, 6, 58, 124, 0, 0]]]
char+=[["LED 6", "digital 6 - graph. mode", [0, 124, 184, 192, 192, 192, 184, 124, 186, 198, 198, 198, 186, 124, 0, 0]]]
char+=[["LED 7", "digital 7 - graph. mode", [0, 124, 186, 198, 198, 198, 130, 0, 2, 6, 6, 6, 2, 0, 0, 0]]]
char+=[["LED 8", "digital 8 - graph. mode", [0, 124, 186, 198, 198, 198, 186, 124, 186, 198, 198, 198, 186, 124, 0, 0]]]
char+=[["LED 9", "digital 9 - graph. mode", [0, 124, 186, 198, 198, 198, 186, 124, 58, 6, 6, 6, 58, 124, 0, 0]]]
char+=[["ə", "schwa - graph. mode", [0, 0, 0, 0, 0, 124, 126, 6, 6, 126, 102, 102, 126, 60, 0, 0]]]
char+=[["ES", "escape - graph. mode", [0, 0, 120, 64, 112, 64, 120, 0, 14, 16, 12, 2, 28, 0, 0, 0]]]
char+=[["?", "head nw - graph. mode", [0, 0, 0, 0, 0, 0, 0, 0, 7, 15, 31, 24, 24, 16, 30, 23]]]
char+=[["?", "head ne - graph. mode", [0, 0, 0, 0, 0, 0, 0, 0, 240, 248, 236, 4, 4, 4, 60, 84]]]
char+=[["?", "head sw - graph. mode", [17, 11, 13, 6, 7, 46, 57, 56, 0, 0, 0, 0, 0, 0, 0, 0]]]
char+=[["?", "head se - graph. mode", [4, 40, 216, 40, 208, 16, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0]]]
 
# real ascii table (32 to 255)
char+=[[" ", "space", [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]]
char+=[["!", "", [0, 0, 24, 24, 24, 24, 24, 24, 24, 24, 0, 0, 24, 24, 0, 0]]]
char+=[['"', "", [0, 0, 102, 102, 102, 102, 102, 102, 0, 0, 0, 0, 0, 0, 0, 0]]]
char+=[["#", "", [0, 0, 102, 102, 255, 255, 102, 102, 255, 255, 102, 102, 0, 0, 0, 0]]]
char+=[["$", "", [24, 24, 62, 126, 96, 96, 124, 62, 6, 6, 126, 124, 24, 24, 0, 0]]]
char+=[["%", "", [0, 0, 102, 102, 108, 12, 24, 24, 48, 54, 102, 102, 0, 0, 0, 0]]]
char+=[["&", "", [56, 124, 108, 108, 56, 56, 112, 112, 222, 222, 204, 204, 254, 118, 0, 0]]]
char+=[["'", "", [0, 0, 24, 24, 24, 24, 24, 24, 0, 0, 0, 0, 0, 0, 0, 0]]]
char+=[["(", "", [0, 0, 6, 12, 28, 24, 24, 24, 24, 24, 24, 28, 12, 6, 0, 0]]]
char+=[[")", "", [0, 0, 96, 48, 56, 24, 24, 24, 24, 24, 24, 56, 48, 96, 0, 0]]]
char+=[["*", "", [0, 0, 102, 102, 60, 60, 255, 255, 60, 60, 102, 102, 0, 0, 0, 0]]]
char+=[["+", "", [0, 0, 0, 24, 24, 24, 126, 126, 24, 24, 24, 0, 0, 0, 0, 0]]]
char+=[[",", "", [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 24, 24, 24, 48, 32]]]
char+=[["-", "", [0, 0, 0, 0, 0, 0, 126, 126, 0, 0, 0, 0, 0, 0, 0, 0]]]
char+=[[".", "", [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 24, 24, 24, 0, 0]]]
char+=[["/", "", [0, 0, 6, 6, 6, 12, 12, 24, 24, 48, 48, 96, 96, 96, 0, 0]]]
char+=[["0", "", [0, 0, 60, 126, 102, 102, 102, 110, 118, 102, 102, 102, 126, 60, 0, 0]]]
char+=[["1", "", [0, 0, 24, 24, 56, 56, 24, 24, 24, 24, 24, 24, 126, 126, 0, 0]]]
char+=[["2", "", [0, 0, 60, 126, 102, 102, 12, 12, 24, 24, 48, 48, 126, 126, 0, 0]]]
char+=[["3", "", [0, 0, 126, 126, 12, 12, 24, 24, 12, 12, 102, 102, 126, 60, 0, 0]]]
char+=[["4", "", [0, 0, 12, 12, 28, 28, 60, 60, 108, 108, 126, 126, 12, 12, 0, 0]]]
char+=[["5", "", [0, 0, 126, 126, 96, 96, 124, 126, 6, 6, 6, 102, 126, 60, 0, 0]]]
char+=[["6", "", [0, 0, 28, 60, 112, 96, 96, 124, 126, 102, 102, 102, 126, 60, 0, 0]]]
char+=[["7", "", [0, 0, 126, 126, 6, 6, 12, 12, 24, 24, 48, 48, 48, 48, 0, 0]]]
char+=[["8", "", [0, 0, 60, 126, 102, 102, 60, 60, 102, 102, 102, 102, 126, 60, 0, 0]]]
char+=[["9", "", [0, 0, 60, 126, 102, 102, 126, 62, 6, 6, 6, 14, 60, 56, 0, 0]]]
char+=[[":", "", [0, 0, 0, 0, 24, 24, 24, 24, 0, 0, 24, 24, 24, 24, 0, 0]]]
char+=[[";", "", [0, 0, 0, 0, 24, 24, 24, 24, 0, 0, 24, 24, 24, 24, 48, 32]]]
char+=[["<", "", [0, 0, 0, 14, 28, 56, 112, 224, 112, 56, 28, 14, 0, 0, 0, 0]]]
char+=[["=", "", [0, 0, 0, 0, 126, 126, 0, 0, 126, 126, 0, 0, 0, 0, 0, 0]]]
char+=[[">", "", [0, 0, 0, 224, 112, 56, 28, 14, 28, 56, 112, 224, 0, 0, 0, 0]]]
char+=[["?", "", [0, 0, 60, 126, 102, 102, 12, 12, 24, 24, 24, 0, 24, 24, 0, 0]]]
char+=[["@", "", [0, 0, 56, 124, 230, 194, 218, 214, 214, 220, 192, 226, 126, 60, 0, 0]]]
char+=[["A", "", [0, 0, 24, 60, 126, 102, 102, 102, 126, 126, 102, 102, 102, 102, 0, 0]]]
char+=[["B", "", [0, 0, 124, 126, 102, 102, 126, 124, 102, 102, 102, 102, 126, 124, 0, 0]]]
char+=[["C", "", [0, 0, 60, 126, 102, 102, 96, 96, 96, 96, 102, 102, 126, 60, 0, 0]]]
char+=[["D", "", [0, 0, 120, 124, 110, 102, 102, 102, 102, 102, 102, 110, 124, 120, 0, 0]]]
char+=[["E", "", [0, 0, 126, 126, 96, 96, 124, 124, 96, 96, 96, 96, 126, 126, 0, 0]]]
char+=[["F", "", [0, 0, 126, 126, 96, 96, 124, 124, 96, 96, 96, 96, 96, 96, 0, 0]]]
char+=[["G", "", [0, 0, 62, 126, 96, 96, 110, 110, 102, 102, 102, 102, 126, 60, 0, 0]]]
char+=[["H", "", [0, 0, 102, 102, 102, 102, 126, 126, 102, 102, 102, 102, 102, 102, 0, 0]]]
char+=[["I", "", [0, 0, 126, 126, 24, 24, 24, 24, 24, 24, 24, 24, 126, 126, 0, 0]]]
char+=[["J", "", [0, 0, 6, 6, 6, 6, 6, 6, 6, 6, 102, 102, 126, 60, 0, 0]]]
char+=[["K", "", [0, 0, 204, 204, 216, 216, 240, 240, 216, 216, 204, 204, 198, 198, 0, 0]]]
char+=[["L", "", [0, 0, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 126, 126, 0, 0]]]
char+=[["M", "", [0, 0, 198, 198, 238, 238, 254, 214, 214, 198, 198, 198, 198, 198, 0, 0]]]
char+=[["N", "", [0, 0, 102, 102, 102, 118, 118, 126, 126, 110, 110, 102, 102, 102, 0, 0]]]
char+=[["O", "", [0, 0, 60, 126, 102, 102, 102, 102, 102, 102, 102, 102, 126, 60, 0, 0]]]
char+=[["P", "", [0, 0, 124, 126, 102, 102, 102, 102, 126, 124, 96, 96, 96, 96, 0, 0]]]
char+=[["Q", "", [0, 0, 60, 126, 102, 102, 102, 102, 102, 102, 102, 106, 124, 54, 0, 0]]]
char+=[["R", "", [0, 0, 248, 252, 204, 204, 204, 252, 248, 216, 204, 204, 198, 198, 0, 0]]]
char+=[["S", "", [0, 0, 62, 126, 96, 96, 112, 56, 28, 14, 6, 6, 126, 124, 0, 0]]]
char+=[["T", "", [0, 0, 126, 126, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 0, 0]]]
char+=[["U", "", [0, 0, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 126, 60, 0, 0]]]
char+=[["V", "", [0, 0, 102, 102, 102, 102, 102, 102, 102, 102, 60, 60, 24, 24, 0, 0]]]
char+=[["W", "", [0, 0, 198, 198, 198, 198, 198, 214, 214, 254, 254, 238, 198, 130, 0, 0]]]
char+=[["X", "", [0, 0, 102, 102, 102, 60, 60, 24, 24, 60, 60, 102, 102, 102, 0, 0]]]
char+=[["Y", "", [0, 0, 102, 102, 102, 102, 60, 60, 24, 24, 24, 24, 24, 24, 0, 0]]]
char+=[["Z", "", [0, 0, 126, 126, 12, 12, 24, 24, 48, 48, 96, 96, 126, 126, 0, 0]]]
char+=[["[", "", [0, 0, 30, 30, 24, 24, 24, 24, 24, 24, 24, 24, 30, 30, 0, 0]]]
# \ is an escape character: needs to be escaped by another \
char+=[["\\", "", [0, 0, 96, 96, 96, 48, 48, 24, 24, 12, 12, 6, 6, 6, 0, 0]]]
char+=[["]", "", [0, 0, 120, 120, 24, 24, 24, 24, 24, 24, 24, 24, 120, 120, 0, 0]]]
char+=[["^", "", [0, 16, 16, 56, 56, 108, 108, 198, 198, 0, 0, 0, 0, 0, 0, 0]]]
char+=[["_", "", [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 254, 254, 0, 0]]]
char+=[["`", "&grave;", [0, 0, 112, 56, 28, 12, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0]]]
char+=[["a", "", [0, 0, 0, 0, 0, 60, 62, 6, 62, 126, 102, 102, 126, 62, 0, 0]]]
char+=[["b", "", [0, 0, 96, 96, 96, 124, 126, 102, 102, 102, 102, 102, 126, 124, 0, 0]]]
char+=[["c", "", [0, 0, 0, 0, 0, 60, 124, 96, 96, 96, 96, 96, 126, 62, 0, 0]]]
char+=[["d", "", [0, 0, 6, 6, 6, 62, 126, 102, 102, 102, 102, 102, 126, 62, 0, 0]]]
char+=[["e", "", [0, 0, 0, 0, 0, 60, 126, 102, 102, 126, 96, 96, 126, 62, 0, 0]]]
char+=[["f", "", [0, 0, 14, 30, 24, 24, 126, 126, 24, 24, 24, 24, 24, 24, 0, 0]]]
char+=[["g", "", [0, 0, 0, 0, 0, 62, 126, 102, 102, 102, 102, 126, 62, 6, 126, 124]]]
char+=[["h", "", [0, 0, 96, 96, 96, 124, 126, 102, 102, 102, 102, 102, 102, 102, 0, 0]]]
char+=[["i", "", [0, 0, 24, 24, 0, 56, 56, 24, 24, 24, 24, 24, 60, 60, 0, 0]]]
char+=[["j", "", [0, 0, 12, 12, 0, 12, 12, 12, 12, 12, 12, 12, 12, 12, 124, 120]]]
char+=[["k", "", [0, 0, 192, 192, 192, 204, 220, 248, 240, 248, 216, 204, 206, 198, 0, 0]]]
char+=[["l", "", [0, 0, 56, 56, 24, 24, 24, 24, 24, 24, 24, 24, 60, 60, 0, 0]]]
char+=[["m", "", [0, 0, 0, 0, 0, 108, 254, 254, 214, 214, 214, 198, 198, 198, 0, 0]]]
char+=[["n", "", [0, 0, 0, 0, 0, 60, 126, 102, 102, 102, 102, 102, 102, 102, 0, 0]]]
char+=[["o", "", [0, 0, 0, 0, 0, 60, 126, 102, 102, 102, 102, 102, 126, 60, 0, 0]]]
char+=[["p", "", [0, 0, 0, 0, 0, 124, 126, 102, 102, 102, 102, 102, 126, 124, 96, 96]]]
char+=[["q", "", [0, 0, 0, 0, 0, 62, 126, 102, 102, 102, 102, 102, 126, 62, 6, 6]]]
char+=[["r", "", [0, 0, 0, 0, 0, 124, 126, 102, 96, 96, 96, 96, 96, 96, 0, 0]]]
char+=[["s", "", [0, 0, 0, 0, 0, 62, 126, 96, 112, 60, 14, 6, 126, 124, 0, 0]]]
char+=[["t", "", [0, 0, 0, 24, 24, 126, 126, 24, 24, 24, 24, 24, 30, 14, 0, 0]]]
char+=[["u", "", [0, 0, 0, 0, 0, 102, 102, 102, 102, 102, 102, 102, 126, 62, 0, 0]]]
char+=[["v", "", [0, 0, 0, 0, 0, 102, 102, 102, 102, 102, 60, 60, 24, 24, 0, 0]]]
char+=[["w", "", [0, 0, 0, 0, 0, 198, 198, 214, 214, 254, 254, 238, 198, 130, 0, 0]]]
char+=[["x", "", [0, 0, 0, 0, 0, 102, 102, 60, 60, 24, 60, 60, 102, 102, 0, 0]]]
char+=[["y", "", [0, 0, 0, 0, 0, 102, 102, 102, 102, 102, 102, 126, 62, 6, 126, 124]]]
char+=[["z", "", [0, 0, 0, 0, 0, 126, 126, 12, 24, 24, 48, 48, 126, 126, 0, 0]]]
char+=[["{", "", [0, 14, 24, 24, 24, 24, 56, 240, 240, 56, 24, 24, 24, 24, 14, 0]]]
char+=[["|", "", [0, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 0]]]
char+=[["}", "", [0, 224, 48, 48, 48, 48, 56, 30, 30, 56, 48, 48, 48, 48, 224, 0]]]
char+=[["~", "&tilde;", [0, 0, 0, 0, 0, 98, 242, 190, 156, 0, 0, 0, 0, 0, 0, 0]]]
char+=[["&Delta;", "&Delta;", [0, 0, 0, 0, 0, 24, 24, 60, 36, 102, 66, 195, 255, 0, 0, 0]]]
char+=[["&Ccedil;", "&Ccedil;", [0, 0, 60, 126, 102, 102, 96, 96, 96, 96, 102, 102, 126, 60, 12, 56]]]
char+=[["&uuml;", "&uuml;", [0, 0, 102, 102, 0, 102, 102, 102, 102, 102, 102, 102, 126, 62, 0, 0]]]
char+=[["&eacute;", "&eacute;", [0, 6, 12, 24, 0, 60, 126, 102, 102, 126, 96, 96, 126, 62, 0, 0]]]
char+=[["&acirc;", "&acirc;", [0, 24, 60, 102, 0, 60, 62, 6, 62, 126, 102, 102, 126, 62, 0, 0]]]
char+=[["&auml;", "&auml;", [0, 0, 102, 102, 0, 60, 62, 6, 62, 126, 102, 102, 126, 62, 0, 0]]]
char+=[["&agrave;", "&agrave;", [0, 96, 48, 24, 0, 60, 62, 6, 62, 126, 102, 102, 126, 62, 0, 0]]]
char+=[["&aring;", "&arond;", [0, 28, 54, 28, 0, 60, 62, 6, 62, 126, 102, 102, 126, 62, 0, 0]]]
char+=[["&ccedil;", "&ccedil;", [0, 0, 0, 0, 0, 60, 124, 96, 96, 96, 96, 96, 126, 62, 12, 56]]]
char+=[["&ecirc;", "&ecirc;", [0, 24, 60, 102, 0, 60, 126, 102, 102, 126, 96, 96, 126, 62, 0, 0]]]
char+=[["&euml;", "&euml;", [0, 0, 102, 102, 0, 60, 126, 102, 102, 126, 96, 96, 126, 62, 0, 0]]]
char+=[["&egrave;", "&egrave;", [0, 96, 48, 24, 0, 60, 126, 102, 102, 126, 96, 96, 126, 62, 0, 0]]]
char+=[["&iuml;", "&iuml;", [0, 0, 102, 102, 0, 56, 56, 24, 24, 24, 24, 24, 60, 60, 0, 0]]]
char+=[["&icirc;", "&icirc;", [0, 24, 60, 102, 0, 56, 56, 24, 24, 24, 24, 24, 60, 60, 0, 0]]]
char+=[["&igrave;", "&igrave;", [0, 96, 48, 24, 0, 56, 56, 24, 24, 24, 24, 24, 60, 60, 0, 0]]]
char+=[["&Auml;", "&Auml;", [0, 102, 102, 24, 60, 126, 102, 102, 126, 126, 102, 102, 102, 102, 0, 0]]]
char+=[["&Aring;", "&Arond;", [60, 102, 60, 24, 60, 126, 102, 102, 126, 126, 102, 102, 102, 102, 0, 0]]]
char+=[["&Eacute;", "&Eacute;", [6, 12, 24, 126, 126, 96, 96, 124, 124, 96, 96, 96, 126, 126, 0, 0]]]
char+=[["&aelig;", "&aelig;", [0, 0, 0, 0, 0, 118, 127, 27, 123, 255, 216, 216, 255, 127, 0, 0]]]
char+=[["&AElig;", "&AElig;", [0, 62, 126, 248, 216, 216, 222, 222, 248, 248, 216, 216, 222, 222, 0, 0]]]
char+=[["&ocirc;", "&ocirc;", [0, 24, 60, 102, 0, 60, 126, 102, 102, 102, 102, 102, 126, 60, 0, 0]]]
char+=[["&ouml;", "&ouml;", [0, 0, 102, 102, 0, 60, 126, 102, 102, 102, 102, 102, 126, 60, 0, 0]]]
char+=[["&ograve;", "&ograve;", [0, 96, 48, 24, 0, 60, 126, 102, 102, 102, 102, 102, 126, 60, 0, 0]]]
char+=[["&ucirc;", "&ucirc;", [0, 24, 60, 102, 0, 102, 102, 102, 102, 102, 102, 102, 126, 62, 0, 0]]]
char+=[["&ugrave;", "&ugrave;", [0, 96, 48, 24, 0, 102, 102, 102, 102, 102, 102, 102, 126, 62, 0, 0]]]
char+=[["&yuml;", "&yuml;", [0, 0, 102, 102, 0, 102, 102, 102, 102, 102, 102, 126, 62, 6, 126, 124]]]
char+=[["&Ouml;", "&Ouml;", [0, 102, 102, 0, 60, 126, 102, 102, 102, 102, 102, 102, 126, 60, 0, 0]]]
char+=[["&Uuml;", "&Uuml;", [0, 102, 102, 0, 102, 102, 102, 102, 102, 102, 102, 102, 126, 60, 0, 0]]]
char+=[["&cent;", "&cent;", [0, 0, 24, 24, 60, 126, 102, 96, 96, 102, 126, 60, 24, 24, 0, 0]]]
char+=[["&pound;", "&pound;", [0, 14, 30, 56, 48, 48, 48, 48, 254, 48, 48, 48, 127, 255, 0, 0]]]
char+=[["&yen;", "&yen;", [0, 0, 102, 102, 102, 102, 126, 60, 24, 126, 24, 24, 24, 24, 0, 0]]]
char+=[["&szlig;", "&szlig;", [0, 0, 24, 60, 102, 102, 102, 124, 102, 102, 102, 124, 108, 96, 64, 0]]]
char+=[["&fnof;", "&fnof; florin ou fonction", [0, 0, 14, 30, 24, 24, 24, 126, 24, 24, 24, 24, 24, 112, 96, 0]]]
char+=[["&aacute;", "&aacute;", [0, 6, 12, 24, 0, 60, 62, 6, 62, 126, 102, 102, 126, 62, 0, 0]]]
char+=[["&iacute;", "&iacute;", [0, 6, 12, 24, 0, 56, 56, 24, 24, 24, 24, 24, 60, 60, 0, 0]]]
char+=[["&oacute;", "&oacute;", [0, 6, 12, 24, 0, 60, 126, 102, 102, 102, 102, 102, 126, 60, 0, 0]]]
char+=[["&uacute;", "&aacute;", [0, 6, 12, 24, 0, 102, 102, 102, 102, 102, 102, 102, 126, 62, 0, 0]]]
char+=[["&ntilde;", "&ntilde;", [0, 50, 122, 76, 0, 60, 126, 102, 102, 102, 102, 102, 102, 102, 0, 0]]]
char+=[["&Ntilde;", "&Ntilde;", [0, 50, 122, 76, 0, 102, 102, 118, 126, 126, 110, 102, 102, 102, 0, 0]]]
char+=[["&ordf;", "&ordf;", [0, 0, 0, 0, 60, 62, 6, 62, 126, 102, 102, 126, 62, 0, 126, 0]]]
char+=[["&ordm;", "&ordm;", [0, 0, 0, 0, 60, 126, 102, 102, 102, 102, 102, 126, 60, 0, 126, 0]]]
char+=[["&iquest;", "&iquest;", [0, 0, 24, 24, 0, 24, 24, 24, 48, 48, 102, 102, 126, 60, 0, 0]]]
char+=[["⌐", "&bnot;", [0, 0, 0, 0, 0, 0, 0, 0, 0, 126, 126, 96, 96, 96, 0, 0]]]
char+=[["&not;", "&not;", [0, 0, 0, 0, 0, 0, 0, 0, 0, 126, 126, 6, 6, 6, 0, 0]]]
char+=[["&frac12;", "&half;", [0, 96, 32, 32, 35, 38, 44, 24, 48, 110, 211, 6, 12, 24, 31, 0]]]
char+=[["&frac14;", "&frac14;", [0, 96, 32, 32, 35, 38, 44, 24, 50, 102, 206, 26, 50, 63, 2, 0]]]
char+=[["&iexcl;", "&iexcl;", [0, 0, 0, 24, 24, 0, 24, 24, 24, 24, 24, 24, 24, 24, 24, 0]]]
char+=[["&laquo;", "&laquo;", [0, 0, 0, 0, 0, 0, 26, 54, 108, 216, 108, 54, 26, 0, 0, 0]]]
char+=[["&raquo;", "&raquo;", [0, 0, 0, 0, 0, 0, 176, 216, 108, 54, 108, 216, 176, 0, 0, 0]]]
char+=[["&atilde;", "&atilde;", [0, 50, 122, 76, 0, 60, 62, 6, 62, 126, 102, 102, 126, 62, 0, 0]]]
char+=[["&otilde;", "&otilde;", [0, 50, 122, 76, 0, 60, 126, 102, 102, 102, 102, 102, 126, 60, 0, 0]]]
char+=[["&Oslash;", "&Oslash;", [0, 1, 61, 126, 102, 102, 110, 110, 118, 118, 102, 102, 126, 188, 128, 0]]]
char+=[["&oslash;", "&oslash;", [0, 0, 0, 0, 1, 61, 126, 102, 110, 126, 118, 102, 126, 188, 128, 0]]]
char+=[["&oelig;", "&oelig;", [0, 0, 0, 0, 0, 126, 255, 219, 219, 223, 216, 216, 255, 127, 0, 0]]]
char+=[["&OElig;", "&OElig;", [0, 0, 126, 254, 216, 216, 222, 222, 216, 216, 216, 216, 254, 126, 0, 0]]]
char+=[["&Agrave;", "&Agrave;", [96, 48, 24, 0, 60, 126, 102, 102, 126, 126, 102, 102, 102, 102, 0, 0]]]
char+=[["&Atilde;", "&Atilde;", [50, 122, 76, 0, 60, 126, 102, 102, 126, 126, 102, 102, 102, 102, 0, 0]]]
char+=[["&Otilde;", "&Otilde;", [50, 122, 76, 0, 60, 126, 102, 102, 102, 102, 102, 102, 126, 60, 0, 0]]]
char+=[["&uml;", "&uml;", [0, 102, 102, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]]
char+=[["&acute;", "&acute;", [0, 6, 12, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]]
char+=[["&dagger;", "&dagger;", [0, 16, 124, 16, 16, 16, 16, 16, 0, 0, 0, 0, 0, 0, 0, 0]]]
char+=[["&para;", "&para;", [0, 0, 122, 202, 202, 202, 202, 202, 122, 10, 10, 10, 10, 10, 0, 0]]]
char+=[["&copy;", "&copy;", [0, 0, 124, 198, 130, 186, 162, 162, 162, 186, 130, 198, 124, 0, 0, 0]]]
char+=[["&reg;", "&reg;", [0, 0, 124, 198, 130, 186, 170, 178, 186, 170, 130, 198, 124, 0, 0, 0]]]
char+=[["&trade;", "&trade;", [241, 91, 95, 85, 81, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]]
char+=[["ij", "&ijlig;", [0, 102, 102, 0, 230, 102, 102, 102, 102, 102, 102, 102, 246, 14, 60, 56]]]
char+=[["IJ", "&IJlig;", [246, 246, 102, 102, 102, 102, 102, 102, 102, 102, 102, 246, 246, 14, 124, 120]]]
char+=[["א", "alef", [0, 0, 102, 118, 118, 62, 60, 60, 110, 110, 102, 98, 0, 0, 0, 0]]]
char+=[["ב", "bet", [0, 0, 124, 124, 12, 12, 12, 12, 12, 12, 126, 126, 0, 0, 0, 0]]]
char+=[["ג", "gimel", [0, 0, 30, 30, 6, 6, 14, 30, 54, 54, 54, 54, 0, 0, 0, 0]]]
char+=[["ד", "dalet", [0, 0, 126, 126, 12, 12, 12, 12, 12, 12, 12, 12, 0, 0, 0, 0]]]
char+=[["ה", "he", [0, 0, 126, 126, 6, 102, 102, 102, 102, 102, 102, 102, 0, 0, 0, 0]]]
char+=[["ו", "vav", [0, 0, 56, 56, 24, 24, 24, 24, 24, 24, 24, 24, 0, 0, 0, 0]]]
char+=[["ז", "zayin", [0, 0, 30, 30, 4, 12, 12, 12, 12, 12, 12, 4, 0, 0, 0, 0]]]
char+=[["ח", "het", [0, 0, 126, 126, 102, 102, 102, 102, 102, 102, 102, 102, 0, 0, 0, 0]]]
char+=[["ט", "tet", [0, 0, 110, 110, 102, 102, 102, 102, 102, 102, 126, 126, 0, 0, 0, 0]]]
char+=[["י", "yod", [0, 0, 60, 60, 12, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]]
char+=[["כ", "kaf", [0, 0, 60, 62, 6, 6, 6, 6, 6, 6, 62, 60, 0, 0, 0, 0]]]
char+=[["ל", "lamed", [96, 96, 126, 126, 6, 6, 6, 14, 28, 48, 48, 48, 0, 0, 0, 0]]]
char+=[["מ", "mem", [0, 0, 108, 110, 62, 54, 102, 102, 102, 110, 110, 110, 0, 0, 0, 0]]]
char+=[["נ", "nun", [0, 0, 28, 28, 12, 12, 12, 12, 12, 12, 124, 124, 0, 0, 0, 0]]]
char+=[["ס", "samekh", [0, 0, 254, 254, 254, 198, 198, 198, 198, 198, 254, 124, 0, 0, 0, 0]]]
char+=[["ע", "ayin", [0, 0, 54, 54, 54, 54, 54, 54, 54, 54, 126, 126, 0, 0, 0, 0]]]
char+=[["פ", "pe", [0, 0, 126, 126, 102, 102, 118, 118, 6, 126, 126, 126, 0, 0, 0, 0]]]
char+=[["צ", "tsadi", [0, 0, 110, 110, 102, 54, 62, 24, 28, 14, 126, 126, 0, 0, 0, 0]]]
char+=[["ק", "qof", [0, 0, 62, 62, 62, 6, 6, 54, 54, 54, 54, 54, 48, 48, 48, 0]]]
char+=[["ר", "resh", [0, 0, 124, 126, 6, 6, 6, 6, 6, 6, 6, 6, 0, 0, 0, 0]]]
char+=[["ש", "shin", [0, 0, 214, 214, 214, 214, 246, 246, 198, 198, 254, 254, 0, 0, 0, 0]]]
char+=[["ת", "tav", [0, 0, 126, 126, 102, 102, 102, 102, 102, 102, 230, 230, 0, 0, 0, 0]]]
char+=[["ן", "final nun", [0, 0, 56, 56, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 0, 0]]]
char+=[["ך", "final kaf", [0, 0, 126, 126, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 0, 0]]]
char+=[["ם", "final mem", [0, 0, 126, 62, 54, 54, 54, 54, 54, 54, 62, 62, 0, 0, 0, 0]]]
char+=[["ף", "final pe", [0, 0, 126, 126, 102, 102, 118, 118, 6, 6, 6, 6, 6, 6, 0, 0]]]
char+=[["ץ", "final tsadi", [0, 0, 110, 110, 102, 118, 62, 14, 6, 6, 6, 6, 6, 6, 0, 0]]]
char+=[["&sect;", "&sect;", [0, 0, 28, 54, 50, 24, 60, 102, 102, 60, 24, 76, 108, 56, 0, 0]]]
char+=[["&and;", "&and;", [0, 0, 0, 0, 0, 16, 16, 56, 56, 108, 108, 198, 198, 0, 0, 0]]]
char+=[["&infin;", "&infin;", [0, 0, 0, 0, 102, 247, 153, 153, 239, 102, 0, 0, 0, 0, 0, 0]]]
char+=[["&alpha;", "&alpha;", [0, 0, 0, 0, 98, 246, 220, 136, 136, 220, 246, 98, 0, 0, 0, 0]]]
char+=[["&beta;", "&beta;", [0, 0, 24, 60, 102, 102, 102, 124, 102, 102, 102, 124, 108, 96, 64, 0]]]
char+=[["&Gamma;", "&Gamma;", [0, 0, 254, 126, 98, 96, 96, 96, 96, 96, 96, 96, 96, 240, 0, 0]]]
char+=[["&pi;", "&pi;", [0, 0, 0, 0, 2, 126, 252, 168, 40, 40, 40, 40, 0, 0, 0, 0]]]
char+=[["&Sigma;", "&Sigma;", [0, 0, 254, 254, 96, 48, 24, 12, 12, 24, 48, 96, 254, 254, 0, 0]]]
char+=[["&sigma;", "&sigma;", [0, 0, 0, 0, 30, 56, 108, 198, 198, 198, 198, 108, 56, 0, 0, 0]]]
char+=[["&micro;", "&mu;", [0, 0, 0, 0, 0, 102, 102, 102, 102, 102, 102, 127, 93, 192, 128, 0]]]
char+=[["&tau;", "&tau;", [0, 0, 0, 2, 126, 252, 144, 48, 48, 48, 48, 32, 0, 0, 0, 0]]]
char+=[["&Phi;", "&Phi;", [0, 124, 16, 16, 124, 198, 130, 130, 130, 130, 198, 124, 16, 16, 124, 0]]]
char+=[["&theta;", "&theta;", [0, 0, 60, 126, 102, 66, 66, 126, 66, 66, 102, 126, 60, 0, 0, 0]]]
char+=[["&Omega;", "&Omega;", [0, 0, 56, 108, 198, 198, 198, 198, 108, 40, 170, 238, 108, 0, 0, 0]]]
char+=[["&delta;", "&delta;", [0, 30, 62, 32, 48, 24, 60, 102, 66, 66, 102, 126, 60, 0, 0, 0]]]
char+=[["∮", "&conint;", [0, 14, 30, 16, 124, 214, 146, 146, 146, 146, 214, 124, 16, 240, 224, 0]]]
char+=[["&phi;", "&phi;", [0, 0, 16, 16, 124, 214, 146, 146, 146, 146, 214, 124, 16, 16, 0, 0]]]
char+=[["&isin;", "&in;", [0, 0, 62, 126, 224, 192, 192, 252, 252, 192, 192, 224, 126, 62, 0, 0]]]
char+=[["&Pi;", "&Pi;", [0, 0, 124, 254, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 0, 0]]]
char+=[["&equiv;", "&equiv;", [0, 0, 0, 0, 126, 126, 0, 126, 126, 0, 126, 126, 0, 0, 0, 0]]]
char+=[["&plusmn;", "&plusmn;", [0, 0, 0, 24, 24, 24, 126, 126, 24, 24, 24, 0, 126, 126, 0, 0]]]
char+=[["&ge;", "&ge;", [0, 0, 96, 112, 56, 28, 14, 28, 56, 112, 96, 0, 126, 126, 0, 0]]]
char+=[["&le;", "&le;", [0, 0, 6, 14, 28, 56, 112, 56, 28, 14, 6, 0, 126, 126, 0, 0]]]
char+=[["⌠", "top half integral", [0, 0, 14, 25, 27, 27, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24]]]
char+=[["⌡", "bottom half integral", [24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 216, 216, 152, 112, 0, 0]]]
char+=[["&divide;", "&divide;", [0, 0, 0, 24, 24, 0, 126, 126, 0, 24, 24, 0, 0, 0, 0, 0]]]
char+=[["&asymp;", "&symp;", [0, 0, 0, 2, 62, 124, 64, 2, 62, 124, 64, 0, 0, 0, 0, 0]]]
char+=[["&deg;", "&deg;", [0, 56, 108, 68, 108, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]]
char+=[["?", "full deg, sup bullet", [0, 56, 124, 124, 124, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]]
char+=[["&bull;", "&bull;", [0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 60, 60, 24, 0, 0, 0]]]
char+=[["&radic;", "&radical", [0, 0, 0, 0, 0, 31, 16, 208, 208, 80, 112, 32, 0, 0, 0, 0]]]
char+=[["ⁿ", "sup n", [0, 0, 48, 120, 72, 72, 72, 72, 0, 0, 0, 0, 0, 0, 0, 0]]]
char+=[["&sup2;", "&sup2", [0, 0, 48, 72, 24, 48, 96, 120, 0, 0, 0, 0, 0, 0, 0, 0]]]
char+=[["&sup3;", "&sup3", [0, 0, 120, 24, 48, 24, 72, 48, 0, 0, 0, 0, 0, 0, 0, 0]]]
char+=[["&macr;", "&macr", [0, 254, 254, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]]
 
bitoff="  " # background (bit=0)
biton="&&" # foreground (bit=1)
# if your system knows ecma-48 way to print colours:
# biton="33[47m  33[0m"
 
for i in range(len(char)):
  cluster=char[i]
  print "%03d %s  %s" %(i+1, cluster[0], cluster[1])
  liste=cluster[2]
  for j in range(16): # runs through character 16 numbers
    ligne=liste[j]
    chaine=""
    for k in range(7, -1, -1): # runs through number 8 bits (strong -> week)
      if ligne & 2**k:
        chaine+=biton
      else:
        chaine+=bitoff
    print chaine
  raw_input()

 

 

 

Brainf*ck interpreter

I found in my archives a brainf*ck interpreter written five years ago.

Brainf*ck is a 8 (eight) instructions set programming language:

  • < and > walks through a set of pointers (0 -> ...)
  • + and - increases or decreases the current pointer (0 <->255)
  • [ jumps to the related ']' if the current pointer is 0
  • ] jumps back to the related '[' if the current pointer is > 0
  • . displays the character equivalent to the ascii rank defined by the current pointer (65 is 'A')
  • , gets a character and puts it in the current pointer (in this app: waits a key with raw_input!)

This application is on debugging mode: it vertically displays any change of pointer, value and output!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
#! /usr/bin/python
 
# Brainf*ck interpreter
# Jean-Christophe Beumier - GPL2 license
# Version 1.00 2009.07.28 -
 
i=0; ptr=0; bytes=[0]; depth=0
 
prg="Capitalizes a minuscule: >>,<<++++[>++[>----<-]<-]>>." # here comes the bf script
end=len(prg)
 
while (i<end):
  char=prg[i] # spells the program string
 
  if (char=='>'):
    ptr=ptr+1
    if ptr>len(bytes)-1: # needs to add a cell to the pointer list
      bytes+=[0]
    print "% 6.f#% 7.f% 4.f  %s" %(i, ptr, bytes[ptr], "pter +1")
 
  elif (char=='<'):
    ptr=ptr-1;
    print "% 6.f#% 7.f% 4.f  %s" %(i, ptr, bytes[ptr], "pter -1")
    if (ptr<0):
      print "*** Negative pointer doesn't work ***"
 
  elif (char=='+'):
    bytes[ptr]=bytes[ptr]+1;
    if bytes[ptr]==256: bytes[ptr]=0
    print "% 6.f#% 7.f% 4.f  %s" %(i, ptr, bytes[ptr],"byte +1")
 
  elif (char=='-'):
    bytes[ptr]=bytes[ptr]-1 ;
    print "% 6.f#% 7.f% 4.f  %s" %(i, ptr, bytes[ptr],"byte -1")
    if bytes[ptr]==-1: bytes[ptr]=255
 
  elif (char=="["):
    if (bytes[ptr]==0):
      print "% 6.f#% 7.f% 4.f  %s" %(i, ptr, bytes[ptr],"cancelled loop!")
      depth=1
      while(depth>0):
        i+=1
        if prg[i] =="[":
          depth+=1
        if prg[i] =="]":
          depth-=1
    else:
      print "% 6.f#% 7.f% 4.f  %s" %(i, ptr, bytes[ptr],"loop in")
 
  elif (char=="]"):
    if (bytes[ptr]>0):
      print "% 6.f#% 7.f% 4.f  %s" %(i, ptr, bytes[ptr],"loop on")
      depth=1
      while(depth>0):
        i=i-1
        if prg[i] =="]":
          depth+=1
        if prg[i] =="[":
          depth-=1
    else:
      print "% 6.f#% 7.f% 4.f  %s" %(i, ptr, bytes[ptr],"loop out ")
 
  elif (char=='.'):
    print "% 6.f#% 7.f% 4.f  %s" %(i, ptr, bytes[ptr],"output: "), chr(bytes[ptr])
 
  elif (char==','):
    print "% 6.f#% 7.f% 4.f  %s" %(i, ptr, bytes[ptr],"input:  "),
    key=raw_input()
    bytes[ptr]=ord(key)
 
  else:
    print "% 6.f#% 7.f% 4.f  Comment: %s" %(i, ptr, bytes[ptr], char)
  i=i+1
 
raw_input("\n###  End of program. Strike [Enter]  ###")

You can try the canonical Hello world!

++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>---.+++++++..+++.>>.<-.<.+++.------.--------.>>+.>++.

 

 

displaying dynamic graphic (and saving it after a while)

A friend of mine, who plays with a raspberry nano computer, wanted to display a sensor (don't remember which). So I tried to write a program getting a data, displaying it by Tkinter, and saving the graphic.

Un ami, qui s'amuse avec le nano computer raspberry, désirait afficher les données d'une sonde (je ne sais plus laquelle). J'ai donc tenté d'écrire un programme qui reçoit des données, les affiche en continu et les sauve de temps en temps.

This script does:

  • display a dot every second (using the Tkinter after() fonction) at the right of the graphic
  • shift the graphic one pixel per second to the left, letting you see the ten past minutes
  • tag the time (hh:mm) at the 50th second, with a matrixed digit method
  • save the graphic every ten minutes (.PGM, Portable Gray Map, a category of PNM)
  • seem to be python3 compatible (displaying: yes, saving: smog until now)
  • what else?

Ce script:

  • inscrit un point toutes les secondes à la droite du graphique, avec la méthode after() de Tkinter
  • déplace le graphique d'un pixel à droite, permettant de regarder les dix dernières minutes
  • écrit le temps hh:mm à la 50e secondes, avec une routine basée sur une matrice de points
  • sauve le graphique toutes les dix minutes (PGM, Portable Gray Map, une catégorie de PNM)
  • semble être compatible avec python3 (l'affichage, mais la sauvegarde est une purée de pois)
  • quoi d'autre?

The script is more or less commented, but I'm a rather wild scripter.

Calling a routine every second - after(1000, routine) - is not the best way to pace a program, because there are so many things the program does between each call! I prefer to ask every tenth of second whether it's already the next second. You can do better with a call every hundredth of second.

Le script est plus ou moins commenté (en mauvais anglais).

Utiliser une pause d'une seconde par la méthode after(1000, routine) (Tkinter) est une mauvaise chose, parce que le script prend également du temps pour faire tout ce qu'il a à faire entre deux pauses. Je préfère donc demander tous les dixièmes de seconde si le système est passé à la seconde suivante. Vous pouvez faire mieux en faisant un appel tous les 100e de secondes. 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
#! /usr/bin/python -Qnew
 
# 2014.11.14 Jean-Christophe Beumier - www.jchr.be
# GPL2, see www.gnu.org/licenses/licenses.html
 
# dynamic display of data from any sensor or computing
# saving graphic files .PNM every 10 minutes
 
import time, os
from Tkinter import *
from math import *
 
# for python 3:
#! /usr/bin/python3
# from tkinter import * 
 
# digit matrix for printdate()
dates=[[6, 9, 9, 9, 9, 9, 6]]
dates+=[[2, 6, 2, 2, 2, 2, 7]]
dates+=[[6, 9, 1, 2, 4, 8, 15]]
dates+=[[6, 9, 1, 2, 1, 9, 6]]
dates+=[[2, 2, 6, 6, 10, 15, 2]]
dates+=[[15, 8, 14, 1, 1, 9, 6]]
dates+=[[6, 8, 14, 9, 9, 9, 6]]
dates+=[[15, 1, 2, 2, 4, 4, 4]]
dates+=[[6, 9, 9, 6, 9, 9, 6]]
dates+=[[6, 9, 9, 9, 7, 1, 6]]
 
tab=[chr(255)]*66000   # list ("table") for image 600x100px
for i in range(600):
  tab[29400+i]=chr(144) # gray horizontal line at mid-height
imgdata="".join(tab) # joining the bytes
p5="P5 600 110 255\n"+imgdata # header and image-data 
 
ang=0
def sensor():
  global ang
  #   on UNIX, 'acpi -t' returns 'Thermal 0: ok, 36.0 degrees C'
  # pfile=os.popen("acpi -t", "r")
  # line=pfile.read()
  # pfile.close()
  # temp=int(round(float(line.split()[3]))) # 4th string of the line
 
  #   not sure you're on Unix, so let's compute something:
  calcul=sin(ang/19)/(1+abs(tan(ang/27)))*39+abs(cos(ang/10))*10
  ang+=1
  return(calcul) 
 
def printdate(x):
  global dates, tab
  if x==1:
    string=time.strftime("%H:%M")
    colour=0 # black digits for time
  else:
    string=time.strftime("%Y.%m.%d")
    colour=80 # dark gray digits for date
  off=0
  for p in string:
    try:
      a=int(p)  # is a number
      cp=0 # vertical offset for digit matrix printing
      for q in dates[a]: # q is a number matrix
        for r in range(4):
          if q & 2**r: # matching bit of number
            tab[600*(102+cp)+549+off+5-r]=chr(colour)
        cp+=1
      off+=5
    except:
      if p==".": # not a number
        tab[600*108+548+off+3]=chr(0)
        off+=3
      elif p==":":
        tab[600*104+549+off+3]=chr(0)
        tab[600*107+549+off+3]=chr(0)
        off+=4
 
h=49 # mid-height
count=int(time.strftime("%S")) # getting the first second
filename=time.strftime("%Y.%m.%d-%Hh%M")
def formage():
  global count, tab, p5, h, filename
  if count%10==0:  # gray dotted vertical line every 10px
    if count==0:   # the first darker
      for i in range(100):
        tab[i*600+599]=chr(64)
    elif count%60==0: # plain line every 60px (minute)
      for i in range(100):
        tab[i*600+599]=chr(144)
    else:
      for i in range(50): # printing date or time
        tab[i*1200+1199]=chr(144)
      if count%60==50:
        if count//60==1:
          printdate(2) # date
        else:
          printdate(1) # time
      
  sortie=sensor()
  h=50+int(sortie)
  if h>99: h=99 # display from 0 to 99, no outside
  if h<0: h=0 
  tab[(99-h)*600+599]=chr(0) # writing the dot into the matrix
 
  p5="P5 600 110 255\n"+"".join(tab) # assembling PNM image
  for i in range(110): # rubbing out the first column
    tab[i*600]=chr(255)
  tab=tab[1:]+[chr(255)] # deleting 1 byte: shifting 1px to left
  tab[29999]=chr(144)    # middle point
  if count%2==1: # 1 out of 2px
    tab[5999]=chr(144)   # adding 90%
    tab[11999]=chr(144)  # adding 80%
    tab[17999]=chr(144)  # adding 70%
    tab[23999]=chr(144)  # adding 60%
    tab[35999]=chr(144)  # adding 40%
    tab[41999]=chr(144)  # adding 30%
    tab[47999]=chr(144)  # adding 20%
    tab[53999]=chr(144)  # adding 10%
 
  count+=1
  if count==600: # saving after 600 dots (image width)
    han=open("tk-%s.pgm" %(filename),"w")
    han.write(p5)
    han.close()
    count=0
    filename=time.strftime("%Y.%m.%d-%Hh%M") # next one
 
  label0.config(text="%5.2f" %(round(sortie,2)))  # rewriting
  image0.config(data=p5)       # image redrawing
  label1.config(image=image0)  # image redisplaying
 
sec0=99
def checktime():
  global sec0
  nsec=int(time.strftime("%S"))
  if nsec!=sec0:
    sec0=nsec    
    formage()
  root0.after(100, checktime)  # waits 0.1sec, before reiteration
 
# tkinter setting:
 
root0=Tk()
root0.geometry("620x150")
label0=Label(root0, text="0.00")
label0.pack()
label0.after(0, checktime)   # waiting 0 sec and calling
image0=PhotoImage(data=p5)
label1=Label(image=image0) # image displaying
label1.image=image0
label1.pack()
 
root0.mainloop()

 

 

gui for 'boucles' application

2014.11.07: on debugging now - maintenant en débogage

Do you want to be able to produce this kind of image

 

...with this kind of application (python+Tkinter)?

Coming soon!

French help-info (I would like to have english, spanish and dutch (.nl) translation):

"""Translation by Your-Name - 2014.12.xx

Argument
Comme la terre tourne autour du soleil, la lune autour de la terre et Lunik 10 autour de la lune du 3 avril au 30 mai 1966, cette application dessine une courbe fermée composée de trois cycles dans un carré de 512px de côté

Boutons du haut

[Exit] fait quitter l'application
[Charg.] (en débogage) charge des paramètres en fonction du titre d'une image déjà sauvegardée.
[Sauv.] sauvegarde le graphique réalisé par l'application, au format PNM: «P5» pour les dessins en N/B ou gris, ou «P6» pour les dessins en couleurs. Pour les systèmes UNIX munis de ImageMagick, le fichier au format PNM est transformé en PNG, économique et sans perte de qualité. Les données sont écrites dans le nom du fichier, ce qui permet à l'application de se remémorer les paramètres en chargeant le fichier.

Informations

'00008 kilopt' donne le nombre de milliers de points que les boutons [Dessin] ou [Ajout] vont dessiner. Sur un amd64 à 1.7GHz, cela prend environ 20 kpt par seconde: Le maximum, 30720, prendrait alors 1500 secondes, c'est-à-dire 25 minutes!
[.fr], [.en], [.es] et [.nl] affichent la documentation en une de ces quatres langues.
[version] fournit les diverses étapes de l'écriture de l'application, le todo et les bugs connus.

Cycle primaire

'C1: 000px' est la longueur du cycle primaire, il est déduit de la longueur des cycles secondaire et tertiaire, la somme des trois cycles valant 250px
'C2: 000px' (seulement en mode «Rafale») est la longueur du cycle primaire pour une seconde courbe.
'Trigo' rappelle que le premier cycle court toujours dans le sens trigonométrique.
'+000°' permet de réorienter la courbe (de 0 à 360°).
*Cycles secondaire et tertiaire
'C1: 000px' affiche la longueur du rayon du cycle secondaire ou tertiaire (de 0 à 120px), modifiable par l'ascenseur horizontal situé à droite.
'C2: 000px' (seulement en mode «Rafale») idem pour une deuxième courbe.
'000sp' afffiche le nombre de spires du cycle secondaire ou tertiaire, modifiable par l'ascenseur à droite (de 0 à 100).
[Trigo] définit le sens du cycle secondaire ou tertiaire: noir sur fond blanc pour le sens trigonométrique, noir sur fond gris pour le sens horaire.
'+000°' permet de déphaser les cycles secondaire ou tertiaire (de 0 à 360°).

Généralités

[ ] appelle la boîte de sélection des couleurs pour définir la couleur de fond de l'image.
[1] appelle la boîte de sélection des couleurs pour définir la couleur de la première courbe.
[<>] (en mode «rafale» seulement) permet d'intervertir les couleurs de la première et seconde courbe.
[2] (en mode «rafale» seulement) appelle la boîte de sélection des couleurs pour définir la couleur de la seconde courbe.
[g] définit l'épaisseur de la courbe: noir sur fond blanc pour deux pixels, noir sur fond gris pour un simple pixel.
'd: 4 ^' permet de définir la densité de la courbe, de 1 à 16 milliers de points pour la révolution complète d'une courbe (4 milliers par défaut).
*Répétitions
'x 1 ^' permet de répéter le graphique: pour n répétitions, la courbe est répétée tous les (360/n)°.
[Rafale] permet de passer en mode «rafale», à savoir plusieurs courbes de la première à la seconde (comprise), définies selon les rayons '1' et '2' et les couleurs associées. Les courbes intermédiaires sont colorées selon le gradient de couleur.
'05' (mode «rafale» seulement) est le nombre de courbes (de 2 à 60) définissable par l'ascenseur à droite.

Action

[Nouveau] efface et dessine un graphique complet selon les paramètres définis.
[Ajout] dessine un graphique au dessus d'un autre existant déjà. Attention: dans ce cas, une nouvelle couleur de fond ne sera pas prise en compte.
[Hasard] dessine un graphique selon des paramètres redéfinis au hasard.

"""

Automatic Mondrian

J'ai toujours pensé que Piet Mondrian (1872-1944) utilisait un ordinateur. La preuve en 175 lignes...

I guess Mondrian (1872-1944) used a computer: as a 175-lined clue...

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
 #! /usr/bin/python -Qnew
# -*- coding: utf-8 -*-
import random, time, os
 
# Automatic Mondrian (Pieter Cornelis "Piet" Mondriaan, 1872-1944)
# v 1.1- 2014, 30 september - GPL 2 by Jean-Christophe BEUMIER
 
# How does it work?
# 1. Creating an image with a light gray background and drawing a frame
# 2. (several times) if (random) x,y is gray and not too close to a line:
#       dividing field (random) by horizontal or vertical line
# 3. if (random) x,y is gray: colouring the field
 
# Rough & dirty written! Known bugs and weaknesses:
# 1. a colour (light gray, red, yellow or blue) can be missing
#    -> if you cannot stand it, delete the file and try another picture
# 2. if your system doesn't have imagemagick, PNM format is heavy; for this
#    kind of picture: 720Ko PNM = about 5Ko GIF = about 1Ko PNG '5' 
#    -> convert it through a picture processor application 
 
# ver 1.1 improvement: lines couldn't cross: processing by dividing fields
#    -> I add an exception, completing the line, by default three times
 
 
# picture dimensions (px) - any size you like, not too little:
width=600
height=400
thick=8 # line width
gray=chr(216) # default colour: very light gray
dark=chr(32) # line: very dark gray
cross=3 # possibility of crossing lines
 
tab=[gray]*width*height*3 # nbr of pixel (RVB: 3 bytes per colour)
nbr=20 # max number of division
clr=[[chr(255),chr(30),chr(30)],[chr(255),chr(255),chr(64)],[chr(0),chr(100),chr(255)]] # red RVB / yellow RVB / blue RVB : Mondrian colours
 
header="P6 %s %s 255\n" %(width, height) # PNM file colour/raw data
 
# framing
for j in range(0,width):
  for i in range(0,thick):
    point=width*3*i+j*3
    tab[(point)]=dark
    tab[point+1]=dark
    tab[point+2]=dark
  for i in range(height-thick,height):
    point=width*3*i+j*3
    tab[point]=dark
    tab[point+1]=dark
    tab[point+2]=dark
for j in range(0,height):
  for i in range(0,thick):
    point=width*3*j+i*3
    tab[(point)]=dark
    tab[point+1]=dark
    tab[point+2]=dark
  for i in range(width-thick,width):
    point=width*3*j+i*3
    tab[point]=dark
    tab[point+1]=dark
    tab[point+2]=dark
 
# drawing
for r in range(nbr): # attempts 'r' times
  # random inner point
  x=thick+random.randrange(width-thick*3)
  y=thick+random.randrange(height-thick*3)
 
  flag1=1
  for i in range(-thick,thick*2):
    if tab[(width*y+x+i)*3]!=gray:
      flag1=0 # vertically too close
  flag0=1
  for j in range(-thick,thick*2):
    if tab[(width*(y+j)+x)*3]!=gray:
      flag0=0 # horizontally too close
 
  thru=False # ver 1.1 improving
  if r<cross: thru=True # possibility of lines through others
 
  hasard=random.randrange(2) # vertical (1) or horizontal (0) line
  if hasard==1 and flag1: # vertical ligne, not too close
    prog=0
    if thru: # ver 1.1 improving
      for k in range(0+thick,height-thick):
        for i in range(thick):
          tab[(k*width+x+i)*3]=dark
          tab[(k*width+x+i)*3+1]=dark
          tab[(k*width+x+i)*3+2]=dark
    else:
      while tab[((y-prog-1)*width+x)*3]==gray:
        for i in range(thick):
          tab[((y-prog-1)*width+x+i)*3]=dark
          tab[((y-prog-1)*width+x+i)*3+1]=dark
          tab[((y-prog-1)*width+x+i)*3+2]=dark
        prog+=1
      prog=0
      while tab[((y+prog)*width+x)*3]==gray:
        for i in range(thick):
          tab[((y+prog)*width+x+i)*3]=dark
          tab[((y+prog)*width+x+i)*3+1]=dark
          tab[((y+prog)*width+x+i)*3+2]=dark
        prog+=1
 
  if hasard==0 and flag0: # horizontal ligne, not too close
    if thru: # ver 1.1 improving
      for k in range(0+thick,width-thick):
        for i in range(thick):
          tab[((y+i)*width+k)*3]=dark
          tab[((y+i)*width+k)*3+1]=dark
          tab[((y+i)*width+k)*3+2]=dark
    else:
      prog=0
      while tab[(width*y+x-prog-1)*3]==gray:
        for i in range(thick):
          tab[(width*(y+i)+x-prog-1)*3]=dark
          tab[(width*(y+i)+x-prog-1)*3+1]=dark
          tab[(width*(y+i)+x-prog-1)*3+2]=dark
        prog+=1
      prog=0
      while tab[(width*y+x+prog)*3]==gray:
        for i in range(thick):
          tab[(width*(y+i)+x+prog)*3]=dark
          tab[(width*(y+i)+x+prog)*3+1]=dark
          tab[(width*(y+i)+x+prog)*3+2]=dark
        prog+=1
 
# colouring
for r in range(nbr): # attempts 'r' times
  x=random.randrange(width)
  y=random.randrange(height)
  if tab[(width*y+x)*3]==gray: # but works only on gray parts of picture
    prog=0
    while tab[(width*y+x+prog-1)*3]==gray:
      prog-=1
    left=x+prog # determining left abscissa of rectangle
    prog=0
    while tab[(width*y+x+prog+1)*3]==gray:
      prog+=1
    right=x+prog # determining right abscissa of rectangle
    prog=0
    while tab[(width*(y+prog-1)+x)*3]==gray:
      prog-=1
    up=y+prog # determining top ordinate of rectangle
    prog=0
    while tab[(width*(y+prog+1)+x)*3]==gray:
      prog+=1 # determining bottom ordinate of rectangle
    down=y+prog
 
    teinte=clr[random.randrange(3)] # random colour of rectangle
    for i in range(left,right+1): # filling rectangle
      for j in range(up,down+1):
       tab[(i+width*j)*3]=teinte[0]
       tab[(i+width*j)*3+1]=teinte[1]
       tab[(i+width*j)*3+2]=teinte[2]
 
image=header+"".join(tab) # header + joining data from list
temps=time.time() # number of second since 1970.01.01 0h00:00
name="mondrian"+str(temps)
 
han=open(name+".pnm","w") # saving picture
han.write(image)
han.close()
 
try:
  # only with imagemagick on your system:
  os.system("convert "+name+".pnm "+name+".png")
  os.remove(name+".pnm") 
except: # I didn't check: imagemagick is on my system
  print """
imagemagick is not on your system
PNM file P6 colour & raw data: rather heavy file
"""

Je ne sais pas ce que vous en pensez... Do you know what?...

 

Mais je trouve que celles-ci sont bien mieux... I find these are much better...

 

...que celles de Mondrian!  ...than Mondrian's one!

 

Cette dernière avec la version 1.1: deux ou trois lignes peuvent se croiser!

This one with ver1.1 improvement:some crossing lines are permitted!

 

Le format image PNM + PAM / PNM + PAM easy graphic format

  Pour cette info en français, voir www.jchr.be/python/pnm-pam.htm

PNM (Portable aNy Map) is a graphic file format by Jef Poskanzer (b. 1958) in the eighties.

Such graphic files can have more specific extensions:

  • .pbm (Portable BitMap) for black/white graphics files
  • .pgm (Portable GrayMap) for grays graphics files (it can be more than 50)
  • .ppm (Portable PixMap) for coloured graphic files

It's no compressed format, and even worse (a single pixel can be encoded '243 222 123 '!), but very easy to create. A PNM begins with a tag ('P1' to 'P6'), a width, a height and (for gray files and coloured maps) a hightest value; after comes the data.

The P1, P2 and P3 data are ascii-coded and space-separated. A comment is possible between an # and an end-of-line before the dimensions; the P4, P5 and P6 data are binary-coded, with no separation.

P1: black&white ascii-coded image

A PNM Black/White file begins with 'P1 width height ' (width and height are pixel values), followed by '0' (white) or '1' (black), and - if you want - a space between each pixel.

P1 6 4
1 1 1 1 1 1
1 0 0 0 0 1
1 0 0 0 0 1
1 1 1 1 1 1
"P1 6 4  111111100001100001111111 " is an equivalent (a last dummy pixels seems to be necessary).

Note: this graphic is a 6x4 pixels images, you'll have to zoom it.

A 1000x1000 pixels will be 1 or 2MB large, but it's possible to shrink it by 8 (each pixel is a bit) with the P4 binary format (see below).

P2: gray ascii-coded image

These files begins with 'P2' tag, a width and a height, followed by the highest value (until 255). The data are also ascii-typed and must have space-separations. In the following sample the values go from 0 (black) to 6 (white)

P2 4 4 6
6 5 4 3
5 4 3 2
4 3 2 1
3 2 1 0
"P2 4 4 6  6 5 4 3 5 4 3 2 4 3 2 1 3 2 1 0 " is an equivalent.

P3: coloured ascii-coded image

A coloured graphic ASCII begins with a 'P3' tag, follow by a width, a height and a maximal value. The datas are a sequence of three values which are the red, green and blue values:

P3 3 3 255
0   0   0    255 255 255    0 0    0
255 255 0    255 0   255    0 255 255
255 0   0     0   255 0       0 0   255

The number of spaces betwen each value doesn't have any importance. Red, green and blue are only coded with 0 or 255: in this example, it's possible to code in an easier way, setting the maximal value to 1 (before the '#'):

P3 # header (comment between '#' and carriage-return)
3 3 1
0 0 0  1 1 1  0 0 0
1 1 0  1 0 1  0 1 1
1 0 0  0 1 0  0 0 1
"P3 3 3 1   0 0 0 1 1 1 0 0 0  1 1 0 1 0 1 0 1 1   1 0 0 0 1 0 0 0 1 " is an equivalent

Note: you'll have to zoom this image to see these nine pixels!

P4, P5 et P6: binary formats

P4, P5 et P6 tags in the beginning of a PNM file are respectivily for black/white, gray scaled and coloured graphics where values are binary coded:

P4: black & white binary-coded:

P4 16 16
...byte-coded data

...without space nor carriage-return ('\n','\r') 

For a P4-PNM file, the first eight pixels must be translated into a value between 0 ('00000000') and 255 ('11111111').

For instance, WBBWWBBW is encoded through the binary number '01100110' = 102, (the 'f' character).

You can translate the binary number with int(number,2), and transform it into a character with char():

char(int("01100110",2)) 

The file will be:

"P4 8 4
ffff"

Some values cannot be written with ASCII-character. You can use chr(int('001100110',2) in a routine.

The best should be adding a line in your script with a command which transforms a PNM-file into PNG-one with os.system("convert image.pnm image.png") from the ImageMagick package (Unix only?).

P5 gray binary-coded image: each pixels is coded by a byte.

P6 colour binary-coded image: each pixel is coded by three bytes (red/green/blue)

NEW! (2016.05.29)

P7: Portable Arbitrary Map (PAM)

P4, P5 or P6 images can be written in a P7 new format, adding transparency or a 2 byte colour definition (256->65536 values) if wanted. ImageMagic can read and convert a PAM image (easy to generate) into PNG (universal format with transparency). If ImageMagic is installed on a UNIX system, you convert it with an easy command:

convert votreimage.pam votreimage.png

The header is a little longer, more versatile and more precise:

P7
# first comments after P7
WIDTH 443
HEIGHT 87
DEPTH 4
MAXVAL 255
TUPLTYPE RGB_ALPHA
# the last comment before ENDHDR
ENDHDR
...binary data byte, from 0 to 255...

  • Each parameter must be on a single line, between P7 and ENDHDR
  • DEPTH is the number of bytes per pixel: 1 for gray or B/W, 3 for colour, 1 more for transparency
  • MAXVAL can be up to 65535; if more than 255, DEPTH must be 2, 6 or 4, 8 if transparency - each canal is written with 2 bytes
  • TUPLTYPE is the image type: BLACKANDWHITE, GRAYSCALE or RGB, you'll have to add _ALPHA for transparency (0 is completely transparent, MAXVAL is completely coloured)
  • Parameters definition ends with ENDHDR and a linefeed
  • data definition of colour pixels is RVBA or RRVVBBAA

 

 

How to generate a P1-file

This script generates a black circle on a white background (you give the radius). It tests the pixels one by one: are they at the good distance from the center (x°,y°)? Pythagore answers with r²=(x-x°)²+(y-y°)². A file 'circle'+diameter+'.pnm' is created.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#! /usr/bin/python -Qnew 
 
import os
 
r=input("radius: ") # asking for a radius
d=r*2+1 # image width and height 
diam=str(d) # string  for header
fichier="P1 %s %s " %(diam,diam) # header 
 
for i in range(d): # rough way to produce a circle
  for j in range(d): 
    if round((abs((i-r)**2)+abs((j-r)**2))**.5)==r: 
      fichier+="1" 
    else: 
      fichier+="0" 
  fichier+="\n" # a last dummy pixel seems to be necessary 
 
handle=open("circle"+diam+".pnm","w") 
handle.write(fichier) 
handle.close() 
 
 
try:
   os.system("convert rond"+diam+".pnm rond"+diam+".png")
except:
   print "Sorry! no ImageMagick package found!"

Cycles sur trois niveaux / Three level cycles

Voici la suite de la page spirographe, à laquelle un niveau a été ajouté. Mon avatar a été réalisé avec cette application. Comme je suis paresseux, le paramétrage est déterminé par une fonction random.

En python 2, il faut préciser -Qnew pour la division 'réelle; 'print' n'est pas encore la fonction print() 

Here comes a tail for spirographe: a third level is added. My avatar comes from this script. As I'm rather lazy, the params are randomly produced, but comments are few by few translated.

Python 2 requires '-Qnew' for 'real' division, and 'print' is a statement, not yet the 'print()' python3 function

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
#! /usr/bin/python -Qnew
# -*- coding: utf-8 -*-
import os,time,math,random
 
t0=time.time()
print "\n Initialisation"
 
# radius length (px) for cycles k1, k2, k3 
k1=100+random.randrange(100)
k2=50+random.randrange(50)
k3=30+random.randrange(30)
 
# image dimension 
centre=k1+k2+k3+5
cote=centre*2
 
# multiplicity of secondary and tertiary cycles
 
r2=random.randrange(10)+3
r3=random.randrange(14)+6
 
 
# clockwise secondary cycle if s2==-1
s2=random.randrange(2)*2-1
if s2==1:
  ss2="p";
else:
  ss2="m"
 
# clockwise tertiary cycle if s3==-1
s3=random.randrange(2)*2-1 # 1 ou -1 
if s3==1:
  ss3="p";
else:
  ss3="m"
 
nom="spiro-%d-%d%s%d-%d%s%d" %(k1,k2,ss2,r2,k3,ss3,r3) # filename with params 
entete="P1 %s %s " %(cote,cote) # header for an ascii-coded black and white PNM file
 
 
matrice=['0']*cote*cote # white pixels matrix
 
t1=time.time()
print "  ",t1-t0,"\n\n Matrix filling",nom+".pnm"
 
for i in range(8000):
  angle=i*math.pi/4000
  x=int(round(centre+math.cos(angle)*k1+math.cos(angle*r2)*k2+math.cos(angle*r3)*k3))
  y=int(round(centre+math.sin(angle)*k1+math.sin(angle*r2)*k2*s2+math.sin(angle*r3)*k3*s3))
  matrice[y*cote+x]="1"        # black pixel 
  matrice[y*cote+x+1]="1"      # right pixel 
  matrice[y*cote+cote+x]="1"   # bottom pixel (a line down) 
  matrice[y*cote+cote+x+1]="1" # bottom-right pixel 
 
fichier=entete+"".join(matrice)
 
han=open(nom+".pnm","w")
han.write(fichier)
han.close()
 
t2=time.time()
print "  ",t2-t1,"\n\n File creation",nom+".trace.pnm"
 
for i in range(1000): # dotted for primary and secondary cycles
  angle=i*math.pi/500
  x=int(round(centre+math.cos(angle)*k1+math.cos(angle*r2)*k2))
  y=int(round(centre+math.sin(angle)*k1+math.sin(angle*r2)*k2*s2))
  matrice[y*cote+x]="1"      # setting black pixel 
 
fichier=entete+"".join(matrice)
 
han=open(nom+".trace.pnm","w")
han.write(fichier)
han.close()
  
t3=time.time()
print "  ",t3-t2,"\n\n  ",t3-t0,"pour le temps global"
 
print
 
# 'eom' must be changed by into your favorite image-viewer 
os.system("eom "+nom+".pnm &")
 
q=raw_input(" Conserver cette image (O/N): ")
if q=="N" or q=="n":
  os.system("rm "+nom+".pnm") # rm delete a file (UNIX) 
  os.system("rm "+nom+".trace.pnm")
  print "   Not saved image\n"
else:
  print "   Saved image\n"

On a common laptop (Celeron 2core 1,8GHz on GNU/Linux Debian Wheezy), less than .2sec:

  • primary cycle: 140 pixels, counterclockwise
  • secondary cycle: 69 pixels, 4 coils clockwise
  • cycle tertiaire: 33pixels, 16 coils, counterclockwise

...with the dotted primary+secondary cycle:

 

  Some more images

 

 

 

  Funny, isn't it?

 

 

 

Spirographe

Il ne s'agira pas vraiment de la simulation d'un spirographe, qui utilise des hypotrochoïdes (Wikipedia dixit). Deux cycles sont composés: un point tourne autour d'un centre qui tourne lui-même, de façon plus lente, autour d'un point fixe comme la lune tourne autour de la terre, qui tourne autour du soleil.

Attention: j'utilise encore python 2.x, qui doit se lancer avec -Qnew pour disposer de la division 'réelle'. 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#! /usr/bin/python -Qnew
# -*- coding: utf-8 -*-
import math
 
gr=150 # grand rayon
pr=50  # petit rayon
 
# rapport du cycle secondaire. Attention:
# si signe==1, le nombre de spires= n-1
# si signe==-1, le nombre de spires= n+1 
rapport=7
signe=1; s="p"
 
# decommenter la ligne suivante pour inverser le sens de la courbe secondaire
#signe=-1; s="m"
 
centre=gr+pr+10 # eloignement maximal du centre + marge de 10 pixels
cote=centre*2  # image side 
 
matrice=['0']*cote*cote # pixels matrix 
 
for i in range(4000): # courbe resultant de la revolution de cercles autour d'un cercle 
  angle=i*math.pi/2000 # le cercle fait 2PI, chaque pas 2PI/10000, donc PI/5000
  x=int(round(centre+math.cos(angle)*gr+math.cos(angle*rapport)*pr))
  y=int(round(centre+math.sin(angle)*gr+math.sin(angle*rapport)*pr*signe))
  matrice[y*cote+x]="1" # chaque pixel '1' est noir
 
nom="spiro-%d-%d%s%d" %(gr,pr,s,rapport)
 
entete="P1 %s %s " %(cote,cote) # entete de fichier PNM noir/blanc au format ASCII
fichier=entete+"".join(matrice) # transforme la liste ['0','0','1','0'...] en cha&icirc;ne '0010...'
 
han=open(nom+".pnm","w")
han.write(fichier)
han.close()
 
# Compl&acute;etion de l'image avec le cercle de base en pointill&acute;e
 
for i in range(200): # tour trigonometrique plus rapide
  angle=i*math.pi/100
  x=int(round(centre+math.cos(angle)*gr))
  y=int(round(centre+math.sin(angle)*gr))
  matrice[y*cote+x]="1"
 
fichier=entete+"".join(matrice)
 
han=open(nom+".trace.pnm","w")
han.write(fichier)
han.close()

 

Petit paradoxe:alors que le rapport entre le cycle secondaire est de 7 par rapport au cycle central, on obtient seulement six spires. C'est parce qu'il faut décompter le tour du cycle central sur lui-même.

En décommentant la ligne 15, l'orientation des spires est inversée. Et ici, le nombre de spires est supérieur au rapport 7.

  Note: j'ai placé l'image contenant le tracé en pointillé du cycle central. Une suite est prévue!!!

taquin

Menu

Voici un taquin 4x4 en console: quinze cases, et une case vide que l'on déplace avec les touches fléchées. En linux, le module curses est utilisé, il faut trouver un équivalent pour Windows.

copie écran d'une console avec taquin.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
<code>
#! /usr/bin/python
# -*- coding: latin-1 -*-
 
# www.jchr.be - 2007.01.27 - GPL2
 
# Rappel: sous Windows, il faut telecharger le module WCurses: voir www.jchr.be/python/modules.htm#curses
 
from time import time
from random import randrange
import curses
 
# cette premiere fonction dessine un tableau regulier (apres initialisation d'une session curses)
# parametres: offset ligne/colonne, nombre de rangees/colonnes, hauteur de rangee, largeur de colonne
def tableau(y,x,nrang,ncol,hrang,lcol):
  ymax=hrang*nrang+1; xmax=lcol*ncol+1
  for j in range(0,ymax):
    for i in range(0,xmax):
      if j%hrang!=0 and i%lcol==0: fenetre.addch(y+j,x+i,curses.ACS_VLINE); continue # lignes
      if j%hrang==0 and i%lcol!=0: fenetre.addch(y+j,x+i,curses.ACS_HLINE); continue
      if j%hrang==0 and i%lcol==0: fenetre.addch(y+j,x+i,curses.ACS_PLUS) # croisements
      if j==0 and i%lcol==0: fenetre.addch(y+j,x+i,curses.ACS_TTEE)       # remplacement de certains croisements par les bords
      if j==ymax-1 and i%lcol==0: fenetre.addch(y+j,x+i,curses.ACS_BTEE)
      if j%hrang==0 and i==0: fenetre.addch(y+j,x+i,curses.ACS_LTEE)
      if j%hrang==0 and i==xmax-1: fenetre.addch(y+j,x+i,curses.ACS_RTEE)
      if j==0 and i==0: fenetre.addch(y+j,x+i,curses.ACS_ULCORNER)        # remplacement de certains bords par les coins
      if j==0 and i==xmax-1: fenetre.addch(y+j,x+i,curses.ACS_URCORNER)
      if j==ymax-1 and i==0: fenetre.addch(y+j,x+i,curses.ACS_LLCORNER)
      if j==ymax-1 and i==xmax-1: fenetre.addch(y+j,x+i,curses.ACS_LRCORNER)
  fenetre.refresh()
 
# permute la case vide avec une case numerotee adjacente
def permute(lieu1,lieu2):
  fenetre.move(2+lieu1//4*2,3+lieu1%4*4)
  if k[lieu1]>0: fenetre.addstr(str(k[lieu1]).rjust(2))
  else: fenetre.addstr('  ')
  fenetre.move(2+lieu2//4*2,3+lieu2%4*4)
  if k[lieu2]>0: fenetre.addstr(str(k[lieu2]).rjust(2))
  else: fenetre.addstr('  ')
  fenetre.refresh()
 
def gauche():
  global zero, cpt
  if (zero%4>0):
    k[zero],k[zero-1]=k[zero-1],k[zero]
    permute(zero,zero-1)
    zero-=1; cpt+=1
 
def droite():
  global zero, cpt
  if (zero%4<3):
    k[zero],k[zero+1]=k[zero+1],k[zero]
    permute(zero,zero+1)
    zero+=1; cpt+=1
 
def bas():
  global zero, cpt
  if (zero>3):
    k[zero],k[zero-4]=k[zero-4],k[zero]
    permute(zero,zero-4)
    zero-=4; cpt+=1
 
def haut():
  global zero, cpt
  if (zero<12):
    k[zero],k[zero+4]=k[zero+4],k[zero]
    permute(zero,zero+4)
    zero+=4; cpt+=1
 
def initial(): # (re)initialisation du jeu (melange du taquin)
  global k, zero, ordre, sec, cpt
  ordre=range(1,16)
  ordre+=[0]; zero=15
  k=ordre[:]
  i=0; anc=0
  # le melange se fait en glissant les pieces au hasard cela ne peut se faire
  # par random.shuffle: un taquin sur deux seulement serait soluble
  while i <1000:
    anc=(anc+2)%4
    r=randrange(0,4)
    if (r==0) and r!=anc: haut(); anc=r; i+=1
    if (r==1) and r!=anc: bas(); anc=r; i+=1
    if (r==2) and r!=anc: gauche(); anc=r; i+=1
    if (r==3) and r!=anc: droite(); anc=r; i+=1
  cpt=0
  for i in range(16):
    if (k[i]==0):
      zero=i
  fenetre.addstr(7,25,' '*20) # efface le score
  fenetre.addstr(8,25,' '*20)
 
  sec=time()
 
# ****** Initialisation de l'application
sec=0.; zero=15; cpt=0; fin=0
 
# Initialisation de la session 'curses' (a ne faire qu'une fois)
ecran= curses.initscr()
fenetre= curses.newwin(15,50,0,0)
fenetre.keypad(1)
curses.curs_set(0)
curses.cbreak()
curses.noecho()
tableau(1,2,4,4,2,4) # dessin du tableau
tableau(0,0,1,1,10,20)
fenetre.addstr(1,25,'Taquin -- www.jchr.be')
fenetre.addstr(2,25,'2007.01.27 -- GPL2')
fenetre.addstr(4,27,'Quitter avec [q]')
fenetre.addstr(5,27,'Melanger avec [Esc]')
fenetre.refresh()
 
initial()
while (fin==0):
  if (ordre==k): # si la liste-taquin est en ordre
    tps=divmod(time()-sec,60);
    fenetre.addstr(7,25,'Resolu en '+str(int(tps[0]))+':'+str(int(tps[1])).zfill(2)+' et')
    fenetre.addstr(8,25,str(cpt)+' deplacements  ')
    fenetre.refresh()
    key=fenetre.getch()
    if key==113 or key==81: break # touche [q] ou [Q]
    initial()
  key=fenetre.getch()
  if key==curses.KEY_LEFT: gauche(); continue
  if key==curses.KEY_RIGHT: droite(); continue
  if key==curses.KEY_DOWN: haut(); continue
  if key==curses.KEY_UP: bas(); continue
  if key==27: initial()
  if key==113 or key==81: break
 
# le break permet de terminer la session 'curses'
fenetre.keypad(0)
curses.echo()
curses.curs_set(1)
curses.nocbreak()
curses.endwin()</code>