Ruby : unexpected ',', expecting '.' or &. or :: or '[' - ruby

I'm currently trying to implement a mathematic method to approximate
f(x) = 0. I've already implemented it in some languages and I want to do it in ruby now just for training.
But I have this error that I really does'nt understand
Here is my code
def fonction (x)
return (x ** 3) + 4 * (x ** 2) - 10
end
def derive (x)
return 3 * (x ** 2) + 8 * x
end
def newton(f, fPrime, n, u0)
if n == 0 then
return u0
else
uN = newton (f, fPrime, (n - 1), u0)
return uN - f(uN) / fPrime(uN)
end
end
for i in 0..6
puts (newton (fonction, derive, i, 2))
end

i think there is space on newton method call
uN = newton (f, fPrime, (n - 1), u0) # there is space after newton
also in this one
for i in 0..6
puts (newton (fonction, derive, i, 2)) # there is space after newton
end
try remove it, and you will see another error i guess, i try it on repl

Related

Recursion for raising a number to a power

I have this code:
def power(x, n)
if n == 1
return x
else
x = x * power(x, n-1)
end
end
power(4, 4)
power(2, 3)
power(10, 3)
power(25, 2)
power(6, 5)
It takes the first number and raises it to the 2nd numberth power. So it works for all of them, but I want to write the code in a way that it prints the results for all 5 of the power functions. How do I do this? I tried to modify with puts instead of return but I cannot get it to work.
You have a variable x which points to the result of the method call. You can print this and then return it from the function:
def power(x, n)
if n == 1
return x
else
x = x * power(x, n-1)
puts x
x
end
end

Rounding some numbers, and converting some to int

I made a method that takes two numbers and returns a calculated value rounded to three decimals. I'm curious to know how I can have numbers such as 1.141 to be rounded but numbers like 5.0 turned into integers (5).
code:
def calculateHypotenuse(a,b)
if (a <= 0 || b <= 0)
return raise
end
c = Math.sqrt((a * a) + (b * b))
return c.round(3)
end
not sure there is a built in function for floats, but a hackish way could be something like this.
def conditional_truncation(x)
x.truncate == x ? x.truncate : x
end
conditional_truncation(1.141)
=> 1.141
conditional_truncation(5.0)
=> 5

Can't get factorial function to work

Factorial 1 and 2 works but 3 and 4 do not. I've worked the steps out on paper and do not see why they do not work. Any help is much appreciated.
def factorial(n)
x = 1
y = n
while x < n
n = n * (y-x)
x = x + 1
end
return n
end
puts("factorial(1) == 1: #{factorial(1) == 1}")
puts("factorial(2) == 2: #{factorial(2) == 2}")
puts("factorial(3) == 6: #{factorial(3) == 6}")
puts("factorial(4) == 24: #{factorial(4) == 24}")
The reason it's not working is that after each loop the value of n gets bigger and the condition x < n keeps executing until it hits a point where n becomes zero. If you pass 3 to the function on the third loop you will have:
while x(3) < n(6)
n(6) = n(6) * (y(3) - x(3))
end
therefore n becomes 0 causing the loop to exit on the next round and the return value is obviously 0. To fix it you just need to replace n with y in the while condition:
while x < y
As a side note just another interesting way you could solve the factorial problem using recursion is:
def factorial(n)
n <= 1 ? 1 : n * factorial(n - 1)
end
Try this:
def factorial(n)
if n < 0
return nil
end
x = 1
while n > 0
x = x * n
n -= 1
end
return x
end

Can this check digit method be refactored?

