diff --git a/math/binarymath/arithmeticmean.go b/math/binary/arithmeticmean.go similarity index 82% rename from math/binarymath/arithmeticmean.go rename to math/binary/arithmeticmean.go index 46f72a405..3fbce0631 100644 --- a/math/binarymath/arithmeticmean.go +++ b/math/binary/arithmeticmean.go @@ -5,8 +5,8 @@ // author(s) [red_byte](https://github.com/i-redbyte) // see arithmeticmean_test.go -// Package binarymath describes algorithms that use binary operations for different calculations. -package binarymath +// Package binary describes algorithms that use binary operations for different calculations. +package binary func MeanUsingAndXor(a int, b int) int { return ((a ^ b) >> 1) + (a & b) diff --git a/math/binarymath/arithmeticmean_test.go b/math/binary/arithmeticmean_test.go similarity index 98% rename from math/binarymath/arithmeticmean_test.go rename to math/binary/arithmeticmean_test.go index 0b06aa50f..fe030e859 100644 --- a/math/binarymath/arithmeticmean_test.go +++ b/math/binary/arithmeticmean_test.go @@ -3,7 +3,7 @@ // author(s) [red_byte](https://github.com/i-redbyte) // see arithmeticmean.go -package binarymath +package binary import "testing" diff --git a/math/binary/checkisnumberpoweroftwo.go b/math/binary/checkisnumberpoweroftwo.go new file mode 100644 index 000000000..46c459cf8 --- /dev/null +++ b/math/binary/checkisnumberpoweroftwo.go @@ -0,0 +1,36 @@ +// checkisnumberpoweroftwo.go +// description: Is the number a power of two +// details: +// Checks if a number is a power of two- [Power of two](https://en.wikipedia.org/wiki/Power_of_two) +// author(s) [red_byte](https://github.com/i-redbyte) +// see checkisnumberpoweroftwo_test.go + +package binary + +// IsPowerOfTwo This function uses the fact that powers of 2 are represented +// like 10...0 in binary, and numbers one less than the power of 2 +// are represented like 11...1. +// Therefore, using the and function: +// 10...0 +// & 01...1 +// 00...0 -> 0 +// This is also true for 0, which is not a power of 2, for which we +// have to add and extra condition. +func IsPowerOfTwo(x int) bool { + return x > 0 && (x&(x-1)) == 0 +} + +// IsPowerOfTwoLeftShift This function takes advantage of the fact that left shifting a number +// by 1 is equivalent to multiplying by 2. For example, binary 00000001 when shifted by 3 becomes 00001000, +// which in decimal system is 8 or = 2 * 2 * 2 +func IsPowerOfTwoLeftShift(number uint) bool { + if number == 0 { + return false + } + for p := uint(1); p > 0; p = p << 1 { + if number == p { + return true + } + } + return false +} diff --git a/math/binary/checkisnumberpoweroftwo_test.go b/math/binary/checkisnumberpoweroftwo_test.go new file mode 100644 index 000000000..83c0b0083 --- /dev/null +++ b/math/binary/checkisnumberpoweroftwo_test.go @@ -0,0 +1,93 @@ +// checkisnumberpoweroftwo_test.go +// description: Test for Is the number a power of two +// author(s) [red_byte](https://github.com/i-redbyte) +// see checkisnumberpoweroftwo.go + +package binary + +import ( + math2 "github.com/TheAlgorithms/Go/math" + "math" + "testing" +) + +func getTestsForPowerOfTwo() []struct { + name string + a int + missing bool +} { + var tests = []struct { + name string + a int + missing bool + }{ + {"Is 64 a power of 2? - YES", 64, true}, + {"Is 1 a power of 2? - YES", 1, true}, + {"Is 2 a power of 2? - YES", 2, true}, + {"Is 5 a power of 2? - NO", 5, false}, + {"Is 1023 a power of 2? - NO", 1023, false}, + {"Is 1024 a power of 2? - YES", 1024, true}, + {"Is 0 a power of 2? - NO", 0, false}, + {"Is 9223372036854775807 a power of 2? - NO", math.MaxInt64, false}, + {"Is 9223372036854775806 a power of 2? - NO", math.MaxInt64, false}, + {"Is 4611686018427387904 a power of 2? - YES", 4611686018427387904, true}, + } + return tests +} + +func TestIsPowerOfTwo(t *testing.T) { + tests := getTestsForPowerOfTwo() + for _, tv := range tests { + t.Run(tv.name, func(t *testing.T) { + result := IsPowerOfTwo(tv.a) + t.Log(tv.a, " ", result) + if result != tv.missing { + t.Errorf("Wrong result! Expected:%v, returned:%v ", tv.missing, result) + } + }) + } +} + +func TestIsPowerOfTwoLeftShift(t *testing.T) { + tests := getTestsForPowerOfTwo() + for _, tv := range tests { + t.Run(tv.name, func(t *testing.T) { + result := IsPowerOfTwoLeftShift(uint(tv.a)) + t.Log(tv.a, " ", result) + if result != tv.missing { + t.Errorf("Wrong result! Expected:%v, returned:%v ", tv.missing, result) + } + }) + } +} + +func TestIsPowOfTwoUseLog(t *testing.T) { + tests := getTestsForPowerOfTwo() + for _, tv := range tests { + t.Run(tv.name, func(t *testing.T) { + result := math2.IsPowOfTwoUseLog(float64(tv.a)) + t.Log(tv.a, " ", result) + if result != tv.missing { + t.Errorf("Wrong result! Expected:%v, returned:%v ", tv.missing, result) + } + }) + } +} + +func BenchmarkIsPowerOfTwoBinaryMethod(b *testing.B) { + for i := 0; i < b.N; i++ { + IsPowerOfTwo(1024) + } +} + +func BenchmarkIsPowerOfTwoUseCycleAndLeftShift(b *testing.B) { + for i := 0; i < b.N; i++ { + IsPowerOfTwoLeftShift(1024) + } +} + +func BenchmarkIsPowerOfTwoUseLog(b *testing.B) { + for i := 0; i < b.N; i++ { + math2.IsPowOfTwoUseLog(1024) + } +} diff --git a/math/binarymath/xorsearch.go b/math/binary/xorsearch.go similarity index 96% rename from math/binarymath/xorsearch.go rename to math/binary/xorsearch.go index 1d706e8ad..cdd4e09c8 100644 --- a/math/binarymath/xorsearch.go +++ b/math/binary/xorsearch.go @@ -5,7 +5,7 @@ // author(s) [red_byte](https://github.com/i-redbyte) // see xorsearch_test.go -package binarymath +package binary func XorSearchMissingNumber(a []int) int { n := len(a) diff --git a/math/binarymath/xorsearch_test.go b/math/binary/xorsearch_test.go similarity index 98% rename from math/binarymath/xorsearch_test.go rename to math/binary/xorsearch_test.go index 73e5489d9..40bc8a8ef 100644 --- a/math/binarymath/xorsearch_test.go +++ b/math/binary/xorsearch_test.go @@ -2,7 +2,7 @@ // description: Test for Find a missing number in a sequence // author(s) [red_byte](https://github.com/i-redbyte) // see xorsearch.go -package binarymath +package binary import ( "testing" diff --git a/math/checkisnumberpoweroftwo.go b/math/checkisnumberpoweroftwo.go new file mode 100644 index 000000000..48f0fe84a --- /dev/null +++ b/math/checkisnumberpoweroftwo.go @@ -0,0 +1,16 @@ +package math + +import ( + "math" +) + +// IsPowOfTwoUseLog This function checks if a number is a power of two using the logarithm. +// The limiting degree can be from 0 to 63. +// See alternatives in the binary package. +func IsPowOfTwoUseLog(number float64) bool { + if number == 0 || math.Round(number) == math.MaxInt64 { + return false + } + log := math.Log2(number) + return log == math.Round(log) +} diff --git a/math/checkisnumberpoweroftwo_test.go b/math/checkisnumberpoweroftwo_test.go new file mode 100644 index 000000000..834b99d83 --- /dev/null +++ b/math/checkisnumberpoweroftwo_test.go @@ -0,0 +1,54 @@ +// checkisnumberpoweroftwo_test.go +// description: Test for Is the number a power of two +// author(s) [red_byte](https://github.com/i-redbyte) +// see checkisnumberpoweroftwo.go + +package math + +import ( + "math" + "testing" +) + +func getTestsForPowerOfTwo() []struct { + name string + a int + missing bool +} { + var tests = []struct { + name string + a int + missing bool + }{ + {"Is 64 a power of 2? - YES", 64, true}, + {"Is 1 a power of 2? - YES", 1, true}, + {"Is 2 a power of 2? - YES", 2, true}, + {"Is 5 a power of 2? - NO", 5, false}, + {"Is 1023 a power of 2? - NO", 1023, false}, + {"Is 1024 a power of 2? - YES", 1024, true}, + {"Is 0 a power of 2? - NO", 0, false}, + {"Is 9223372036854775807 a power of 2? - NO", math.MaxInt64, false}, + {"Is 9223372036854775806 a power of 2? - NO", math.MaxInt64, false}, + {"Is 4611686018427387904 a power of 2? - YES", 4611686018427387904, true}, + } + return tests +} + +func TestIsPowOfTwoUseLog(t *testing.T) { + tests := getTestsForPowerOfTwo() + for _, tv := range tests { + t.Run(tv.name, func(t *testing.T) { + result := IsPowOfTwoUseLog(float64(tv.a)) + t.Log(tv.a, " ", result) + if result != tv.missing { + t.Errorf("Wrong result! Expected:%v, returned:%v ", tv.missing, result) + } + }) + } +} + +func BenchmarkIsPowerOfTwoUseLog(b *testing.B) { + for i := 0; i < b.N; i++ { + IsPowOfTwoUseLog(1024) + } +}