diff --git a/app/services/utils.rb b/app/services/utils.rb new file mode 100644 index 0000000..68ea33c --- /dev/null +++ b/app/services/utils.rb @@ -0,0 +1,20 @@ +# frozen_string_literal: true + +class Utils + def self.previous_power_of_two(number) + return 0 if number.zero? + + exponent = Math.log2 number + 2**exponent.floor + end + + def self.next_power_of_two(number) + return 1 if number.zero? + + 2 * previous_power_of_two(number) + end + + def self.po2?(number) + number.to_s(2).count('1') == 1 + end +end diff --git a/spec/services/utils_spec.rb b/spec/services/utils_spec.rb new file mode 100644 index 0000000..f1c9ef5 --- /dev/null +++ b/spec/services/utils_spec.rb @@ -0,0 +1,50 @@ +# frozen_string_literal: true + +RSpec.describe Utils do + [ + { test: 5, result: 4 }, + { test: 3, result: 2 }, + { test: 13, result: 8 }, + { test: 35, result: 32 }, + { test: 32, result: 32 }, + { test: 0, result: 0 }, + { test: 3482, result: 2048 }, + { test: 1337, result: 1024 } + ].each do |parameters| + it "calculates #{parameters[:result]} as previous power of two from #{parameters[:test]}" do + expect(Utils.previous_power_of_two(parameters[:test])).to eq(parameters[:result]) + end + end + + [ + { test: 5, result: 8 }, + { test: 3, result: 4 }, + { test: 13, result: 16 }, + { test: 35, result: 64 }, + { test: 32, result: 64 }, + { test: 0, result: 1 }, + { test: 3482, result: 4096 }, + { test: 1337, result: 2048 } + ].each do |parameters| + it "calculates #{parameters[:result]} as previous power of two from #{parameters[:test]}" do + expect(Utils.next_power_of_two(parameters[:test])).to eq(parameters[:result]) + end + end + + [ + { test: 5, result: false }, + { test: 3, result: false }, + { test: 16, result: true }, + { test: 4, result: true }, + { test: 32, result: true }, + { test: 0, result: false }, + { test: 3482, result: false }, + { test: 8192, result: true } + ].each do |parameters| + is_isnt = "isn't" unless parameters[:result] + is_isnt = 'is' if parameters[:result] + it "thinks #{parameters[:test]} #{is_isnt} a power of two" do + expect(Utils.po2?(parameters[:test])).to eq(parameters[:result]) + end + end +end