: .r u.r ;
: position ( row -- ) cr 33 swap 2 * - spaces ;
: pas ( 0 ... 0 -- 0 ... 0 ) 0 >r begin
over + >r dup 0= until
begin r> dup while dup 4 .r repeat ;
: pass ( -- ) 0 1 0 18 0 ?do dup position >r pas r> 1+ loop drop ;
: pax ( 0 ... 0 -- ) drop begin 0= until ;
: pascal ( -- ) pass pax ;
pascal
cr
The same mod2: : .r u.r ;
: position ( row -- ) cr 33 swap 2 * - spaces ;
: pas ( 0 ... 0 -- 0 ... 0 ) 0 >r begin
over + >r dup 0= until
begin r> dup while dup 2 mod 4 .r repeat ;
: pass ( -- ) 0 1 0 18 0 ?do dup position >r pas r> 1+ loop drop ;
: pax ( 0 ... 0 -- ) drop begin 0= until ;
: pascal ( -- ) pass pax ;
pascal
cr
A Forth for people in a hurry: git clone https://github.com/howerj/subleq
cd subleq
sed -i 's,0 constant opt.control,1 constant opt.control,g' subleq.fth
gmake subleq
./subleq subleq.dec < subleq.fth > new.dec
./subleq new.dec < pas.f
1
1 1
1 0 1
1 1 1 1
1 0 0 0 1
1 1 0 0 1 1
1 0 1 0 1 0 1
1 1 1 1 1 1 1 1
1 0 0 0 0 0 0 0 1
1 1 0 0 0 0 0 0 1 1
1 0 1 0 0 0 0 0 1 0 1
1 1 1 1 0 0 0 0 1 1 1 1
1 0 0 0 1 0 0 0 1 0 0 0 1
1 1 0 0 1 1 0 0 1 1 0 0 1 1
1 0 1 0 1 0 1 0 1 0 1 0 1 0 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 ok
By changing `4 .r` to `bl + dup dup dup emit emit emit emit` I get this: !!!!
!!!!!!!!
!!!! !!!!
!!!!!!!!!!!!!!!!
!!!! !!!!
!!!!!!!! !!!!!!!!
!!!! !!!! !!!! !!!!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!! !!!!
!!!!!!!! !!!!!!!!
!!!! !!!! !!!! !!!!
!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!
!!!! !!!! !!!! !!!!
!!!!!!!! !!!!!!!! !!!!!!!! !!!!!!!!
!!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!! !!!!
!!!!!!!! !!!!!!!! ok
But this is not using bitwise AND, just the Pascal's triangle approach. (Interestingly, you can reformulate that as a neighborhood-2 2-state 1-dimensional cellular automaton pretty easily; it occurs in a couple of different guises in Wolfram's catalog.)Here's an ASCII-art version that uses AND as Michał describes:
32 value size : line cr size 0 do dup i and if bl else [char] # then dup emit emit loop drop ;
: pasand size 0 do i line loop ;
Running `pasand` then yields this: ################################################################
## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ##
#### #### #### #### #### #### #### ####
## ## ## ## ## ## ## ##
######## ######## ######## ########
## ## ## ## ## ## ## ##
#### #### #### ####
## ## ## ##
################ ################
## ## ## ## ## ## ## ##
#### #### #### ####
## ## ## ##
######## ########
## ## ## ##
#### ####
## ##
################################
## ## ## ## ## ## ## ##
#### #### #### ####
## ## ## ##
######## ########
## ## ## ##
#### ####
## ##
################
## ## ## ##
#### ####
## ##
########
## ##
####
## ok
: sier cr 32 0 do 32 0 do i j and if ." " else ." * " then loop cr loop ;
sier
Output from eforth/subleq (with do...loop set in the config): * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* * * * * * * * * * * * * * * *
* * * * * * * * * * * * * * * *
* * * * * * * *
* * * * * * * * * * * * * * * *
* * * * * * * *
* * * * * * * *
* * * *
* * * * * * * * * * * * * * * *
* * * * * * * *
* * * * * * * *
* * * *
* * * * * * * *
* * * *
* * * *
* *
* * * * * * * * * * * * * * * *
* * * * * * * *
* * * * * * * *
* * * *
* * * * * * * *
* * * *
* * * *
* *
* * * * * * * *
* * * *
* * * *
* *
* * * *
* *
* *
*
ok
ok
"As everyone knows", you get a Sierpinski triangle by taking the entries in Pascal's triangle mod 2. That is, taking binomial coefficients mod 2.
Now, here's a cute theorem about binomial coefficients and prime numbers: for any prime p, the number of powers of p dividing (n choose r) equals the number of carries when you write r and n-r in base p and add them up.
For instance, (16 choose 8) is a multiple of 9 but not of 27. 8 in base 3 is 22; when you add 22+22 in base 3, you have carries out of the units and threes digits.
OK. So, now, suppose you look at (x+y choose x) mod 2. This will be 1 exactly when no 2s divide it; i.e., when no carries occur when adding x and y in binary; i.e., when x and y never have 1-bits in the same place; i.e., when x AND y (bitwise) is zero.
And that's exactly what OP found!
https://m.youtube.com/watch?v=tRaq4aYPzCc
Just kidding. This was a fun read.
I should probably update that page to explain how to use objdump correctly to disassemble MS-DOG .COM files.
If you like making fractal patterns with bitwise arithmetic, you'll probably love http://canonical.org/~kragen/sw/dev3/trama. Especially if you like stack machines too. The page is entirely in Spanish (except for an epilepsy safety warning) but I suspect that's unlikely to be a problem in practice.
The corresponding equivalent of functional programming would be Church bits in a functional quad-tree encoding \s.(s TL TR BL BR). Then, the Sierpinski triangle can be written as (Y \fs.(s f f f #f)), where #f is the Church bit \tf.f!
Rendering proof: https://lambda-screen.marvinborner.de/?term=ERoc0CrbYIA%3D
Bitwise XOR modulo T: https://susam.net/fxyt.html#XYxTN1srN255pTN1sqD
Bitwise AND modulo T: https://susam.net/fxyt.html#XYaTN1srN255pTN1sqN0
Bitwise OR modulo T: https://susam.net/fxyt.html#XYoTN1srN255pTN1sqDN0S
Where T is the time coordinate. Origin for X, Y coordinates is at the bottom left corner of the canvas.
You can pause the animation anytime by clicking the ‘■’ button and then step through the T coordinate using the ‘«’ and ‘»’ buttons.
PRBS sequences are well-known, well-used "pseudo-random" sequences that are, for example, used to (non-cryptographically!) scramble data links, or to just test them (Bit Error Rate).
I made my own PRBS generator, and was surprised that visualizing its output, it was full of Sierpinski triangles of various sizes.
Even fully knowing and honoring that they have no cryptographic properties, it didn't feel very "pseudo-random" to me.
cc -w -xc -std=c89 -<<<'main(c){int r;for(r=32;r;)printf(++c>31?c=!r--,"\n":c<r?" ":~c&r?" `":" #");}'&&./a.*
It used to be cooler back when compilers supported weird K&R style C by default. I got it under 100 characters back then, and the C part was just 73 characters. This version is a bit longer but works with modern clang. The 73-character K&R C version that you can still compile today with GCC is: main(c,r){for(r=32;r;)printf(++c>31?c=!r--,"\n":c<r?" ":~c&r?" `":" #");}
I tend to like lcamtuf's Electronics entries a bit better (I'm an EE after all) but I find he has a great way of explaining things.
— of course. In the same way the (standard) Cantor set consists of precisely those numbers from the interval [0,1] that can be represented using only 0 and 2 in their ternary expansion (repeated 2 is allowed, as in 1 = 0.2222...). If self-similar fractals can be conveniently represented in positional number systems, it is because the latter are self-similar.
jcul•5h ago
Apologies for a comment not related to the content, but it makes it difficult to read the article on mobile.
jcul•5h ago
IceDane•4h ago