WeixiangYan/CodeTransOcean huggingface dataset:
Task: Sphenic numbers




Go: package main

import (
    "fmt"
    "math"
    "rcu"
    "sort"
)

func main() {
    const limit = 1000000
    limit2 := int(math.Cbrt(limit)) 
    primes := rcu.Primes(limit / 6)
    pc := len(primes)
    var sphenic []int
    fmt.Println("Sphenic numbers less than 1,000:")
    for i := 0; i < pc-2; i++ {
        if primes[i] > limit2 {
            break
        }
        for j := i + 1; j < pc-1; j++ {
            prod := primes[i] * primes[j]
            if prod+primes[j+1] >= limit {
                break
            }
            for k := j + 1; k < pc; k++ {
                res := prod * primes[k]
                if res >= limit {
                    break
                }
                sphenic = append(sphenic, res)
            }
        }
    }
    sort.Ints(sphenic)
    ix := sort.Search(len(sphenic), func(i int) bool { return sphenic[i] >= 1000 })
    rcu.PrintTable(sphenic[:ix], 15, 3, false)
    fmt.Println("\nSphenic triplets less than 10,000:")
    var triplets [][3]int
    for i := 0; i < len(sphenic)-2; i++ {
        s := sphenic[i]
        if sphenic[i+1] == s+1 && sphenic[i+2] == s+2 {
            triplets = append(triplets, [3]int{s, s + 1, s + 2})
        }
    }
    ix = sort.Search(len(triplets), func(i int) bool { return triplets[i][2] >= 10000 })
    for i := 0; i < ix; i++ {
        fmt.Printf("%4d ", triplets[i])
        if (i+1)%3 == 0 {
            fmt.Println()
        }
    }
    fmt.Printf("\nThere are %s sphenic numbers less than 1,000,000.\n", rcu.Commatize(len(sphenic)))
    fmt.Printf("There are %s sphenic triplets less than 1,000,000.\n", rcu.Commatize(len(triplets)))
    s := sphenic[199999]
    pf := rcu.PrimeFactors(s)
    fmt.Printf("The 200,000th sphenic number is %s (%d*%d*%d).\n", rcu.Commatize(s), pf[0], pf[1], pf[2])
    fmt.Printf("The 5,000th sphenic triplet is %v.\n.", triplets[4999])
}




Python: 


from sympy import factorint

sphenics1m, sphenic_triplets1m = [], []

for i in range(3, 1_000_000):
    d = factorint(i)
    if len(d) == 3 and sum(d.values()) == 3:
        sphenics1m.append(i)
        if len(sphenics1m) > 2 and i - sphenics1m[-3] == 2 and i - sphenics1m[-2] == 1:
            sphenic_triplets1m.append(i)

print('Sphenic numbers less than 1000:')
for i, n in enumerate(sphenics1m):
    if n < 1000:
        print(f'{n : 5}', end='\n' if (i + 1) % 15 == 0 else '')
    else:
        break

print('\n\nSphenic triplets less than 10_000:')
for i, n in enumerate(sphenic_triplets1m):
    if n < 10_000:
        print(f'({n - 2} {n - 1} {n})', end='\n' if (i + 1) % 3 == 0 else '  ')
    else:
        break

print('\nThere are', len(sphenics1m), 'sphenic numbers and', len(sphenic_triplets1m),
      'sphenic triplets less than 1 million.')

S2HK = sphenics1m[200_000 - 1]
T5K = sphenic_triplets1m[5000 - 1]
print(f'The 200_000th sphenic number is {S2HK}, with prime factors {list(factorint(S2HK).keys())}.')
print(f'The 5000th sphenic triplet is ({T5K - 2} {T5K - 1} {T5K}).')
Task: Tree from nesting levels




Go: package main

import "fmt"

type any = interface{}

func toTree(list []int) any {
    s := []any{[]any{}}
    for _, n := range list {
        for n != len(s) {
            if n > len(s) {
                inner := []any{}
                s[len(s)-1] = append(s[len(s)-1].([]any), inner)
                s = append(s, inner)
            } else {
                s = s[0 : len(s)-1]
            }
        }
        s[len(s)-1] = append(s[len(s)-1].([]any), n)
        for i := len(s) - 2; i >= 0; i-- {
            le := len(s[i].([]any))
            s[i].([]any)[le-1] = s[i+1]
        }
    }
    return s[0]
}

