pc(one liner Python Calculator)

ターミナルからPython一行コードを入力・実行

数値計算・代数計算にとってSymPyは強力な助っ人
Pythonを立ち上げることなく、ターミナルから簡単にPythonコードを一行で入力・実行できるようにするシェルスクリプト

【更新】

20230908
・インストールするファイルを1つだけにした
・モードを9つにした
・出力を7つにした
・カラー表示にした
・複数行コード入力メニュー[2c]Codeを追加

【動作確認環境】

【macOS12.6.5】
Python 3.11.4
Bash、zsh

【Ubuntu22.04.2LTS】
Python 3.11.1
Bash

【必須Pythonライブラリ】
SymPyライブラリ
mpmathライブラリ

【インストール】

HOMEにディレクトリmyscript/pcをつくる
HOME/myscript/pcに
py.sh
を配置

MacOS .zshrcに以下を追記

source $HOME/myscript/pc/pc.sh

ubuntu .bashrcに以下を追記

alias open=xdg-open
source $HOME/myscript/pc/pc.sh

【Menu】

[1ENTER]One-Liner [2c]Code [3f]Frac [4p]mpf [5r]Rump [6m]man [7h]history [8s]SymPyWeb [9q]Quit >
に対して1文字(ENTERなし)入力

[1][ENTER]One-Liner no change (** & ^ OK)
[2][c]Code TAB OK Enter ## to Stop inputting
[3][f]Frac Auto Change 2/3 -> Fraction(“2/3”).limit_denominator()
[4][p]mpf mp(multiple-precision) mpf Real float Auto Change 3.14 -> mpf(“3.14”)
[5][r]rump verification of Rumps example
[6][m]man This manual page
[7][h]history show code history open \$PCDIR/pclist.txt
[8][s]SymPyWeb show SymPy Web Site
[9][q]quit quit pc

【OUTPUT】

[1]pprint(eq,use_unicode=False)
[2]pprint(eq,use_unicode=True)
[3]pprint(eval(eq))
[4]print(eval(eq))
[5]N(eq, precision)
[6]latex(eval(eq))
[7]latex(N(eq,precision))

シェルスクリプト pc.sh

#!/usr/bin/env bash

# pc(one liner Python Calculator)
# Python with SymPy & Shell Scripts

version='20230908'

# 設置ディレクトリ
PCDIR=HOME/myscript/pc


# コマンド pce
# pc.sh 編集
function pce(){
openPCDIR/pc.sh
}


# コマンド pcl
# 入力履歴表示
function pcl(){
open PCDIR/pclist.txt
}

# コマンド pcd
# SymPy Doc Web表示
function pcd(){
open 'https://docs.sympy.org/latest/tutorials/intro-tutorial/features.html'
}


