Why is this happening with base converter? - ruby

I am building a number base converter. Here is my code:
def num_to_s(num, base)
results = []
remainders = []
while base <= num
result = num / base #divide the initial value of num
num = result #put that back in num so you can do it again
results << num #push into array, then map for remainders
end
remainders << results.map{|i| result = i % base} #get remainders (doesn't shovel first one?)
first_remainder = num % base #since the first remainder isn't getting recorded
return (first_remainder.to_s + remainders.to_s).reverse
end
num_to_s(13346, 7)
The modulo that gathers the remainders from the results array is not picking up the remainder from the very first iteration of that array. I remedied the skip by giving the first modulo operation it's own separate variable, which may be a cheap hack but it works. Why is this happening? And is there a better way to fix it (without some complete overhaul)?
It needs to convert up to base 16. I am aware that this will not convert base 16 yet because of the letters involved, I'll figure that when I get to it. But I am open to suggestions on that as well.

The very first operation you do is to modulo number by base. That’s why the initial is not kept. So, the easiest way to keep it is just to put it into an array initially:
def num_to_s (num, base)
results = [num] # keep the initial
while base <= num
num /= base # divide the initial value of num
results << num # push into array, then map for remainders
end
# reverse an array and only then join it into string
results.map {|i| i % base}.reverse.join
end
puts num_to_s(13346, 7)
#⇒ 53624

Related

Ruby prime number sum