func main() {
    tests := [][]int{
        {},
        {1, 2, 4},
        {3, 1, 3, 1},
        {1, 2, 3, 1},
        {3, 2, 1, 3},
        {3, 3, 3, 1, 1, 3, 3, 3},
    }
    for _, test := range tests {
        nest := toTree(test)
        fmt.Printf("%17s => %v\n", fmt.Sprintf("%v", test), nest)
    }
}




Python: def to_tree(x, index=0, depth=1):
   so_far = []
   while index < len(x):
       this = x[index]
       if this == depth:
           so_far.append(this)
       elif this > depth:
           index, deeper = to_tree(x, index, depth + 1)
           so_far.append(deeper)
       else: 
           index -=1
           break
       index += 1
   return (index, so_far) if depth > 1 else so_far


if __name__ ==  "__main__":
    from pprint import pformat

    def pnest(nest:list, width: int=9) -> str:
        text = pformat(nest, width=width).replace('\n', '\n    ')
        print(f" OR {text}\n")

    exercises = [
        [],
        [1, 2, 4],
        [3, 1, 3, 1],
        [1, 2, 3, 1],
        [3, 2, 1, 3],
        [3, 3, 3, 1, 1, 3, 3, 3],
        ]
    for flat in exercises:
        nest = to_tree(flat)
        print(f"{flat} NESTS TO: {nest}")
        pnest(nest)
Task: Sylvester's sequence




Go: package main

import (
    "fmt"
    "math/big"
)

func main() {
    one := big.NewInt(1)
    two := big.NewInt(2)
    next := new(big.Int)
    sylvester := []*big.Int{two}
    prod := new(big.Int).Set(two)
    count := 1
    for count < 10 {
        next.Add(prod, one)
        sylvester = append(sylvester, new(big.Int).Set(next))
        count++
        prod.Mul(prod, next)
    }
    fmt.Println("The first 10 terms in the Sylvester sequence are:")
    for i := 0; i < 10; i++ {
        fmt.Println(sylvester[i])
    }

    sumRecip := new(big.Rat)
    for _, s := range sylvester {
        sumRecip.Add(sumRecip, new(big.Rat).SetFrac(one, s))
    }
    fmt.Println("\nThe sum of their reciprocals as a rational number is:")
    fmt.Println(sumRecip)
    fmt.Println("\nThe sum of their reciprocals as a decimal number (to 211 places) is:")
    fmt.Println(sumRecip.FloatString(211))
}




Python: 

from functools import reduce
from itertools import count, islice



def sylvester():
    
    def go(n):
        return 1 + reduce(
            lambda a, x: a * go(x),
            range(0, n),
            1
        ) if 0 != n else 2

    return map(go, count(0))




def main():
    

    print("First 10 terms of OEIS A000058:")
    xs = list(islice(sylvester(), 10))
    print('\n'.join([
        str(x) for x in xs
    ]))

    print("\nSum of the reciprocals of the first 10 terms:")
    print(
        reduce(lambda a, x: a + 1 / x, xs, 0)
    )



if __name__ == '__main__':
    main()
Task: Order disjoint list items




Go: package main

import (
	"fmt"
	"sort"
	"strings"
)

type indexSort struct {
	val sort.Interface
	ind []int
}

func (s indexSort) Len() int           { return len(s.ind) }
func (s indexSort) Less(i, j int) bool { return s.ind[i] < s.ind[j] }
func (s indexSort) Swap(i, j int) {
	s.val.Swap(s.ind[i], s.ind[j])
	s.ind[i], s.ind[j] = s.ind[j], s.ind[i]
}

func disjointSliceSort(m, n []string) []string {
	s := indexSort{sort.StringSlice(m), make([]int, 0, len(n))}
	used := make(map[int]bool)
	for _, nw := range n {
		for i, mw := range m {
			if used[i] || mw != nw {
				continue
			}
			used[i] = true
			s.ind = append(s.ind, i)
			break
		}
	}
	sort.Sort(s)
	return s.val.(sort.StringSlice)
}

func disjointStringSort(m, n string) string {
	return strings.Join(
		disjointSliceSort(strings.Fields(m), strings.Fields(n)), " ")
}

func main() {
	for _, data := range []struct{ m, n string }{
		{"the cat sat on the mat", "mat cat"},
		{"the cat sat on the mat", "cat mat"},
		{"A B C A B C A B C", "C A C A"},
		{"A B C A B D A B E", "E A D A"},
		{"A B", "B"},
		{"A B", "B A"},
		{"A B B A", "B A"},
	} {
		mp := disjointStringSort(data.m, data.n)
		fmt.Printf("%s → %s » %s\n", data.m, data.n, mp)
	}

}




