need repeat(x,char) function to build a string

Monkey Forums/Monkey Programming/need repeat(x,char) function to build a string

c.k.(Posted 2012) [#1]
I want to create a string of '*' that is the same length as another string (to cover a password). What's the best way to do that?


ziggy(Posted 2012) [#2]
Create an integer array of value "*"[0] and then call to String.Frombytes function.
[monkeycode]Function Main()
Print "Chain of 10: " + Chain(10)
End

Function Chain:String(Num:Int)
Local ints:=New Int[Num]
For Local i=0 until ints.Length
ints[i] = "*"[0] 'Believe it or not, "*"[0] is an integer.
Next
Return String.FromChars(ints)
End[/monkeycode]


c.k.(Posted 2012) [#3]
I'll post the solution I created before ziggy responded... :-)

Function pwstring:String(pw:String)
	Local c:String = ""
	Local i:Int = pw.Length()
	For Local t:Int = 1 to i
		c = c + "*"
	Next
	Return c
End

'called like
cPW1 = pwstring( myString ) ' returns a string of '*' with length of myString
cPW2 = pwstring( "howdy" ) ' returns '*****'


ziggy, can you explain your code? The reasoning, etc... Thank you! :-)


ziggy(Posted 2012) [#4]
Not bad, but in your implementation, you're creating a new string at every For loop, and this will have a deep performance impact on long strings.


c.k.(Posted 2012) [#5]
Where's the new string getting created?


Shinkiro1(Posted 2012) [#6]
In your for loop.
[monkeycode]c = c + "*"[/monkeycode]
Returns a new string every time.


ziggy(Posted 2012) [#7]
ziggy, can you explain your code? The reasoning, etc... Thank you! :-)

Yes: A string is just an array of integers, where every integer represents a char, so, in order to avoid creating a new string on every loop iteration (wich is very CPU intensive) I thought it would be a good idea to have a single-time mem allocation of the space required for the new string, and just modify each character (without allocating additional datal, or adding work to do to the garbage collector.

The explanation;

This is just the function declaration
[monkeycode]Function Chain:String(Num:Int)[/monkeycode]
Now, we make an string integer array with as many elements as char we want to repesent:
[monkeycode] Local ints:=New Int[Num][/monkeycode]
Then we set a loop in order to initialize each array element:
[monkeycode] For Local i=0 until ints.Length[/monkeycode]
In each loop operation, we set the corresponding item in the integer array with its character number. When you add [0] to any string, you get the integer numerical representation of the first character of the string, so doing "*"[0] just get converted in compile time to the integer value that represents the * character.
[monkeycode] ints[i] = "*"[0] 'Believe it or not, "*"[0] is an integer.
Next[/monkeycode]
Then, all we have to do is read this array as a string, and return it. this may "create" the string object as Monkey does not allow you to directly return the same integer array as an string, even when they're internally the same. There must be a good reason for this... ?
[monkeycode] Return String.FromChars(ints)
End[/monkeycode]
Just hope it's useful to any newbie.


Gerry Quinn(Posted 2012) [#8]
On the other hand, if you're covering a password you're on user interface time, and efficiency doesn't matter.


ziggy(Posted 2012) [#9]
Well, it depends on how many function calls there are. In fact, when using a not strong typed target such as JavaScript or ActionScript, the pre-allocation of the string does not avoid a final concatenation calculation on the String.FromChars function, due to the limits of the target languages (I've tried alternative implementations for the FromChars method on JavaScript, with no better results). So, in this particular situation your implementation could be a bit faster.
On a test I've done, your implementation took 150 millisecs on on JavaScript compared to 500 on my implementation, wich that means yours is 75% faster on JavaScript. Surprisingly the same code runing on glfw was giving 85 millisecs on my implementation, and 2600 on yours, wich means that yours is 3058% slower. you can see the huge difference there.
This big difference is caused by the String.FromChars function call. I think this should have a better implementation on JavaScript, but I'm not sure this is possible given the nature of JavaScript.


Gerry Quinn(Posted 2012) [#10]
Just as a matter of interest: how long was the string on your test?


ziggy(Posted 2012) [#11]
It was like 20-30 chars but it was a loop of more than a million calls or the like. I haven't kept the source, but feel free to make your own test.