Add spacing between digits and non digits - swift

Hi guys I have a probelm that I needed to solve. Here are the examples:
input is ABCD12345 will output ABCD 12345
input is A12345BCDE will output A 12345 BCDE
imput is ABC 12345 will output ABC 12345 (excess spacing removed)
As shown above a single spacing shall be added when there are no spacing but if there is, it will check if there are double spaces, then it will make it into single spacing.

To accomplish what you ask you can do something like this:
let letters = NSCharacterSet.letterCharacterSet()
let digits = NSCharacterSet.decimalDigitCharacterSet()
var res = ""
var lastDigit = false
for char in [input].unicodeScalars {
if letters.longCharacterIsMember(char.value) && lastDigit {
res += " "
lastDigit = false
} else if digits.longCharacterIsMember(char.value) && !lastDigit {
res += " "
lastDigit = true
}
if String(char) != " " {
res += String(char)
}
}
print(res)
In the code above you should replace the [input] placeholder with the input that you want to deal and the result string will be in res variable.

Related

How to truncate a comma-separated value string with remainder count

I'm trying to achieve string truncate with "& more..." when string is truncated. I have this in picture:
Exact code minus text, in image:
func formatString() -> String {
let combinedLength = 30
// This array will never be empty
let strings = ["Update my profile", "Delete me", "Approve these letters"]
// In most cases, during a loop (no order of strings)
//let strings = ["Update", "Delete", "Another long word"]
let rangeNum = strings.count > 1 ? 2 : 1
let firstN = strings[0..<rangeNum]
// A sum of first 2 or 1
let actualLength = firstN.compactMap { $0.count }.reduce(0, +)
switch actualLength {
case let x where x <= combinedLength:
// It's safe to display all
return strings.map{String($0)}.joined(separator: ", ")
default:
if rangeNum == 2 {
if actualLength <= combinedLength {
return strings.first! + ", " + strings[1] + ", & \(strings.count - 2) more..."
}
return strings.first! + ", & \(strings.count - 1) more..."
}
// There has to be at least one item in the array.
return strings.first!
}
}
While truncateMode looks like a match, it's missing the , & n more... where n is the remainder.
My code may not be perfect but was wondering how to refactor. I feel there's a bug in there somewhere. I've not taken into consideration for larger screens: iPad where I would want to display more comma-separated values, I only look for the max 2 then display "& n more" depending on the size of the array.
Is there a hidden modifier for this? I'm using XCode 13.4.1, targeting both iPhone and iPad.
Edit:
The title is incorrect. I want to convert an array of strings into a comma-separated value string that's truncated using the function I have.

I have a string and a number. I need to find the first sub-string that contain the same characters with the length of the number

For example:
number= 3
my_string= "gghhsstttevvv"
The output:
"ttt"
*if the number was 2, the output is: "gg"
The below script will give you the desired output :
number = input("Enter Number")
string = input("Enter String")
count = dict.fromkeys(string,0)
for i in string:
count[i] += 1
#print(count)
occurences = count.values()
#print(occurences)
result = [k for k,v in count.items() if v == int(number)]
if not result:
print("No matching substring of length " +number+ " found")
else:
print(result) # To print all the characters with the given count
print(result[0]) # To print the first character with the given count
output_char = result[0]
frequency = count[output_char]
output_char = output_char*frequency
print(output_char)
Output:
python3 string.py
Enter Number5
Enter Stringgghhsstttevvv
No matching substring of length 5 found
python3 string.py
Enter Number3
Enter Stringgghhsstttevvv
['t', 'v']
t
ttt

Swift split substring based on word wrap

junior developer here. I am currently trying to achieve a substring that is split every n characters of a String.
This is my code for the function
public func split(every: Int) -> [String] {
var result = [String]()
for i in stride(from: 0, to: self.count, by: every) {
let startIndex = self.index(self.startIndex, offsetBy: i)
let endIndex = self.index(startIndex, offsetBy: every, limitedBy: self.endIndex) ?? self.endIndex
result.append(String(self[startIndex..<endIndex]))
}
return result
}
The above code works as expected. But there is one lacking from the code above, which is the word wrapping. Here is the sample String
let itemName = "Japanese Matcha SM w RB -L Special Edition And Americano MS w Brown Sugar Limited Edition"
print(itemName.split(every: 26))
The result will be
["Japanese Matcha SM w RB -L", " Special Edition And Ameri", "cano MS w Brown Sugar Limi", "ted Edition"]
Notice the
[" Special Edition And Ameri"], ["cano MS w Brown Sugar Limi"]
I am trying to figure out how to do the word wrap algorithm based on every n character, but couldn't find any clue.
For example, from above case, how to generate the array becomes,
[" Special Edition And"], ["Americano MS w Brown"], ["Sugar"]
So as you can see, the algorithm might check whether every n characters has a word that is being cut out (dynamic check based on the n characters), hence will move the cut word into the next array.
So in that case, the algorithm will cleverly bypass the every n character, might be less, but not more than n characters, if there is any word not being wrapped.
Is my explanation clear? Can anyone guide me please? Thanks
This is some simple implementation of this algorithm, you can start with that.
First we cut string by words, then add them to temporary string until we meet characters limit.
let itemName = "Japanese Matcha SM w RB -L Special Edition And Americano MS w Brown Sugar Limited Edition"
let table = itemName.split(separator: " ")
let limit = 26
var tempString = ""
var finalResult: [String] = []
for item in table {
tempString += item + " "
if tempString.count >= limit {
finalResult.append(tempString)
tempString = ""
}
}
print(finalResult)
How about this?
extension String {
func split(every: Int) -> [String] {
var result = [String]()
let words = self.split(separator: " ")
var line = String(words.first!)
words.dropFirst().forEach { word in
let word = " " + String(word)
if line.count + word.count <= every {
line.append(word)
} else {
result.append(line)
line = word
}
}
result.append(line)
return result
}
}