Python: from __future__ import print_function

def order_disjoint_list_items(data, items):
    
    itemindices = []
    for item in set(items):
        itemcount = items.count(item)
        
        lastindex = [-1]
        for i in range(itemcount):
            lastindex.append(data.index(item, lastindex[-1] + 1))
        itemindices += lastindex[1:]
    itemindices.sort()
    for index, item in zip(itemindices, items):
        data[index] = item

if __name__ == '__main__':
    tostring = ' '.join
    for data, items in [ (str.split('the cat sat on the mat'), str.split('mat cat')),
                         (str.split('the cat sat on the mat'), str.split('cat mat')),
                         (list('ABCABCABC'), list('CACA')),
                         (list('ABCABDABE'), list('EADA')),
                         (list('AB'), list('B')),
                         (list('AB'), list('BA')),
                         (list('ABBA'), list('BA')),
                         (list(''), list('')),
                         (list('A'), list('A')),
                         (list('AB'), list('')),
                         (list('ABBA'), list('AB')),
                         (list('ABAB'), list('AB')),
                         (list('ABAB'), list('BABA')),
                         (list('ABCCBA'), list('ACAC')),
                         (list('ABCCBA'), list('CACA')),
                       ]:
        print('Data M: %-24r Order N: %-9r' % (tostring(data), tostring(items)), end=' ')
        order_disjoint_list_items(data, items)
        print("-> M' %r" % tostring(data))
Task: Hash join




Go: package main

import "fmt"

func main() {
    tableA := []struct {
        value int
        key   string
    }{
        {27, "Jonah"}, {18, "Alan"}, {28, "Glory"}, {18, "Popeye"},
        {28, "Alan"},
    }
    tableB := []struct {
        key   string
        value string
    }{
        {"Jonah", "Whales"}, {"Jonah", "Spiders"},
        {"Alan", "Ghosts"}, {"Alan", "Zombies"}, {"Glory", "Buffy"},
    }
    
    h := map[string][]int{}
    for i, r := range tableA {
        h[r.key] = append(h[r.key], i)
    }
    
    for _, x := range tableB {
        for _, a := range h[x.key] {
            fmt.Println(tableA[a], x)
        }
    }
}




Python: from collections import defaultdict

def hashJoin(table1, index1, table2, index2):
    h = defaultdict(list)
    
    for s in table1:
        h[s[index1]].append(s)
    
    return [(s, r) for r in table2 for s in h[r[index2]]]

table1 = [(27, "Jonah"),
          (18, "Alan"),
          (28, "Glory"),
          (18, "Popeye"),
          (28, "Alan")]
table2 = [("Jonah", "Whales"),
          ("Jonah", "Spiders"),
          ("Alan", "Ghosts"),
          ("Alan", "Zombies"),
          ("Glory", "Buffy")]

for row in hashJoin(table1, 1, table2, 0):
    print(row)
Task: Odd squarefree semiprimes




Go: package main

import (
    "fmt"
    "rcu"
    "sort"
)

func main() {
    primes := rcu.Primes(333)
    var oss []int
    for i := 1; i < len(primes)-1; i++ {
        for j := i + 1; j < len(primes); j++ {
            n := primes[i] * primes[j]
            if n >= 1000 {
                break
            }
            oss = append(oss, n)
        }
    }
    sort.Ints(oss)
    fmt.Println("Odd squarefree semiprimes under 1,000:")
    for i, n := range oss {
        fmt.Printf("%3d ", n)
        if (i+1)%10 == 0 {
            fmt.Println()
        }
    }
    fmt.Printf("\n\n%d such numbers found.\n", len(oss))
}




Python: 

def isPrime(n):
    for i in range(2, int(n**0.5) + 1):
        if n % i == 0:
            return False        
    return True


