Shuffling a string in Swift - swapping a location not supported [duplicate] - string

This question already has an answer here:
fatal error: swapping a location with itself is not supported with Swift 2.0
(1 answer)
Closed 7 years ago.
I have this code to shuffle a string in swift. For some reason it is giving an error in Xcode 7.1 "swapping a location with itself is not supported. I thought it was working ok. Any ideas where I have gone wrong much appreciated!
let selectedWord = word1 // word1 is a string
var chars = Array(selectedWord.characters)
chars.shuffleString()
let shuffledWord = String(chars)
word1 = shuffledWord
extension Array {
mutating func shuffleString() {
for index in 0..<(count - 1) {
let j = Int(arc4random_uniform(UInt32(count - index))) + index
swap(&self[index], &self[j]) // error on this line saying 'swapping a location with itself is not supported'

The swap function changed in a recent version of Xcode to prevent swapping a variable with itself. You can add a guard statement just before your swap to make sure index and j aren't the same:
extension Array {
mutating func shuffleString() {
for index in 0..<(count - 1) {
let j = Int(arc4random_uniform(UInt32(count - index))) + index
guard i != j else { continue }
swap(&self[index], &self[j])
}
}
}

Related

NumberFormatException in Kotlin

I was solving a question on CodeChef. A specific line to take input like:
10 232 4543
I was willing to store it in variables and then perform the calculation.
The following is the line of code I am using to achieve this.
val (d,l,r) = readLine()!!.split(" ").map{ it -> it.toInt()}
This line worked for previous question but is not working for the current question. I am inserting my code and the link to the question.
fun main(){
var t = readLine()!!.toInt()
for(i in 0 until t){
val (d,l,r) = readLine()!!.split(" ").map{ it -> it.toInt()}
if(d<l){
println("Too Early")
}
else if(d>r){
println("Too Late")
}
else{
println("Take second dose now")
}
}
}
This is the link to the question: https://www.codechef.com/LP1TO201/problems/VDATES
The following is the error I am receiving.
Exception in thread "main" java.lang.NumberFormatException: For input string: ""
at java.base/java.lang.NumberFormatException.forInputString(NumberFormatException.java:67)
at java.base/java.lang.Integer.parseInt(Integer.java:678)
at java.base/java.lang.Integer.parseInt(Integer.java:786)
at ProgKt.main(prog.kt:4)
at ProgKt.main(prog.kt)
An empty string is not a number. There are two easy ways to solve this:
Filter empty strings using isEmpty():
val (d,l,r) = readLine()!!.split(" ").filterNot { it.isEmpty() }.map { it -> it.toInt() }
Use toIntOrNull() and only take non-null elements:
val (d,l,r) = readLine()!!.split(" ").mapNotNull { it -> it.toIntOrNull() }

Determine if the integer is one digit and add a zero before it [duplicate]

This question already has answers here:
Leading zeros for Int in Swift
(12 answers)
Closed 7 years ago.
I need to check if the int is only one digit and if it is, I want to add a zero in front of it. I have this code but it doesnt work.
var minutes2 = Int(minutes)
var minutessize: Int = sizeofValue(minutes2)
if minutessize < 2 {
var needStringHere = "0\(minutes2)"
let a: Int? = needStringHere.toInt()
minutes2 = a!
}
You can just check if the minutes count is less than 10:
var str = "\(minutes2)"
if (minutes2 < 10) { str = "0\(minutes2)" }

Error handling in Swift non-optional-valued functions [duplicate]

This question already has an answer here:
Trim end off of string in swift, getting error at runtime
(1 answer)
Closed 7 years ago.
Trying to get to grips with Swift programming, I wrote the following:
var s : String = "dog"
var i1 : String.Index = advance(s.startIndex, 2)
var t1 : String = s.substringToIndex(i1)
Executing this code in a playground, t1 has the value "do", as expected. However, if I try to construct an index that exceeds the string's length, this happens:
var s : String = "dog"
var i2 : String.Index = advance(s.startIndex, 4)
var t2 : String = s.substringToIndex(i2)
This time, the line var i2 ... shows the error
Execution was interrupted, reason: EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP,subcode=0x0).
I read the Swift documentation, but the entry for String.substringToIndex reads in its entirety:
func substringToIndex(index: String.Index) -> String
[Foundation]
Returns a new string containing the characters of the String up to, but not including, the one at a given index.
The result is not optional, nor does the function possess an error parameter or return an empty string in case of faulty arguments.
I don't know how to prevent this by not creating an index in the first place, because String does not have a length or count property.
Since Swift does not have exception handling, how can programs recover from errors like this?
This is on OS X 10.10.2, Xcode 6.2.
The error is in advance(s.startIndex, 4) as you cannot advance eyond the end index:
1> var s = "dog"
s: String = "dog"
2> var i1 = advance(s.startIndex, 4)
fatal error: can not increment endIndex
i1: String.Index = {
_base = { /* ... */ }
/* ... */
}
Execution interrupted. Enter Swift code to recover and continue.
Enter LLDB commands to investigate (type :help for assistance.)
You avoid this by providing an end index as:
3> var i1 = advance(s.startIndex, 4, s.endIndex)
i1: String.Index = {
_base = { /* ... */ }
/* ... */
}
and then:
4> s.substringToIndex(i1)
$R0: String = "dog"
at least for Swift1.2, in Xcode6-Beta3.

Remove nth character from string

I have seen many methods for removing the last character from a string. Is there however a way to remove any old character based on its index?
Here is a safe Swift 4 implementation.
var s = "Hello, I must be going"
var n = 5
if let index = s.index(s.startIndex, offsetBy: n, limitedBy: s.endIndex) {
s.remove(at: index)
print(s) // prints "Hello I must be going"
} else {
print("\(n) is out of range")
}
While string indices aren't random-access and aren't numbers, you can advance them by a number in order to access the nth character:
var s = "Hello, I must be going"
s.removeAtIndex(advance(s.startIndex, 5))
println(s) // prints "Hello I must be going"
Of course, you should always check the string is at least 5 in length before doing this!
edit: as #MartinR points out, you can use the with-end-index version of advance to avoid the risk of running past the end:
let index = advance(s.startIndex, 5, s.endIndex)
if index != s.endIndex { s.removeAtIndex(index) }
As ever, optionals are your friend:
// find returns index of first match,
// as an optional with nil for no match
if let idx = s.characters.index(of:",") {
// this will only be executed if non-nil,
// idx will be the unwrapped result of find
s.removeAtIndex(idx)
}
Swift 3.2
let str = "hello"
let position = 2
let subStr = str.prefix(upTo: str.index(str.startIndex, offsetBy: position)) + str.suffix(from: str.index(str.startIndex, offsetBy: (position + 1)))
print(subStr)
"helo"
var hello = "hello world!"
Let's say we want to remove the "w". (It's at the 6th index position.)
First: Create an Index for that position. (I'm making the return type Index explicit; it's not required).
let index:Index = hello.startIndex.advancedBy(6)
Second: Call removeAtIndex() and pass it our just-made index. (Notice it returns the character in question)
let choppedChar:Character = hello.removeAtIndex(index)
print(hello) // prints hello orld!
print(choppedChar) // prints w

interview riddle (string manipulation) - explanation needed

i am studying for an interview and encountered a question + solution.
i am having a problem with one line in the solution and was hoping maybe someone here can explain it.
the question:
Write a method to replace all spaces in a string with ‘%20’.
the solution:
public static void ReplaceFun(char[] str, int length) {
int spaceCount = 0, newLength, i = 0;
for (i = 0; i < length; i++) {
if (str[i] == ‘ ‘) {
spaceCount++;
}
}
newLength = length + spaceCount * 2;
str[newLength] = ‘\0’;
for (i = length - 1; i >= 0; i--) {
if (str[i] == ‘ ‘) {
str[newLength - 1] = ‘0’;
str[newLength - 2] = ‘2’;
str[newLength - 3] = ‘%’;
newLength = newLength - 3;
} else {
str[newLength - 1] = str[i];
newLength = newLength - 1;
}
}
}
my problem is with line number 9. how can he just set str[newLength] to '\0'? or in other words, how can he take over the needed amount of memory without allocating it first or something like that?
isn't he running over a memory?!
Assuming this is actually meant to be in C (private static is not valid C or C++), they can't, as it's written. They're never allocating a new str which will be long enough to hold the old string plus the %20 expansion.
I suspect there's an additional part to the question, which is that str is already long enough to hold the expanded %20 data, and that length is the length of the string in str, not counting the zero terminator.
This is valid code, but it's not good code. You are completely correct in your assessment that we are overwriting the bounds of the initial str[]. This could cause some rather unwanted side-effects depending on what was being overwritten.

Resources