I am trying to take the sum of the n first prime numbers. I found a way of showing the first 100, but I don't know how to get rid of 1 and how to make a sum with the numbers. I was thinking about storing them into an array, but I can not figure it out.
num = 1
last = 100
while (num <= last)
condition = true
x = 2
while (x <= num / 2)
if (num % x == 0)
condition = false
break
end
x = x + 1
end
primes = [] # Here
if condition
puts num.to_s
primes << num.to_s # Here
end
num = num + 1
end
puts primes.inject(:+) # Here
Based on what I understood from what you guys are saying I added these lines (the ones commented # Here). It still does not print the sum of them. What I meant with getting rid of 1 is that I know that 1 is not considered a prime number, and I do not get how to make it without 1. Thank you very much guys for your time and answers, and please understand that I am just starting to study this.
If you want to add a list of numbers together you can use the following:
list_of_prime_numbers.inject(0) {|total,prime| total + prime}
This will take the list of numbers, and add them one by one to an accumulator (total) that was injected into the loop (.inject(0)), add it to the current number (prime) and then return the total which then becomes the value of total in the next iteration.
I'm not quite sure what you mean by:
I don't know how to get rid of 1
but if you mean to not use the first number (which is 1 in a list of primes starting from 0)
then you could do:
list_of_prime_numbers[1...list_of_prime_numbers.length].
inject(0) {|total,prime| total + prime}
Which would only get all the numbers except the first up to but not including the length of the array
and as for getting the number into the array you could push it into the array like so:
list_of_prime_numbers << prime_number
You can make use of Prime Enumerable in ruby
require 'prime'
((1..100).select { |number| Prime.prime?(number) }).inject(:+)
OR
Prime.each(100).inject(:+)
Hope this helps.

Sort Integer Array Ruby

Have the function PermutationStep (num) take the num parameter being passed and return the next number greater than num using the same digits. For example: if num is 123 return 132, if it's 12453 return 12534. If a number has no greater permutations, return -1 (ie. 999)
Here's my code. I'd like to sort an array of large integers in numerical order. Using the regular sort method doesn't give the right order for some numbers. Is there a sort_by structure that I can replace 'sort' with in my code below?
def PermutationStep(num)
num = num.to_s.split('').map {|i| i.to_i}
permutations = num.permutation.to_a.sort #<= I want to sort by numerical value here
permutations.each_with_index do |n, idx|
if n == num
if n == permutations[-1]
return -1
else
return permutations[idx+1].join.to_i
end
end
end
end
For example, 11121. When I run the code it gives me 11121.I want the next highest permutation, which should be 12111.
Also, when I try { |a,b| b <=> a }, I also get errors.
You can pass a block to sort.
num.permutation.to_a.sort { |x, y| x.to_i <=> y.to_i }
This SO thread may be of some assistance: How does Array#sort work when a block is passed?
num.permutation.to_a is an array of arrays, not an array of integers, which causes the result not what you expected.
Actually you don't need to sort since you only need the minimum integer that is bigger than the input.
def PermutationStep(num)
nums = num.to_s.split('')
permutations = nums.permutation.map{|a| a.join.to_i}
permutations.keep_if{|n| n > num}.min || -1
end
puts PermutationStep(11121) # 11211
puts PermutationStep(999) # -1
Call to_i before your sort the permutations. Once that is done, sort the array an pick the first element greater than your number:
def PermutationStep(num)
numbers = num.to_s.split('')
permutations = numbers.permutation.map { |p| p.join.to_i }.sort
permutations.detect { |p| p > num } || -1
end
You don't need to consider permutations of digits to obtain the next higher number.
Consider the number 126531.
Going from right to left, we look for the first decrease in the digits. That would be 2 < 6. Clearly we cannot obtain a higher number by permuting only the digits after the 2, but we can obtain a higher number merely by swapping 2 and 6. This will not be the next higher number, however.
We therefore look for the smallest digit to the right of 2 that is greater than 2, which would be 3. Clearly, the next higher number will begin 13 and will have the remaining digits ordered smallest to largest. Therefore, the next higher number will be 131256.
You can easily see that the next higher number for 123 is 132, and for 12453 is 12534.
The proof that procedure is correct is easily established by induction, first showing that it is correct for numbers with two digits, then assuming it is correct for numbers with n>=2 digits, showing it is correct for numbers with n+1 digits.
It can be easily implemented in code:
def next_highest(n)
a = n.to_s.reverse.split('').map(&:to_i)
last = -Float::INFINITY
x,ndx = a.each_with_index.find { |d,i| res = d<last; last=d; res }
return nil unless x
swap_val = a[ndx]
swap_ndx = (0...ndx).select { |i| a[i] > swap_val }.min_by{ |i| a[i] }
a[ndx], a[swap_ndx] = a[swap_ndx], swap_val
a[0...ndx] = a[0...ndx].sort.reverse
a.join.reverse
end
next_highest(126531) #=> "131256"
next_highest(109876543210) #=> "110023456789"

Prime factoring returns nil when fed primes

I made a method that generates prime factors. Whatever composite number I push to it, it gives the prime factors. However, if I push a prime number into it, it wouldn't return 1 and the number itself. Instead, it would return 1 and some prime number smaller than the number pushed into the method.
I decided to shove an if statement that would cut the process short if the number pushed into turns out to be prime. Here's the code:
def get_prime_factors(number)
prime_factors = []
i = 0
primes = primes_gen(number)
if primes.include?(number)
return "Already a prime!"
end
original_number = number
while primes[i] <= original_number / 2
if number % primes[i] == 0
prime_factors << primes[i]
number = number / primes[i]
else
i = i + 1
end
if number == 1
return prime_factors
end
end
end
I fed 101 to the method and the method returned nil. This method calls the primes_gen method, which returns an array containing all primes smaller than the input value. Here it is:
def primes_gen(limit)
primes = []
i = 0
while i <= limit
primes << i if isprime?(i)
i = i + 1
end
primes.delete(0)
primes.delete(1)
return primes
end
I know there ought to be a more finessed way to fix the. If anyone wants to recommend a direction for me to explore as far as that goes, I'd be very grateful.
EDIT: Changed line 4 of the primes_gen() method to include a <= operator instead of a < operator.
Try changing primes = primes_gen(number) to primes = primes_gen(number+1) in first function and see if it works. Or try changing the i < limit condition to i <= limit in the second function.
Also, why are you deleting the 0th and 1st element in primes_gen method? Is it because of values you get for 0, 1? In which case, you can initialize with i=2.

Calculate missing number

Here's the exercise:
You have been given a list of sequential numbers from 1 to 10,000, but
they are all out of order; furthermore, a single number is missing
from the list. The object of the task is to find out which number is
missing.
The strategy to this problem is to sum the elements in the array, then sum the range 1 to 10,000, and subtract the difference. This is equal to the missing number. The formula for calculating the sum of the range from 1..n being n(n+1)/2.
This is my current approach:
def missing_number(array)
sum = 0
array.each do |element|
sum += element
end
((10000*10001)/2) - sum
end
Where I am getting tripped up is the output when I input an array such as this:
puts missing_number(*1..10000) #=> 0
Why does this happen?
Thanks!
No need to sort the array. An array of length N is supposed to have all but one of the numbers 1..(N+1) so the array length + 1 is the basis for figuring out what the grand_sum would be if all values were there.
def missing_number(array)
grand_sum = (array.length + 1) * (array.length + 2) / 2
grand_sum - array.inject(:+)
end
ADDENDUM
This method takes an array as an argument, not a range. You can't use a range directly because there wouldn't be a missing value. Before calling the method you need some mechanism for generating an array which meets the problem description. Here's one possible solution:
PROBLEM_SIZE = 10_000
# Create an array corresponding to the range
test_array = (1..PROBLEM_SIZE).to_a
# Target a random value for deletion -- rand(N) generates values in
# the range 0..N-1, inclusive, so add 1 to shift the range to 1..N
target_value = rand(PROBLEM_SIZE) + 1
# Delete the value and print so we can check the algorithm
printf "Deleting %d from the array\n", test_array.delete(target_value)
# Randomize the order of remaining values, as per original problem description
test_array.shuffle!
# See what the missing_number() method identifies as the missing number
printf "Algorithm identified %d as the deleted value\n", \
missing_number(test_array)
An alternative approach to solving the problem if it's not performance critical, because of its readability:
def missing_number(array)
(1..10_000).to_a - array
end
Instead of *1..10000, the argument should be (1..10000).to_a.
You shouldn't be using *1..10000, this will just expand to 10,000 arguments. (1..10000).to_a will return zero because there are no elements missing between 1..10000 you need to remove one. Below is some code with a detailed explanation.
def missing_number array
# put elements in order
array.sort!
# get value of last array element
last = array[-1]
# compute the expected total of the numbers
# 1 - last
# (n + 1)(n)/2
expected = (last + 1) * (last / 2)
# actual sum
actual = array.inject{|sum,x| sum + x}
# find missing number by subtracting
(expected - actual)
end
test = (1..10000).to_a
test.delete 45
puts "Missing number is: #{missing_number(test)}"

optimize this ruby code

So this code will count the total number of pairs of numbers whose difference is K. it is naive method and I need to optimize it. suggestions?
test = $stdin.readlines
input = test[0].split(" ")
numbers = test[1].split(" ")
N = input[0]
K = input[1]
count = 0
for i in numbers
current = i.to_i
numbers.shift
for j in numbers
difference = (j.to_i - current).abs
if (difference == K)
count += 1
end
end
end
puts count
Would have been nice for you to give some examples of input and output, but I think this is correct.
require 'set'
def count_diff(numbers, difference)
set = Set.new numbers
set.inject 0 do |count, num|
set.include?(num+difference) ? count+1 : count
end
end
difference = gets.split[1].to_i
numbers = gets.split.map { |num| num.to_i }
puts count_diff(numbers, difference)
Untested, hopefully actual Ruby code
Documentation for Set: http://www.ruby-doc.org/stdlib/libdoc/set/rdoc/classes/Set.html
require 'set'
numbers_set = Set.new
npairs = 0
numbers.each do |number|
if numbers_set.include?(number + K)
npairs += 1
end
if numbers_set.include?(number - K)
npairs += 1
end
numbers_set.add(number)
end
Someone deleted his post, or his post was deleted... He had the best solution, here it is :
test = $stdin.readlines
input = test[0].split(" ")
numbers = test[1].split(" ")
K = input[1]
count = 0
numbers.combination(2){|couple| couple.inject(:-).abs == K ? count++}
puts count
You don't even need N.
I do not know Ruby so I'll just give you the big idea:
Get the list
Keep a boolean array (call it arr), marking off numbers as true if the number exists in the list
Loop through the list and see if arr[num-K] and/or arr[num+K] is true where num is a number in your list
This uses up quite a bit of memory though so another method is to do the following:
Keep a hash map from an integer n to an integer count
Go through your list, adding num+K and num-K to the hash map, incrementing count accordingly
Go through your list and see if num is in the hash map. If it is, increment your counter by count

Resources