dc (desk calculator) is a Unix command that performs arbitrary-precision calculations. It uses RPN (reverse polish notation), so the sum of 1 and 2 is expressed as 1 2 +. dc has just barely enough features to be Turing-complete, and is considered an esolang.
For whatever reason, I have tried to write some actual programmes in it over the years. Here they are.
Golden ratio
I tried to calculate the golden ratio with a binary search (which, it seems, is my go-to approach for calculating any mathematical constant). i used the mathematical function x/((1/x)+1), which approaches 1 as x approaches the golden ratio.
#!/bin/dc # gold.dc # 2023 # # Binary search for the golden ratio. 67k 60si # Iterator variable; num of iterations to do. 1sb # Test value to use. 0.5sd # Difference to move by; halved each iteration. [lb1lb/1+/]st # Function that tests value in b. Return is >1 if b>phi. [lbpld+sbltx1<?ld2/sdli1-dsi0!=l]sl # Main loop. [lbld-sb]s? # Conditional that un-does the incrementation by d. llxq
I then tried to implement a different method, using linear interpolation. My idea was to take 2 points on either side of the proper value, draw a straight line between them, and then go to the middle of that line. This idea didn't work very well, in fact it seems to be even worse:
#!/bin/dc # gold2.dc # 2023 # # More advanced search for the golden ratio. 67k 80si # Iterator variable; num of iterations to do. 1sa2sb # Upper and lower bounds. [l-1l-/1+/]st # Function that tests value in -. Return is >1 if value > phi. [ las-ltxsAlbs-ltxsB # now A = t(a) and B = t(b) 1lA/la*p # approximate n for which t(n) = 1 s-ltx # get t(n) d1>r1<R # Assume they are never equal, as that only happens at infinity. las-ltxsAlbs-ltxsB # now A = t(a) and B = t(b) 1lB/lb*p # approximate n for which t(n) = 1 s-ltx # get t(n) d1>r1<R # Assume they are never equal, as that only happens at infinity. li1-dsi0!=l]sl # Main loop. [l-sa]sr [l-sb]sR llxq
Conway's Game of Life
#!/usr/bin/dc 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 # width 8 # height sxsy lxly*ss # s=size 0[ds_:wl_1+dls>F]dsFxs0 # load cell values into array 'w' # transition table #B0 1 2 3 4 5 6 7 8 (births) 0 0 0 1 0 0 0 0 0 #S0 1 2 3 4 5 6 7 8 0 0 1 1 0 0 0 0 0 2 # amount of rows in trans. table 9*[1-ds_:tl_d0<F]dsFxs0 # PRINT ------------------------------------------------------------------------ [1-dds_lx%d0=R0!=Sd0<Q]sQ # print world main loop [l_;wps0]sR # print rightmost cell of row [l_;wn]sS # print other ones [lslQxs0]sP # print world # SIMULATE --------------------------------------------------------------------- [r[r]sFd0!>Fs0]sA # wrap around on -1 (top of stack=bound, below that=coord) [ly1-lAxly%lx*rlx1-lAxlx%+;w]sC # get cell (torus; top of stack=y, below that=x) [1-sv lxlVxs0 lvd0<U]sU # for y [1-sh # store x,y in h,v (horz., vert.) and get neighbours lh1-lv1-lCx lh lv1-lCx+ lh1+lv1-lCx+ lh1-lv lCx+ lh1+lv lCx+ lh1-lv1+lCx+ lh lv1+lCx+ lh1+lv1+lCx+ lhlvlCx # get center cell 9*+;t # look up new cell value in trans. table lvlx*lh+:n lhd0<V]sV # for x (h=x, v=y) [[1-dd;nr:wd0<F]sFlslFxs0]sW # flush new generation (n) into old (w) [lylUxs0lWx]sT # simulate tick # ------------------------------------------------------------------------------ [Press RET to simulate a generation. Type and enter 'q' to quit. ]P [?lTxlPxdx]dxq
Triangle fill
As Terry A. Davis said, "it's fucking algebra, nigger!"
Both this and life.dc were made in September 2020. The 6 numbers at the end specify the points of the triangle.
#!/usr/bin/dc
# REGISTERS ARE THE CRUTCH OF THE STACK-IMPAIRED MIND . . .
16 16 # width, height
# b=buffer
sxdsylx*dss # s=size
[1-d0r:bd0<F]dsFxs0 # init b
# RENDER -----------------------------------------------------------------------
[ 3k# returns (m=(ax-bx)/(ay-by)|c=(ax-m*ay))
dS_r-S- # -=ax-bx
dS_r-L-r/
dL_*L_r-
0k]sS # calculate slope and offset of line defined by 2 points (ax|bx|ay|by)
[r]sR
[2Q]sQ
[S_[dl_<Qd1r:b1+lFx]dsFxL_s0s0]sL # draw horizontal line (right|left)
[[ lilx*d # index to beg. of row
# c,m = offset,slope of left line; C,M = right line
lilm*lc+ .5+d1%- +r # calculate coord of left edge
lilM*lC+ .5+d1%- + # right edge
lLx # draw row
li1+dsil.>J
]sJsiS.lJxL.s0
]sG # Draw section of triangle from top to bot with lines cm,CM (top|bot)
[ 0k
s1s2 s3s4 s5s6 # 12=a, 34=b, 56=c (all are xy)
# cycle points until a is at the top
[l6l5l4l3l2l1s5s6s1s2s3s4 l2l4<F l2l6<F]dsFx
#TODO: make by this point invariant: ay<=by && ay<=cy
l2d1%-s^ # top y value
l4d1%-s- # mid y value
l6d1%-s_ # bot. y value
[l_l-s_s-]sFl_l->F # swap mid and bot if they're ordered wrong
[ l4l2l3l1lSxscsm # draw triangle from top to mid (if ay<mid)
l6l2l5l1lSxsCsM
l-l^lGx
]sH l-l2<H
[ l6l4l5l3lSxscsm # draw triangle from mid to bot (if by<cy)
l2l6l1l5lSxsCsM
l_l-lGx
]sH l6l4<H
[ l4l2l3l1lSxscsm # draw triangle from mid to bot (if cy<by)
l4l6l3l5lSxsCsM
l_l-lGx
]sH l4l6<H
]sT # draw triangle (ax|ay|bx|by|cx|cy)
# SHOW -------------------------------------------------------------------------
[ [[]pn]sG # print newline
0k # modulo works weird when precision is above 0
0[d;bn1+dlx%0=Gdls>F]dsFx
]sP # print buffer as plaintext
#........
#...b....
#........
#........
#.c......
#.......a
#........
#........
4 1 1 3 6 7
#5 7 4 1 1 3
#6 12 14 1 1 3
lTx
lPxq