Libraries for bc and dc.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

#### 389 lines 11 KiB Raw Permalink Blame History

 `#!/usr/local/bin/bc -l digits.bc` `### Digits-Misc.BC - Treat numbers as strings of digits II` ` ## Functions of interest but questionable worth` `# Workhorse function - use POSIX scope to check` `# . 'base' parameter of many functions here` `define base_check_misc_() {` ` if(bijective)print "Bijective mode not supported by this function.\n"` ` if(base<2){` ` if(base<=-2){` ` print "Negative bases not currently supported; "` ` } else if(base==-1||base==0||base==1) {` ` print "Nonsense base: ",base,"; "` ` }` ` print "Using ibase instead.\n"` ` base=ibase` ` }` `}` ` ` `# Product of each digit with one added, less 1` `# e.g. 235 -> (2+1)(3+1)(5+1)-1 = 3*4*6 - 1 = 71 in base ten` `define digit_product1(base,x) { ` ` auto os,t;` ` if(x<0)return digit_product1(base,-x);` ` os=scale;scale=0;base/=1;x/=1` ` .=base_check_misc_()` ` t=1;while(x){t*=1+(x%base);x/=base}` ` scale=os;return(t-1)` `}` `# Product of each digit's corresponding odd numbers through the relation` `# digit -> 2*digit + 1, then the result is passed through the inverse relation x -> (x-1)/2` `# e.g. 13462 -> ( (2*1+1)(2*3+1)(2*4+1)(2*6+1)(2*2+1)-1 )/2 = (3*7*9*13*5 - 1)/2 = 6142` `define digit_product2(base,x) { ` ` auto os,t;` ` if(x<0)return digit_product2(base,-x);` ` os=scale;scale=0;base/=1;x/=1` ` .=base_check_misc_()` ` t=1;while(x){t*=1+2*(x%base);x/=base}` ` t=(t-1)/2` ` scale=os;return(t)` `}` `## Swap digit pairs` `define sdp(base,x) {` ` auto os,b2,t,nx,dd,dl,dr,pw;` ` if(x<0)return sdp(base,-x)` ` .=base_check_misc_()` ` os=scale;scale=0;base/=1` ` b2=base*base` ` nx=x/1` ` if(scale(x)&&x!=nx){` ` pw=A^os;for(t=1;t<=pw;t*=b2){}` ` nx=(x*t)/1` ` scale=os;return sdp(base,nx)/t` ` }` ` x=nx;pw=1` ` for(t=0;x;x=nx){dd=x-(nx=x/b2)*b2;dr=dd-(dl=dd/base)*base;t+=pw*(dr*base+dl);pw*=b2;x=nx}` ` scale=os;return t` `}` `## Palindromes` `# Determine if x is a negapalindrome (type 1) in the given base` `# - an NP is any number whose opposing pairs of digits,` `# (counted in from either end) sum to one less than the base` `# e.g. 147258 is an NP(1) in base ten since 1+8 = 4+5 = 7+2 = 9 = ten - 1` `define is_negapalindrome(base,x) {` ` auto os` ` os=scale;scale=0;base/=1;x/=1` ` .=base_check_misc_()` ` # divisibility by base-1 is a necessary condition for [P]NP(1)s in even bases` ` # divisibility by (base-1)/2 is a necessary condition for [P]NP(1)s in odd bases` ` if(x%((base-1)/(1+base%2))!=0){scale=os;return 0}` ` if(x<0)x=-x` ` x += reverse(base,x)+1` ` if(x a single digit NP(1), which is invalid for even bases` ` r=base^digits(base,x)` ` x=x*r+reverse(base,r*base-1-x)/base` ` }` ` scale=os;return s*x` `}` `define unmap_negapalindrome(base, x) {` ` auto os,r,s` ` os=scale;scale=0` ` s=1;if(x<0)x*=(s=-1)` ` .=base_check_misc_()` ` if(base%2){` ` r=base^((digits(base,x)+1)/2)` ` x=x/r+r/base-1` ` } else {` ` r=base^(digits(base,x)/2)` ` x=x/r-1` ` }` ` scale=os;return s*x` `}` ` ## To do (one day): map_ functions for remaining NPs and PNPs` ` ` `## Calculator segments` `# Return the number of segments of a 7-segment calculator display that` `# are required to display the value of x in the given base.` `# Supports up to base 36; Some calculators may have a different number` `# of segments per number than given here.` `define calcsegments(base,x) {` ` auto os,oib,s[],t;` ` oib=ibase;ibase=A` ` s[ 0]=s[ 6]=s[ 9]=s[10]=s[32]=6` ` s[ 1]=s[27]=2` ` s[ 2]=s[ 3]=s[ 5]=s[11]=s[13]=s[14]=s[16]=s[25]=s[26]=s[31]=s[34]=5` ` s[ 4]=s[12]=s[15]=s[17]=s[20]=s[24]=s[28]=s[29]=s[35]=4` ` s[ 7]=s[19]=s[21]=s[22]=s[23]=s[30]=s[33]=3` ` s[ 8]=7` ` s[18]=1` ` ibase=oib` ` os=scale;scale=0;x/=1` ` t=0;if(x<0){t=1;x=-x}` ` if(x==0){scale=os;return s[0]}` ` if(2>base||base>6*6){` ` print "calcsegments: only bases 2 to 36 (decimal) supported\n";` ` base=A` ` }` ` while(x){t+=s[x%base];x/=base}` ` scale=os;return t` `}` `## Miscellaneous` `# The base number created by appending all base numbers` `# from 1 to x, e.g. in base ten: 1, 12, 123, ..., 123456789101112, etc.` `define append_all(base,x) {` ` auto a,i,m,l,os;` ` os=scale;scale=0;base/=1;x/=1` ` .=base_check_misc_()` ` if(x<=0)return(0);` ` m=1;while(x){l=m;m*=base;for(i=l;i0){.=d[x%base]++;x/=base}` ` for(i=base-1;i>=0;i--)if(d[i])for(j=0;j0){.=d[x%base]++;x/=base}` ` for(i=1;id){n=d}` ` s=1;if(-n>=m){s=-1;base=-n}else{base=m}` ` for(i=0;(d=d__[i])=0;i++)x=x*base+d` ` if(d__[i]!=s*base){print "join_digits: unexpected element in array\n";scale=os;return x/s}` ` scale=os+5;x+=5*A^(-1-os)` ` for(p=1/base;p&&(d=d__[++i])=0;p/=base)x+=d*p` ` if(d__[i]!=-1)print "join_digits: unexpected element in array\n";` ` scale=os;return x/s` `}` `## Pandigital Index` `# pdhi(x) - Pan Digital Halving Index` `# Returns how many times x must be divided by 2 before` `# the result contains all digits from 0 to 9 (if ibase = 10).` `# e.g. 3339 -> 1669.5 -> 834.75 -> 417.375 ->` `# 208.6875 -> 104.34375 -> 52.171875 ->` `# 26.0859375 -> 13.04296875, i.e. 8 times` `# Uses ibase as the base for divisions (usually 10)` `define pdhi(x) {` ` auto d[],xi,xf,c,r,pdhi,lim,i;` ` if(x==0){print "pdhi: Infinity\n";return A^scale-1}` ` if(x<0)x=-x` ` c=1;pdhi=-1;lim=int(A/ibase+3)*scale` ` while(c){` ` pdhi+=1` ` xi=int(x);xf=x-xi` ` while(xi){` ` r=int(xi/ibase)` ` d[xi-ibase*r]=1` ` xi=r` ` }` ` for(i=lim ; i && xf ; i--){` ` #while(xf){` ` xf*=ibase` ` r=int(xf)` ` d[r]=1` ` xf-=r` ` }` ` c=ibase` ` for(r=0;r 1669.5 -> 834.75 -> 417.375 ->` `# 208.6875 -> 104.34375 -> 52.171875 ->` `# 26.0859375 -> 13.04296875, i.e. 8 times` `# Uses ibase as the base for divisions (usually 10)` `define pdmi(x,m) {` ` auto d[],xi,xf,c,r,pdmi,lim,i;` ` if(x==0){print "pdmi: Infinity\n";return A^scale-1}` ` if(x<0)x=-x` ` c=1;pdmi=-1;lim=int(A/ibase+3)*scale` ` while(c){` ` pdmi+=1` ` xi=int(x);xf=x-xi` ` while(xi){` ` r=int(xi/ibase)` ` d[xi-ibase*r]=1` ` xi=r` ` }` ` for(i=lim ; i && xf ; i--){` ` #while(xf){` ` xf*=ibase` ` r=int(xf)` ` d[r]=1` ` xf-=r` ` }` ` c=ibase` ` for(r=0;r