2024年9月28日土曜日

fx-CG50 で Biomorph を描く

 Sentaro様から「面白いモノはナーイ ?」との事で、fx-CG50 upython をしばき倒す(?) 「Pickovers' Biomorph」のコードを動かしてみました。

当方が、Pickovers' Biomorph を知った、そのネタ元と言いますと、昔、図書館で読んだ、日経サイエンス誌の連載「コンピューター・リクリエーション」(A. K. Dewdney) なのですが、Pickover biomorphs で検索すると、およその所が解ると思います。

Mandelbrot set graphics の作業の様ですが、少し異なる部分もあります。
詳細はコードをご参照ください。

Pickovers' Biomorphs の場合、繰り返す計算式を色々と変更する事で、描かれる画像が多様に変化します。
このコードでは、

    z = z*z+c
を繰り返しますが、これを、例えばつぎの行にある様に、
    z = cmath.sin(z*z)-c
とかに変更すると、画像が大きく変化するのです。

複素数平面の座標値に数式を繰り返し適用するため、複素数を扱う関数が必要になりますが、残念ながら、fx-CG50 には cmath module が用意されておりません。

そこで、急ごしらえで cmath module を用意しました。 残念ながら、asin() などはまだ、用意できておりませんが、チョット遊ぶなら、この辺りから始めても十分であると思います。 

実行は、プログラムを読み込んだ後、

biom() 

と入力する事で実行されます。

ループ中の数式を変更する事でも、画像が大きく変化するのですが、定数 c を変える事でも、微妙に画像が変化します。
定数 c も複素数ですが、biom(c.real, c.imag) の様に、実部と虚部をカンマで分けて指定する事で与えられます。

残念ながら、cmath module が system binary ではなく、実行速度が大変遅いという哀しい部分はありますが、
じわじわとグラフィクスが描かれる様を眺めるのも、手のひらで動く電卓ならではの愉しみであると思います。

 

追記 on 2024-10-05

過日、K 様にコメント戴き、sqrt() を更新いたしました。
math.copysign() が fx-CG50 には無いため、自家製の copysign() もどき csign() を付け足しましたヨ。これにより、計算速度が向上したという具合には行きませんが、ネタとしては色々と面白かったので、後日、別記したく思います。

謝謝 !


リスト  biom.py

# title : biom.py - Pickovers' Biomorph for fx-CG50
# begin : 2024-09-28 19:33:39

from casioplot import *
import math
import cmath

def  biom(re=0, im=0) :
  width  = 383
  height = 191

  xs=-3.8
  xe= 3.8
  ys=-1.9
  ye= 1.9
 
  c = re - im*1j

  #  Biomorph
  for j in range(height):
    for i in range(width):
      z = (i*(xe-xs)/width +xs) + 1j*(j*(ys-ye)/height+ye)
      #  repeating core
      k = 0
      while abs(z) <= 10 and k < 10:
        z = z*z+c
        #z = cmath.sin(z*z)-c
        k=k+1
      #  
      if abs(z.real) < 10 or abs(z.imag) < 10 :
        set_pixel(int(i), int(j))

      #  show graphix progressively
      show_screen()


リスト  cmath.py

##  title : [WIP] cmath module for fx-CG50
## begin : 2024-09-28 00:38

import math

# copysign() like something ...
def csign(x, y) :
if y == 0.0 :
if str(y) == '-0.0' :
return -abs(x)
else :
return abs(x)
else :
if y < 0 :
return -abs(x)
else :
return abs(x)

#
def phase(x) :
return math.atan2(x.imag, x.real)

##
def exp(x) :
return pow(math.e, x)

##
def ln(x) :
return math.log(abs(x)) + phase(x)*1j

##
def log(x, base=math.e) :
return ln(x) / ln(base)

## thanks K sama ! on 2024-10-04
def sqrt(x) :
# return pow(x, 0.5)
return math.sqrt((abs(z)+z.real)/2) + 1j* csign(math.sqrt((abs(z)-z.real)/2), z.imag)

##
def sin(c) :
return math.sin(c.real)*math.cosh(c.imag) + (math.cos(c.real)*math.sinh(c.imag))*1j

##
def cos(c) :
return math.cos(c.real)*math.cosh(c.imag) - (math.sin(c.real)*math.sinh(c.imag))*1j

##
def tan(c) :
return sin(c) / cos(c)

2024年9月22日日曜日

python電卓を持っていても余り使っておらんので、暇つぶし

 以前に、fx-CG50 を買って、先日、ようやく python が使える様にアップデートした所。
「慣らし運転」ではありませんが、pythonの計算速度を見るつもりで、簡単なループ計算を実行したという次第。

プログラムは以下。
冒頭の文字列部分は「コメント」なので、電卓では無用ノ介。本体のループ部分だけを入れて、実行してみてください。


'''
NHK TV 「3ヶ月で学ぶ数学」より。

問題 : 
3桁の整数 ABC (=100*A+10*B+C) について、
+  ABC * 3/4 = BCA
+  BCA * 3/4 = CAB

の関係を満たす整数ABC は、2つある。全てを求めよ。
(中学校の入試問題より)

答え : 

1. 比例式を準備

+  ABC : BCA = 4 : 3
+  BCA : CAB = 4 : 3

2.  比例式を、最小公倍数にて一本に

+  ABC : BCA = 4 : 3 = 16 :12
+  BCA : CAB = 4 : 3 = 12 : 9

よって、
+  ABC : BCA : CAB = 16 : 12 : 9

3. これより、
   「CAB は 9の倍数」→「CAB の各桁の和は 9 の倍数」→「ABC, BCA の各桁の和は 9 の倍数」

4. また、
   「ABC は 9の倍数 and 16の倍数」→「ABC は 16*9の倍数」

+  16*9 = 144 の倍数
   144, 288, 432, 576, 720, 864

5. 一本化した比例式より、
   A >= B >= C

6.  この条件を満たす 144の倍数は、
    432, 864

という具合であった。

しかし、pythonが動く電卓がある事だし 力技で、解いてみたという次第。
(大人気ない)

結果は、

Hit ! 0
Hit ! 432
Hit ! 864

という具合。
1000回ループながらも、瞬時に答えが得られ、ビックリしてしまいました。

'''

for a in range(10) :
    for b in range(10) :
        for c in range(10) :
            abc = a*100+b*10+c
            bca = 100*b+10*c+a
            cab = c*100+a*10+b
            if abc *3/4 == bca :
                if bca *3/4 == cab :
                    print('Hit !', abc)