diff --git a/.github/workflows/golang_test.yml b/.github/workflows/golang_test.yml index 27979ea..70b1564 100644 --- a/.github/workflows/golang_test.yml +++ b/.github/workflows/golang_test.yml @@ -22,7 +22,5 @@ jobs: version: v1.51.0 args: --disable-all -E gofmt --print-linter-name skip-build-cache: true - - name: run math unit testing - run: go test ./math/... - - name: run math implementation unit testing - run: go test ./math_implementation/... + - name: run unit testing + run: go test $(go list ./... | grep -v 'basic\|intermediate\|utilities') diff --git a/math_implementation/armstrong/is_armstrong_test.go b/math_implementation/armstrong/is_armstrong_test.go index 2e85d35..5c9fc55 100644 --- a/math_implementation/armstrong/is_armstrong_test.go +++ b/math_implementation/armstrong/is_armstrong_test.go @@ -34,7 +34,7 @@ var testCase = []struct { }, } -func testingArmstrong(t *testing.T) { +func TestArmstrong(t *testing.T) { for _, test := range testCase { t.Run(test.name, func(t *testing.T) { funcResult := cekArmstrong(test.input) diff --git a/math_implementation/faktorial/faktorial.go b/math_implementation/faktorial/faktorial.go new file mode 100644 index 0000000..ca1c297 --- /dev/null +++ b/math_implementation/faktorial/faktorial.go @@ -0,0 +1,66 @@ +package faktorial + +import "errors" + +var ArgumentNegatif = errors.New("argumen input harus berupa bilangan bulat non-negatif") + +// fungsi untuk menghitung faktorial secara bruteforce +func Iterasi(n int) (int, error) { + if n < 0 { + return 0, ArgumentNegatif + } + + hasil := 1 + for i := 2; i <= n; i++ { + hasil *= i + } + return hasil, nil +} + +// fungsi menghitung faktorial secara rekursif +func Rekursif(n int) (int, error) { + if n < 0 { + return 0, ArgumentNegatif + } + + if n <= 1 { + return 1, nil + } + + prev, _ := Rekursif(n - 1) + return n * prev, nil +} + +// menghitung faktorial menggunakan tree biner (divide and conquer) +func TreeBin(n int) (int, error) { + if n < 0 { + return 0, ArgumentNegatif + } + + if n == 0 { + return 1, nil + } + + if n == 1 || n == 2 { + return n, nil + } + + return produkTree(2, n), nil +} + +func produkTree(l int, r int) int { + if l > r { + return 1 + } + + if l == r { + return l + } + + if r-l == 1 { + return l * r + } + + m := (l + r) / 2 + return produkTree(l, m) * produkTree(m+1, r) +} diff --git a/math_implementation/faktorial/faktorial_test.go b/math_implementation/faktorial/faktorial_test.go new file mode 100644 index 0000000..974695c --- /dev/null +++ b/math_implementation/faktorial/faktorial_test.go @@ -0,0 +1,47 @@ +package faktorial + +import ( + "fmt" + "testing" +) + +type fungsiFaktorial func(int) (int, error) + +var implementasi = map[string]fungsiFaktorial{ + "Iterasi": Iterasi, + "Rekursif": Rekursif, + "Tree": TreeBin, +} + +var testCase = []struct { + n int + ekspetasi int +}{ + {0, 1}, + {1, 1}, + {6, 720}, + {9, 362880}, +} + +func TestFaktorial(t *testing.T) { + for implName, implFunction := range implementasi { + t.Run(implName+" error input negatif", func(t *testing.T) { + _, error := implFunction(-1) + if error != ArgumentNegatif { + t.Errorf("tidak ada error dari input negatif") + } + }) + + for _, tc := range testCase { + t.Run(fmt.Sprintf("%s dengan input %d", implName, tc.n), func(t *testing.T) { + aktual, err := implFunction(tc.n) + if err != nil { + t.Errorf("add error") + } + if aktual != tc.ekspetasi { + t.Errorf("ekspetasi: %d, aktual: %d", tc.ekspetasi, aktual) + } + }) + } + } +}