# コマンド help
function help(){
cat << EOF
********** General Commands Manual ***************
NAME
    pc - one liner Python Calculator

SYNTAX
    pc

VERSION
    This man page documents pc version{version}

DESCRIPTION
[Menu]
[1][ENTER]One-Liner  no change (** & ^ OK)
[2][c]Code  TAB OK Enter ## to Stop inputting
[3][f]Frac  Auto Change 2/3 -> Fraction("2/3").limit_denominator()
[4][p]mpf   mp(multiple-precision) mpf Real float  Auto Change 3.14 -> mpf("3.14")
[5][r]rump  verification of Rumps example
[6][m]man  This manual page
[7][h]history  show code history  open \PCDIR/pclist.txt
[8][s]SymPyWeb  show SymPy Web Site
[9][q]quit  quit pc

[OUTPUT] just Frac mpf
[1]pprint(eq,use_unicode=False)
[2]pprint(eq,use_unicode=True)
[3]pprint(eval(eq))
[4]print(eval(eq))
[5]N(eq, precision)
[6]latex(eval(eq))
[7]latex(N(eq,precision))

[OUTPUT] exec
[0]exec('eq')

[EXPRESSION] All SymPy Code OK
─────────────────────────┬─────────────────────────────────────────────────────
Math                     │ Python&SymPy Code
─────────────────────────┼─────────────────────────────────────────────────────
quotient                 │ //
─────────────────────────┼─────────────────────────────────────────────────────
remainder                │ %
─────────────────────────┼─────────────────────────────────────────────────────
quotient and remainder   │ divmod()
─────────────────────────┼─────────────────────────────────────────────────────
fraction                 │ 2/3 Frac(2,3) Frac("2/3")
─────────────────────────┼─────────────────────────────────────────────────────
square root              │ sqrt(2)  
─────────────────────────┼─────────────────────────────────────────────────────
Pi                       │ pi
─────────────────────────┼─────────────────────────────────────────────────────
Napier Constant          │ E
─────────────────────────┼─────────────────────────────────────────────────────
trigonometric function   │ sin(pi/3)
                         │ sin(60*pi/180)
─────────────────────────┼─────────────────────────────────────────────────────
exponential function     │ exp()
─────────────────────────┼─────────────────────────────────────────────────────
natural logarithm        │ log(E**2)
─────────────────────────┼─────────────────────────────────────────────────────
common logarithm         │ log(2,10)  log(x, base)
─────────────────────────┼─────────────────────────────────────────────────────
imaginary unit           │ (2+3j)*(5-7j)
─────────────────────────┼─────────────────────────────────────────────────────
imaginary unit(SymPy)    │ exp(cos(E**I)+sin(E*pi))
                         │ I**I
─────────────────────────┼─────────────────────────────────────────────────────
prime factorization      │ factorint(1000)
─────────────────────────┼─────────────────────────────────────────────────────
factorial                │ factorial(10)
─────────────────────────┼─────────────────────────────────────────────────────
algebra symbolic variable│ from a to z
algebra symbolic function│ only f
─────────────────────────┼─────────────────────────────────────────────────────
expand                   │ expand((x+y)**10)
─────────────────────────┼─────────────────────────────────────────────────────
factor                   │ factor(a**10-b**10)
─────────────────────────┼─────────────────────────────────────────────────────
simplification           │ simplify(1+x+x**2+x**3)
─────────────────────────┼─────────────────────────────────────────────────────
sequence                 │ sequence(k**2,(k,1,10))
                         │ sequence(k**2,(k,1,10))[9]
─────────────────────────┼─────────────────────────────────────────────────────
summation of a sequence  │ Sum(k**2,(k,1,n)).doit()
─────────────────────────┼─────────────────────────────────────────────────────
product of a sequence    │ product(k,(k,1,10))
─────────────────────────┼─────────────────────────────────────────────────────
equation                 │ solve(a*x**2+b*x+c,x)
                         │ solve(x**2-1,x)[0]
─────────────────────────┼─────────────────────────────────────────────────────
simultaneous equations   │ solve([2/3*x-y-1,3/7*x-2*y-5/9],[x,y])
─────────────────────────┼─────────────────────────────────────────────────────
simultaneous equations   │ solve([x+y-4,x-y-2],[x,y])
─────────────────────────┼─────────────────────────────────────────────────────
differential equation    │ variable function f
                         │ dsolve(Eq(f(t).diff(t, t) - f(t), exp(t)), f(t))
─────────────────────────┼─────────────────────────────────────────────────────
differential             │ diff(x**2,x)
─────────────────────────┼─────────────────────────────────────────────────────
indefinite integral      │ integrate(x**3,x)
─────────────────────────┼─────────────────────────────────────────────────────
definite integral        │ integrate(x**3,(x,0,1))
─────────────────────────┼─────────────────────────────────────────────────────
infinity                 │ oo                         │ integrate(1/(1+x**2), (x, -oo, oo))
─────────────────────────┼─────────────────────────────────────────────────────
limit                    │ limit(sin(x)/x, x, 0)
─────────────────────────┼─────────────────────────────────────────────────────
Taylor series            │ series(sin(x),x, 0, 12)
─────────────────────────┼─────────────────────────────────────────────────────
Taylor series            │ taylor(sin, 0, 5)
 coefficient list        │
─────────────────────────┼─────────────────────────────────────────────────────
substitution             │ (x - x**3/6 + x**5/120 - x**7/5040).subs(x, 1)
─────────────────────────┼─────────────────────────────────────────────────────
matrix                   │ Matrix([[1, 2], [2, 2]]).det()
─────────────────────────┼─────────────────────────────────────────────────────
matrix                   │ Matrix([[1, 2], [2, 2]]).eigenvals()
─────────────────────────┼─────────────────────────────────────────────────────
matrix                   │ Matrix([[1, 2], [2, 2]]).eigenvects()
─────────────────────────┼─────────────────────────────────────────────────────
Seki-Bernoulli number    │ bernoulli()
─────────────────────────┼─────────────────────────────────────────────────────
zeta function            │ zeta()
                         │ zetazero()
─────────────────────────┼─────────────────────────────────────────────────────
Boolean-valued check     │ 1+1 == 3                         │ expand((x+y)**2) == x**2+2*x*y+y**2
─────────────────────────┼─────────────────────────────────────────────────────
plotting graphs          │ plot(x**2, (x, -1, 2), ylabel = "y")
─────────────────────────┼─────────────────────────────────────────────────────
mpmath floating-point    │ (-2)**mpf("0.5")
─────────────────────────┴─────────────────────────────────────────────────────

********** General Commands Manual ***************

EOF
}