Difficulty getting readLine() to work as desired on HackerRank

I'm attempting to submit the HackerRank Day 6 Challenge for 30 Days of Code.
I'm able to complete the task without issue in an Xcode Playground, however HackerRank's site says there is no output from my method. I encountered an issue yesterday due to browser flakiness, but cleaning caches, switching from Safari to Chrome, etc. don't seem to resolve the issue I'm encountering here. I think my problem lies in inputString.
Task
Given a string, S, of length N that is indexed from 0 to N-1, print its even-indexed and odd-indexed characters as 2 space-separated strings on a single line (see the Sample below for more detail).
Input Format
The first line contains an integer, (the number of test cases).
Each line of the subsequent lines contain a String, .
Constraints
1 <= T <= 10
2 <= length of S < 10,000
Output Format
For each String (where 0 <= j <= T-1), print S's even-indexed characters, followed by a space, followed by S's odd-indexed characters.
This is the code I'm submitting:
import Foundation
let inputString = readLine()!
func tweakString(string: String) {
// split string into an array of lines based on char set
var lineArray = string.components(separatedBy: .newlines)
// extract the number of test cases
let testCases = Int(lineArray[0])
// remove the first line containing the number of unit tests
lineArray.remove(at: 0)
/*
Satisfy constraints specified in the task
*/
guard lineArray.count >= 1 && lineArray.count <= 10 && testCases == lineArray.count else { return }
for line in lineArray {
switch line.characters.count {
// to match constraint specified in the task
case 2...10000:
let characterArray = Array(line.characters)
let evenCharacters = characterArray.enumerated().filter({$0.0 % 2 == 0}).map({$0.1})
let oddCharacters = characterArray.enumerated().filter({$0.0 % 2 == 1}).map({$0.1})
print(String(evenCharacters) + " " + String(oddCharacters))
default:
break
}
}
}
tweakString(string: inputString)
I think my issue lies the inputString. I'm taking it "as-is" and formatting it within my method. I've found solutions for Day 6, but I can't seem to find any current ones in Swift.
Thank you for reading. I welcome thoughts on how to get this thing to pass.
readLine() reads a single line from standard input, which
means that your inputString contains only the first line from
the input data. You have to call readLine() in a loop to get
the remaining input data.
So your program could look like this:
func tweakString(string: String) -> String {
// For a single input string, compute the output string according to the challenge rules ...
return result
}
let N = Int(readLine()!)! // Number of test cases
// For each test case:
for _ in 1...N {
let input = readLine()!
let output = tweakString(string: input)
print(output)
}
(The forced unwraps are acceptable here because the format of
the input data is documented in the challenge description.)
Hi Adrian you should call readLine()! every row . Here an example answer for that challenge;
import Foundation
func letsReview(str:String){
var evenCharacters = ""
var oddCharacters = ""
var index = 0
for char in str.characters{
if index % 2 == 0 {
evenCharacters += String(char)
}
else{
oddCharacters += String(char)
}
index += 1
}
print (evenCharacters + " " + oddCharacters)
}
let rowCount = Int(readLine()!)!
for _ in 0..<rowCount {
letsReview(str:String(readLine()!)!)
}

Coffeescript memoization?

I have a function that displays a number as a properly formatted price (in USD).
var showPrice = (function() {
var commaRe = /([^,$])(\d{3})\b/;
return function(price) {
var formatted = (price < 0 ? "-" : "") + "$" + Math.abs(Number(price)).toFixed(2);
while (commaRe.test(formatted)) {
formatted = formatted.replace(commaRe, "$1,$2");
}
return formatted;
}
})();
From what I've been told, repeatedly used regexes should be stored in a variable so they are compiled only once. Assuming that's still true, how should this code be rewritten in Coffeescript?
This is the equivalent in CoffeeScript
showPrice = do ->
commaRe = /([^,$])(\d{3})\b/
(price) ->
formatted = (if price < 0 then "-" else "") + "$" + Math.abs(Number price).toFixed(2)
while commaRe.test(formatted)
formatted = formatted.replace commaRe, "$1,$2"
formatted
You can translate your JavaScript code into CoffeeScript using js2coffee. For given code the result is:
showPrice = (->
commaRe = /([^,$])(\d{3})\b/
(price) ->
formatted = ((if price < 0 then "-" else "")) + "$" + Math.abs(Number(price)).toFixed(2)
formatted = formatted.replace(commaRe, "$1,$2") while commaRe.test(formatted)
formatted
)()
My own version is:
showPrice = do ->
commaRe = /([^,$])(\d{3})\b/
(price) ->
formatted = (if price < 0 then '-' else '') + '$' +
Math.abs(Number price).toFixed(2)
while commaRe.test formatted
formatted = formatted.replace commaRe, '$1,$2'
formatted
As for repeatedly used regexes, I don't know.