if __name__ == '__main__':
    for p in range(3, 999):
        if not isPrime(p):            
            continue
        for q in range(p+1, 1000//p):
            if not isPrime(q):
                continue
            print(p*q, end = " ");
Task: Sierpinski curve




Go: package main

import (
    "github.com/fogleman/gg"
    "math"
)

var (
    width  = 770.0
    height = 770.0
    dc     = gg.NewContext(int(width), int(height))
)

var cx, cy, h float64

func lineTo(newX, newY float64) {
    dc.LineTo(newX-width/2+h, height-newY+2*h)
    cx, cy = newX, newY
}

func lineN() { lineTo(cx, cy-2*h) }
func lineS() { lineTo(cx, cy+2*h) }
func lineE() { lineTo(cx+2*h, cy) }
func lineW() { lineTo(cx-2*h, cy) }

func lineNW() { lineTo(cx-h, cy-h) }
func lineNE() { lineTo(cx+h, cy-h) }
func lineSE() { lineTo(cx+h, cy+h) }
func lineSW() { lineTo(cx-h, cy+h) }

func sierN(level int) {
    if level == 1 {
        lineNE()
        lineN()
        lineNW()
    } else {
        sierN(level - 1)
        lineNE()
        sierE(level - 1)
        lineN()
        sierW(level - 1)
        lineNW()
        sierN(level - 1)
    }
}

func sierE(level int) {
    if level == 1 {
        lineSE()
        lineE()
        lineNE()
    } else {
        sierE(level - 1)
        lineSE()
        sierS(level - 1)
        lineE()
        sierN(level - 1)
        lineNE()
        sierE(level - 1)
    }
}

func sierS(level int) {
    if level == 1 {
        lineSW()
        lineS()
        lineSE()
    } else {
        sierS(level - 1)
        lineSW()
        sierW(level - 1)
        lineS()
        sierE(level - 1)
        lineSE()
        sierS(level - 1)
    }
}

func sierW(level int) {
    if level == 1 {
        lineNW()
        lineW()
        lineSW()
    } else {
        sierW(level - 1)
        lineNW()
        sierN(level - 1)
        lineW()
        sierS(level - 1)
        lineSW()
        sierW(level - 1)
    }
}

func squareCurve(level int) {
    sierN(level)
    lineNE()
    sierE(level)
    lineSE()
    sierS(level)
    lineSW()
    sierW(level)
    lineNW()
    lineNE() 
}

func main() {
    dc.SetRGB(0, 0, 1) 
    dc.Clear()
    level := 5
    cx, cy = width/2, height
    h = cx / math.Pow(2, float64(level+1))
    squareCurve(level)
    dc.SetRGB255(255, 255, 0) 
    dc.SetLineWidth(2)
    dc.Stroke()
    dc.SavePNG("sierpinski_curve.png")
}




Python: import numpy as np
import matplotlib.pyplot as plt
from matplotlib.colors import hsv_to_rgb as hsv

def curve(axiom, rules, angle, depth):
    for _ in range(depth):
        axiom = ''.join(rules[c] if c in rules else c for c in axiom)

    a, x, y = 0, [0], [0]
    for c in axiom:
        match c:
            case '+':
                a += 1
            case '-':
                a -= 1
            case 'F' | 'G':
                x.append(x[-1] + np.cos(a*angle*np.pi/180))
                y.append(y[-1] + np.sin(a*angle*np.pi/180))

    l = len(x)
    
    for i in range(l - 1):
        plt.plot(x[i:i+2], y[i:i+2], color=hsv([i/l, 1, .7]))
    plt.gca().set_aspect(1)
    plt.show()

curve('F--XF--F--XF', {'X': 'XF+G+XF--F--XF+G+X'}, 45, 5)
Task: Palindromic primes




Go: package main

import (
    "fmt"
    "rcu"
)

func reversed(n int) int {
    rev := 0
    for n > 0 {
        rev = rev*10 + n%10
        n /= 10
    }
    return rev
}

func main() {
    primes := rcu.Primes(99999)
    var pals []int
    for _, p := range primes {
        if p == reversed(p) {
            pals = append(pals, p)
        }
    }
    fmt.Println("Palindromic primes under 1,000:")
    var smallPals, bigPals []int
    for _, p := range pals {
        if p < 1000 {
            smallPals = append(smallPals, p)
        } else {
            bigPals = append(bigPals, p)
        }
    }
    rcu.PrintTable(smallPals, 10, 3, false)
    fmt.Println()
    fmt.Println(len(smallPals), "such primes found.")

    fmt.Println("\nAdditional palindromic primes under 100,000:")
    rcu.PrintTable(bigPals, 10, 6, true)
    fmt.Println()
    fmt.Println(len(bigPals), "such primes found,", len(pals), "in all.")
}




Python: 

from itertools import takewhile



def palindromicPrimes():
    
    def p(n):
        s = str(n)
        return s == s[::-1]
    return (n for n in primes() if p(n))



def main():
    
    print('\n'.join(
        str(x) for x in takewhile(
            lambda n: 1000 > n,
            palindromicPrimes()
        )
    ))





def primes():
    
    n = 2
    dct = {}
    while True:
        if n in dct:
            for p in dct[n]:
                dct.setdefault(n + p, []).append(p)
            del dct[n]
        else:
            yield n
            dct[n * n] = [n]
        n = 1 + n



if __name__ == '__main__':
    main()
Task: Find words which contains all the vowels




Go: package main

import (
    "bytes"
    "fmt"
    "io/ioutil"
    "log"
    "unicode/utf8"
)

func main() {
    wordList := "unixdict.txt"
    b, err := ioutil.ReadFile(wordList)
    if err != nil {
        log.Fatal("Error reading file")
    }
    bwords := bytes.Fields(b)
    var words []string
    for _, bword := range bwords {
        s := string(bword)
        if utf8.RuneCountInString(s) > 10 {
            words = append(words, s)
        }
    }
    count := 0
    fmt.Println("Words which contain all 5 vowels once in", wordList, "\b:\n")
    for _, word := range words {
        ca, ce, ci, co, cu := 0, 0, 0, 0, 0
        for _, r := range word {
            switch r {
            case 'a':
                ca++
            case 'e':
                ce++
            case 'i':
                ci++
            case 'o':
                co++
            case 'u':
                cu++
            }
        }
        if ca == 1 && ce == 1 && ci == 1 && co == 1 && cu == 1 {
            count++
            fmt.Printf("%2d: %s\n", count, word)
        }
    }
}




Python: import urllib.request
from collections import Counter

urllib.request.urlretrieve("http://wiki.puzzlers.org/pub/wordlists/unixdict.txt", "unixdict.txt")

dictionary = open("unixdict.txt","r")

wordList = dictionary.read().split('\n')

dictionary.close()

for word in wordList:
    if len(word)>10:
        frequency = Counter(word.lower())
        if frequency['a']==frequency['e']==frequency['i']==frequency['o']==frequency['u']==1:
            print(word)
Task: Base 16 numbers needing a to f




Go: package main

import (
    "fmt"
    "strconv"
    "strings"
)

func main() {
    const nondecimal = "abcdef"
    c := 0
    for i := int64(0); i <= 500; i++ {
        hex := strconv.FormatInt(i, 16)
        if strings.ContainsAny(nondecimal, hex) {
            fmt.Printf("%3d ", i)
            c++
            if c%15 == 0 {
                fmt.Println()
            }
        }
    }
    fmt.Printf("\n\n%d such numbers found.\n", c)
}




Python: 



def p(n):
    
    return 9 < n and (9 < n % 16 or p(n // 16))




def main():
    
    xs = [
        str(n) for n in range(1, 1 + 500)
        if p(n)
    ]
    print(f'{len(xs)} matches for the predicate:\n')
    print(
        table(6)(xs)
    )





def chunksOf(n):
    
    def go(xs):
        return (
            xs[i:n + i] for i in range(0, len(xs), n)
        ) if 0 < n else None
    return go



def table(n):
    
    def go(xs):
        w = len(xs[-1])
        return '\n'.join(
            ' '.join(row) for row in chunksOf(n)([
                s.rjust(w, ' ') for s in xs
            ])
        )
    return go



if __name__ == '__main__':
    main()
Task: Juggler sequence




Go: package main

import (
    "fmt"
    "log"
    
    big "github.com/ncw/gmp"
    "rcu"
)

var zero = new(big.Int)
var one = big.NewInt(1)
var two = big.NewInt(2)

func juggler(n int64) (int, int, *big.Int, int) {
    if n < 1 {
        log.Fatal("Starting value must be a positive integer.")
    }
    count := 0
    maxCount := 0
    a := big.NewInt(n)
    max := big.NewInt(n)
    tmp := new(big.Int)
    for a.Cmp(one) != 0 {
        if tmp.Rem(a, two).Cmp(zero) == 0 {
            a.Sqrt(a)
        } else {
            tmp.Mul(a, a)
            tmp.Mul(tmp, a)
            a.Sqrt(tmp)
        }
        count++
        if a.Cmp(max) > 0 {
            max.Set(a)
            maxCount = count
        }
    }
    return count, maxCount, max, len(max.String())
}

func main() {
    fmt.Println("n    l[n]  i[n]  h[n]")
    fmt.Println("-----------------------------------")
    for n := int64(20); n < 40; n++ {
        count, maxCount, max, _ := juggler(n)
        cmax := rcu.Commatize(int(max.Int64()))
        fmt.Printf("%2d    %2d   %2d    %s\n", n, count, maxCount, cmax)
    }
    fmt.Println()
    nums := []int64{
        113, 173, 193, 2183, 11229, 15065, 15845, 30817, 48443, 275485, 1267909,
        2264915, 5812827, 7110201, 56261531, 92502777, 172376627, 604398963,
    }
    fmt.Println("       n      l[n]   i[n]   d[n]")
    fmt.Println("-------------------------------------")
    for _, n := range nums {
        count, maxCount, _, digits := juggler(n)
        cn := rcu.Commatize(int(n))
        fmt.Printf("%11s   %3d    %3d    %s\n", cn, count, maxCount, rcu.Commatize(digits))
    }
}




Python: from math import isqrt

def juggler(k, countdig=True, maxiters=1000):
    m, maxj, maxjpos = k, k, 0
    for i in range(1, maxiters):
        m = isqrt(m) if m % 2 == 0 else isqrt(m * m * m)
        if m >= maxj:
            maxj, maxjpos  = m, i
        if m == 1:
            print(f"{k: 9}{i: 6,}{maxjpos: 6}{len(str(maxj)) if countdig else maxj: 20,}{' digits' if countdig else ''}")
            return i

    print("ERROR: Juggler series starting with $k did not converge in $maxiters iterations")


print("       n    l(n)  i(n)       h(n) or d(n)\n-------------------------------------------")
for k in range(20, 40):
    juggler(k, False)

for k in [113, 173, 193, 2183, 11229, 15065, 15845, 30817, 48443, 275485, 1267909]:
    juggler(k)
Task: Sierpinski square curve




Go: package main

import (
    "github.com/fogleman/gg"
    "github.com/trubitsyn/go-lindenmayer"
    "log"
    "math"
)

const twoPi = 2 * math.Pi

var (
    width  = 770.0
    height = 770.0
    dc     = gg.NewContext(int(width), int(height))
)

var cx, cy, h, theta float64

func main() {
    dc.SetRGB(0, 0, 1) 
    dc.Clear()
    cx, cy = 10, height/2+5
    h = 6
    sys := lindenmayer.Lsystem{
        Variables: []rune{'X'},
        Constants: []rune{'F', '+', '-'},
        Axiom:     "F+XF+F+XF",
        Rules: []lindenmayer.Rule{
            {"X", "XF-F+F-XF+F+XF-F+F-X"},
        },
        Angle: math.Pi / 2, 
    }
    result := lindenmayer.Iterate(&sys, 5)
    operations := map[rune]func(){
        'F': func() {
            newX, newY := cx+h*math.Sin(theta), cy-h*math.Cos(theta)
            dc.LineTo(newX, newY)
            cx, cy = newX, newY
        },
        '+': func() {
            theta = math.Mod(theta+sys.Angle, twoPi)
        },
        '-': func() {
            theta = math.Mod(theta-sys.Angle, twoPi)
        },
    }
    if err := lindenmayer.Process(result, operations); err != nil {
        log.Fatal(err)
    }
    
    operations['+']()
    operations['F']()

    
    dc.SetRGB255(255, 255, 0) 
    dc.SetLineWidth(2)
    dc.Stroke()
    dc.SavePNG("sierpinski_square_curve.png")
}




Python: import matplotlib.pyplot as plt
import math


def nextPoint(x, y, angle):
    a = math.pi * angle / 180
    x2 = (int)(round(x + (1 * math.cos(a))))
    y2 = (int)(round(y + (1 * math.sin(a))))
    return x2, y2


def expand(axiom, rules, level):
    for l in range(0, level):
        a2 = ""
        for c in axiom:
            if c in rules:
                a2 += rules[c]
            else:
                a2 += c
        axiom = a2
    return axiom


def draw_lsystem(axiom, rules, angle, iterations):
    xp = [1]
    yp = [1]
    direction = 0
    for c in expand(axiom, rules, iterations):
        if c == "F":
            xn, yn = nextPoint(xp[-1], yp[-1], direction)
            xp.append(xn)
            yp.append(yn)
        elif c == "-":
            direction = direction - angle
            if direction < 0:
                direction = 360 + direction
        elif c == "+":
            direction = (direction + angle) % 360

    plt.plot(xp, yp)
    plt.show()


if __name__ == '__main__':
    
    s_axiom = "F+XF+F+XF"
    s_rules = {"X": "XF-F+F-XF+F+XF-F+F-X"}
    s_angle = 90

    draw_lsystem(s_axiom, s_rules, s_angle, 3)