# コマンド pc
# 本体
function pc(){

echo -e "\033[92mpcversion\033[0m"
echo 'Copyright 2023 sakurAi Science Factory, Inc.'
echo 'This is free software with ABSOLUTELY NO WARRANTY.'


unset eq
unset N
mode=''

while :
do

while :
do
    echo -e '\033[36m[1ENTER]One-Liner [2c]Code [3f]Frac [4p]mpf [5r]Rump [6m]man [7h]history [8s]SymPyWeb [9q]Quit > \033[0m'
    stty raw -echo
    VAR=`dd bs=1 count=1 2>/dev/null`
    stty -raw echo
    case "VAR" in
    '')  mode="just" ; break ;;
    1 )  mode="just" ; break ;;
    2 )  mode="exec" ; break ;;
    c )  mode="exec" ; break ;;
    3 )  mode="frac" ; break ;;
    f )  mode="frac" ; break ;;
    4 )  mode="mpf" ; break ;;
    p )  mode="mpf" ; break ;;
    5 )  mode="rump" ; break ;;
    r )  mode="rump" ; break ;;
    6 )  help ; continue ;;
    m )  help ; continue ;;
    7 )  pcl ; continue ;;
    h )  pcl ; continue ;;
    8 )  pcd && continue ;;
    s )  pcd && continue ;;
    9 )  mode="quit" ; break ;;
    q )  mode="quit" ; break ;;
    * )  mode="just" ; break ;;
    esac
done

echo -n "">PCDIR/pceq.txt

[ "mode" = "just" ] && echo -e "\033[92m[1]eq(one liner code) >\033[0m" && read eqq && echoeqq | sed -e 's%\^%**%g' > PCDIR/pceq.txt && eq=(<PCDIR/pceq.txt) && echo -e -n '\033[92m\nprecision[default:16]>\033[0m' && read N
[ "mode" = "exec" ] && echo -e '\033[92m[2]eq(Multiple Lines + ##) >\033[0m' && eqq="" && IFS='\n' &&
while :
do
  read v
  eqq+=v'\n'
  if [ v = "##" ]; then
    break
  fi
