Beginner's question

I’m just starting to learn Ruby (started two days ago), and something
came up in a practice problem that I just can’t figure out (I tried
debugging to pinpoint the error to no avail). I am experiencing
unexpected behavior when defining new_string = string instead of
new_string = “”. The variable “string” changes along with “new_string”
when I do so, even though there is nothing I can see in the code that
should cause this to happen. (When I define new_string = “”, the
original variable, “string”, doesn’t change as the loop proceeds.) Can
anyone explain what’s going on here?

Problem/my program:

Write a method that takes in a string and an array of indices in the

string. Produce a new string, which contains letters from the input

string in the order specified by the indices of the array of indices.

Difficulty: medium.

def scramble_string(string, positions)
new_string = string
#new_string = “” <-- this fixes the problem
i = 0
while i < string.length
x = positions[i]
new_string[i] = string[x]
#I used these lines for attempted debugging
#puts(positions[i])
#puts(string)
#puts(new_string)
i = i + 1
end
return new_string
end

These are tests to check that your code is working. After writing

your solution, they should all print true.

puts(
'scramble_string(“abcd”, [3, 1, 2, 0]) == “dbca”: ’ +
(scramble_string(“abcd”, [3, 1, 2, 0]) == “dbca”).to_s
)

puts(
'scramble_string(“markov”, [5, 3, 1, 4, 2, 0]) == “vkaorm”): ’ +
(scramble_string(“markov”, [5, 3, 1, 4, 2, 0]) == “vkaorm”).to_s
)

Thor Reinhold wrote in post #1172302:

I am experiencing
unexpected behavior when defining new_string = string instead of
new_string = “”. The variable “string” changes along with “new_string”

new_string= string # new_string and string points to same data
new_string= string.clone # new_string point to a copy of string data
new_string= string+"" # + makea new string whih is pointer by b

Your code seem as C code translate to ruby…
Here an other solution :

def scramble_string(string, positions)
string.size.times.each_with_object(string.clone) { |pos,dst|
dst[pos]= string[positions[pos] || pos]
}
end

p scramble_string(“markov”, [5, 3, 1, 4, 2, 0])
p scramble_string("", [0])
p scramble_string(“abc”, [])

or
def scramble_string(string, positions)
positions.each_with_index.
each_with_object(string.clone) { |(val,pos),dst|
dst[pos]= string[val] || dst[pos] if pos<string.size
}
end

Thanks for your reply, Regis. I think I understand–if I globally define
new_string as equal to string, then that means when changes to one
occur, then it changes the other too?

I have some experience with C, but I’m just starting to learn Ruby. So
that probably explains why my solution looks like it does. :slight_smile: Once I
learn more about Ruby and know more of the powerful methods that are
available, hopefully I’ll be able to come up with the kind of compact
and elegant solutions you’ve suggested.