问题
Convert String in this way
let initialString = "atttbcdddd"
// result must be like this "at3bcd4"
But repetition must be more than 2. For example, if we have "aa" the result will be "aa", but if we have "aaa", the result will be "a3"
One more example:
let str = "aahhhgggg"
//result "aah3g4"
My try:
func encrypt(_ str: String) -> String {
let char = str.components(separatedBy: "t") //must input the character
var count = char.count - 1
var string = ""
string.append("t\(count)")
return string
}
if i input "ttttt" it will return "t5" but i should input the character
回答1:
What you are looking for is the “Run-length encoding”. Note that this is not an encryption!
Here is a possible implementation (explanations inline):
func runLengthEncode(_ str: String) -> String {
var result = ""
var pos = str.startIndex // Start index of current run
while pos != str.endIndex {
let char = str[pos]
// Find index of next run (or `endIndex` if there is none):
let next = str[pos...].firstIndex(where: { $0 != char }) ?? str.endIndex
// Compute the length of the current run:
let length = str.distance(from: pos, to: next)
// Append compressed output to the result:
result.append(length <= 2 ? String(repeating: char, count: length) : "\(char)\(length)")
pos = next // ... and continue with next run
}
return result
}
Examples:
print(runLengthEncode("atttbcdddd")) // at3bcd4
print(runLengthEncode("aahhhgggg")) // aah3g4
print(runLengthEncode("abbbaaa")) // ab3a3
回答2:
Checkout this :
func convertString(_ input : String) -> String {
let allElements = Array(input)
let uniqueElements = Array(NSOrderedSet(array: allElements)) as! [Character]
var outputString = ""
for uniqueChar in uniqueElements {
var count = 0
for char in allElements {
if char == uniqueChar {
count+=1
}
}
if count > 2 {
outputString += "\(uniqueChar)\(count)"
} else if count == 2 {
outputString += "\(uniqueChar)\(uniqueChar)"
} else {
outputString += "\(uniqueChar)"
}
}
return outputString
}
Input : convertString("atttbcdddd")
Output : at3bcd4
回答3:
I've tried it before for one of the interview and also I think you too :). However, very simple way to do it is just go through step by step of code.
let initialString = "atttbcdddd"
var previousChar: Character = " "
var output = ""
var i = 1 // Used to count the repeated charaters
var counter = 0 // To check the last character has been reached
//Going through each character
for char in initialString {
//Increase the characters counter to check the last element has been reached. If it is, add the character to output.
counter += 1
if previousChar == char { i += 1 }
else {
output = output + (i == 1 ? "\(previousChar)" : "\(previousChar)\(i)")
i = 1
}
if initialString.count == counter {
output = output + (i == 1 ? "\(previousChar)" : "\(previousChar)\(i)")
}
previousChar = char
}
let finalOutput = output.trimmingCharacters(in: .whitespacesAndNewlines)
print(finalOutput)
回答4:
let initialString = "atttbcdddd"
let myInitialString = initialString + " "
var currentLetter: Character = " "
var currentCount = 1
var answer = ""
for (_, char) in myInitialString.enumerated(){
if char == currentLetter {
currentCount += 1
} else {
if currentCount > 1 {
answer += String(currentCount)
}
answer += String(char)
currentCount = 1
currentLetter = char
}
}
print(answer)
回答5:
Use reduce here.
func exp(_ s : String, _ term: String) -> String{ //term_inator: Any Char not in the Sequence.
guard let first = s.first else {return ""}
return """
\(s.dropFirst().appending(term).reduce(("\(first)",1)){ r, c in
let t = c == r.0.last!
let tc = t ? r.1 : 0
let tb = t ? "" : "\(c)"
let ta = t ? "" : r.1 > 2 ? "\(r.1)" : r.1 == 2 ? "\(r.0.last!)" : ""
return (r.0 + ta + tb, tc + 1)
}.0.dropLast())
"""}
print(exp(initialString, " "))
let initialString = "abbbaaa" // ab3a3
let initialString = "aahhhgggg" // aah3g4
let initialString = "aabbaa" // aabbaa
来源:https://stackoverflow.com/questions/54766558/task-from-the-interview-how-we-would-solve-it