done
echo -e "eqq" > PCDIR/pceq.txt
[ "mode" = "frac" ] && echo -e "\033[92m[3]eq(one liner code) >\033[0m" && read eqq && echo "eqq" >>PCDIR/pclist.txt && echo eqq | sed -e 's%[0-9]\+/[0-9]\+%Frac("&").limit_denominator()%g' -e 's%\^%**%g'>PCDIR/pceq.txt && eq=(<PCDIR/pceq.txt) && echo -e -n '\033[92m\nprecision[default:16] > \033[0m' && read N
[ "mode" = "mpf" ] && echo -e "\033[92m[4]eq(one liner code) >\033[0m" && read eqq && echoeqq | sed -e 's%[0-9]\+\.*[0-9]*%mpf("&")%g' -e 's%\^%**%g' > PCDIR/pceq.txt && eq=(<PCDIR/pceq.txt) && echo -e -n '\033[92m\nprecision[default:16]>\033[0m' && read N
[ "mode" = "rump" ] && echo -e '\033[92mRump'\''s example Test\033[0m' && eq="rump"
[ "mode" = "quit" ] && echo -e '\033[92mQuit pc\033[0m' && break


COMMAND=(cat << EOF
echo "eq" >>PCDIR/pclist.txt
echo -E "
from fractions import Fraction as Frac
from mpmath import *
from pprint import pprint
mp.pretty = True
from sympy import *

init_printing() #降べきの順
# init_printing(order='rev-lex') #昇べきの順
var('a:z')
f = Function('f')

GRE='\033[92m'
RED='\033[91m'
VIO='\033[95m'
END='\033[0m'

mp.dps = {N:-16}

print(VIO+'\n[1]pprint(eq,use_unicode=False)'+END)
pprint(eq,use_unicode=False)

print(VIO+'\n[2]pprint(eq,use_unicode=True)'+END)
pprint(eq,use_unicode=True)

print(VIO+'\n[3]pprint(eval(eq), order="rev-lex")'+END)
pprint(eval('eq'), order='rev-lex')

print(VIO+'\n[4]print(eval(eq))'+END)
print(eval('eq'))

print(VIO+'\n[5]N(eq,{N:-16})'+END)
try:
    N(eq,{N:- 16})
except AttributeError:
    print(RED+'No Numerical Evaluation'+END)
else:
    pprint(N(eq,{N:-16}))

print(VIO+'\n[6]latex(eval(eq))'+END)
try:
    latex(eval('eq'))
except AttributeError:
    print(RED+'No Output in LaTeX'+END)
else:
    print(latex(eval('eq')))

print(VIO+'\n[7]latex(N(eq,{N}))'+END)
try:
    latex(N(eq,{N:-16}))
except AttributeError:
    print(RED+'No Output in LaTeX'+END)
else:
    print(latex(N(eq,{N:-16})))
print('\n')
" | python

EOF

)


# モード毎
casemode in
just )
eval "{COMMAND}"
;;


exec )
echo "eqq" >> PCDIR/pclist.txt
echo -E "
from mpmath import *
from pprint import pprint
mp.pretty = True
from sympy import *
from fractions import Fraction as Frac
init_printing()
#init_printing(order='rev-lex')
var('a:z')
f = Function('f')

GRE='\033[92m'
RED='\033[91m'
VIO='\033[95m'
END='\033[0m'

mp.dps ={N:- 16}

print(VIO+'\n[0]exec(eq)'+END)
f = open('PCDIR/pceq.txt')
cmd = f.read()
exec(cmd)
print('\n')
" | python
echo -n "">PCDIR/pceq.txt
;;


frac )
echo eq && echo -n -e '\033[92mexpression change? [n(ENTER)/y]\033[0m ' ; read yn
case "yn" in [Yy])
read eq ;;
[])
;;
[n])
;;
esac
eval echo "COMMAND"
;;


mpf )
echo eq && echo -n -e '\033[92mexpression change? [n(ENTER)/y]\033[0m ' ; read yn
case "yn" in [Yy])
read eq ;;
[])
;;
[n])
;;
esac
eval "{COMMAND}"
;;


rump )
echo -e -n '\033[92mprecision[default:16]>\033[0m'
read N
echo "eq" >> PCDIR/pclist.txt
echo -E "
from mpmath import *
mp.pretty = True

a=77617
b=33096
c=333.75*b**6+a**2*(11*a**2*b**2-b**6-121*b**4-2)+5.5*b**8+a/(2*b)
print(f'Normal {c}')

def g(a, b):
    return (mpf('333.75')*b**6 + a**2*(11*a**2*b**2-b**6-121*b**4-2)+mpf('5.5')*b**8+a/(mpf('2')*b))
print('{:6}'.format('mp.dps'))
for mp.dps in range(1,N+1):
    print('{:6}'.format(mp.dps),g(mpf('77617'), mpf('33096')))
print('')
" | python

esac

done

}