I have the following method for doing a check digit on a tracking number, but it just feels lengthy/sloppy. Can it be refactored and just generally cleaned up?
I'm running Ruby 1.8.7.
def is_fedex(number)
n = number.reverse[0..14]
check_digit = n.first.to_i
even_numbers = n[1..1].to_i + n[3..3].to_i + n[5..5].to_i + n[7..7].to_i + n[9..9].to_i + n[11..11].to_i + n[13..13].to_i
even_numbers = even_numbers * 3
odd_numbers = n[2..2].to_i + n[4..4].to_i + n[6..6].to_i + n[8..8].to_i + n[10..10].to_i + n[12..12].to_i + n[14..14].to_i
total = even_numbers + odd_numbers
multiple_of_ten = total + 10 - (total % 10)
remainder = multiple_of_ten - total
if remainder == check_digit
true
else
false
end
end
EDIT: Here are valid and invalid numbers.
Valid: 9612019950078574025848
Invalid: 9612019950078574025847
def is_fedex(number)
total = (7..20).inject(0) {|sum, i| sum + number[i..i].to_i * ( i.odd? ? 1 : 3 ) }
number[-1].to_i == (total / 10.0).ceil * 10 - total
end
I believe you should keep your code. While it's not idiomatic or clever, it's the one you will have the least trouble to understand a few months from now.
I'm not a ruby programmer, so if any of the syntax is off, I apologize but you should get the general idea. A few things I see: First, you don't need to slice the array, a single index should be sufficient. Second, Instead of splitting even and odd, you could do something like this:
total = 0
for i in (1..14)
total += n[i].to_i * ( i % 2 == 1 ? 1 : 3 )
end
Third, remainder could be simplified to 10 - (total % 10).
I realize you're running 1.8.7, but here's my attempt using each_slice and inject in conjunction, a 1.9.2 feature:
def is_fedex(number)
total = number.reverse[1..14].split(//).map(&:to_i).each_slice(2).inject(0) do |t, (e,o)|
t += e*3 + o
end
10 - (total % 10) == number[-1].to_i
end
It passes both tests
Give this a try:
#assuming number comes in as a string
def is_fedex(number)
n = number.reverse[0..14].scan(/./)
check_digit = n[0].to_i
total = 0
n[1..14].each_with_index {|d,i| total += d.to_i * (i.even? ? 3 : 1) }
check_digit == 10 - (total % 10)
end
> is_fedex("12345678901231") => true
edit incorporating simplified remainder logic as Kevin suggested
Something like this?
def is_fedex(number)
even_arr, odd_arr = number.to_s[1..13].split(//).map(&:to_i).partition.with_index { |n, i| i.even? }
total = even_arr.inject(:+) * 3 + odd_arr.inject(:+)
number.to_s.reverse[0..0].to_i == (total + 10 - (total % 10)) - total
end
If you can give me a valid and invalid number I can test if it works and maybe tweak it further :)
This function should to:
def is_fedex(number)
# sanity check
return false unless number.length == 15
data = number[0..13].reverse
check_digit = number[14..14].to_i
total = (0..data.length-1).inject(0) do |total, i|
total += data[i..i].to_i * 3**((i+1)%2)
end
(10 - total % 10) == check_digit
end
The arithmetic expression 3**((i+1)%2) might look a bit complex, but is essentially the same as (i.odd? ? 1 : 3). Both variants are correct, which you use is up to you (and might affect speed...)
Also note, that if you use Ruby 1.9, you can use data[i] instead of data[i..i] which is required for for Ruby 1.8.

Bit interleaving optimized for Ruby

Granted, optimizing bit twiddling in Ruby is a bit of a mismatch to begin with. That aside, I'm looking for a snippet or a gem that can interleave two arbitrary integer coords optimized as best can be for MRI (1.9) or a native gem.
Some approaches in C are: http://graphics.stanford.edu/~seander/bithacks.html#InterleaveTableObvious
As an example or starting point, here's "Interleave bits the obvious way" in Ruby, somewhat uglified to keep it from creating temp arrays (which increase the runtime by about 2X per array) and with a binary length method inlined for a further 6% decrease (If you know neither input is ever zero, you can omit that check for a few percent more..)
def interleave(y)
z = 0
bl = self > 0 ? Math.log2(self) : 1
ybl = y > 0 ? Math.log2(y) : 1
((((bl <=> ybl) == -1) ? ybl : bl).floor + 1).times{|i| z |= (self & 1 << i) << i | (y & 1 << i) << (i + 1)}
return z
end
Results from a 2.66Ghz i5 with 1.9.2p180:
x = y = 0b11111111_11111111_11111111_11111111
Benchmark.bm{|bm| bm.report{1000000.times{x.interleave(y)}}}
user system total real
18.360000 0.010000 18.370000 ( 18.356196)
Surely there's a better way?
Update
I included the zero fix from #Wayne Conrad, albeit far uglier than his and only marginally faster. Also moved the floor and + 1 so as to be executed once instead of twice per.
Here is a Gist of this with matching de-interleave.
Here's a quick & cheesy implementation to get you going until a good one comes along:
def mortanize(x, y)
xs, ys = [x, y].map do |n|
n.to_s(2)
end
nbits = [xs, ys].map(&:size).max
xs, ys = [xs, ys].map do |n|
('0' * (nbits - n.size) + n).chars
end
ys.zip(xs).join.to_i(2)
end
As you might expect, it's no speed deamon. On my box, with MRI 1.8.7, it computes about 35,000 16-bit results per second. Yours computes 68,000 16-bit results per second. Or, see the next algorithm for 256,000 16-bit results per second.
If you're willing to trade a little memory and startup time for speed, then:
def base_mortanize(x, y)
xs, ys = [x, y].map do |n|
n.to_s(2)
end
nbits = [xs, ys].map(&:size).max
xs, ys = [xs, ys].map do |n|
('0' * (nbits - n.size) + n).chars
end
ys.zip(xs).join.to_i(2)
end
MORTON_TABLE_X = 256.times.map do |x|
base_mortanize(x, 0)
end
MORTON_TABLE_Y = 256.times.map do |y|
base_mortanize(0, y)
end
def mortanize(x, y)
z = []
while (x > 0 || y > 0)
z << (MORTON_TABLE_X[x & 0xff] | MORTON_TABLE_Y[y & 0xff])
x >>= 8
y >>= 8
end
z.reverse.inject(0) do |result, word|
result << 16 | word
end
end
This one computes 256,000 16-bit results per second.
There's a bug in your answer if either argument is zero. Here's one possible fix for it. First define this function:
def bit_size(x)
return 1 if x == 0
Math.log2(x).floor + 1
end
And then, inside interleave, replace:
z, bl, ybl = 0, (Math.log2(self)).floor + 1, (Math.log2(y)).floor + 1
with:
z = 0
bl = bit_size(x)
ybl = bit_size(y)
Here is the rspec test case I used:
describe "mortanize" do
it "should interleave integers" do
mortanize(0, 0).should eql 0
mortanize(0, 1).should eql 2
mortanize(1, 0).should eql 1
mortanize(0xf, 0x3).should eql 0x5f
mortanize(0x3, 0xf).should eql 0xaf
mortanize(0xf, 0x0).should eql 0x55
mortanize(0x0, 0xf).should eql 0xaa
mortanize(0x3, 0xc).should eql 0xa5
mortanize(0xf, 0xf).should eql 0xff
mortanize(0x1234, 0x4321).should eql 0x210e0d12
end
end
Here's another solution, benchmarked about 50% faster than the accepted one, and for 16-bit integers (where the first one only does 8-bit):
Magic = [0x55555555, 0x33333333, 0x0F0F0F0F, 0x00FF00FF]
# Interleave lower 16 bits of x and y, so the bits of x
# are in the even positions and bits from y in the odd;
# z gets the resulting 32-bit Morton Number.
# x and y must initially be less than 65536.
# Rubyfied from http://graphics.stanford.edu/~seander/bithacks.html
def _interleave_bits_16b(x,y)
x = (x | (x << 8)) & Magic[3]
x = (x | (x << 4)) & Magic[2]
x = (x | (x << 2)) & Magic[1]
x = (x | (x << 1)) & Magic[0]
y = (y | (y << 8)) & Magic[3]
y = (y | (y << 4)) & Magic[2]
y = (y | (y << 2)) & Magic[1]
y = (y | (y << 1)) & Magic[0]
z = x | (y << 1)
end
If you have an implementation already in C, you can use FFI, otherwise you can write it directly with the help of RubyInline

Resources