String permutations using recursion - algorithm

For example if I have a string {a, b, c}. I need to print out on the console all the permutations without repeating letters from 1 letter to 3 letters like this:
a b c ab ac abc acb ba bc bac bca ca cb cab cba
How can I write this using recursion?

If you need all the permutations of the chars into a String you can use a recursive function.
Here's the code in Swift.
func visit(unused:[Character], used: [Character] = [Character]()) -> [String] {
var result = [String(used)]
for (index, char) in unused.enumerate() {
var unused = unused
unused.removeAtIndex(index)
var used = used
used.append(char)
result = result + visit(unused, used: used)
}
return result
}
As you can see the function receives 2 params:
unused: represents the list of chars not yet used
used: the chars used to build possible element of the ouput. This parameter is optional so if it's not passed to the function, an empty array is used (this is useful for the first invocation).
Test
let word = "abc"
let chars = [Character](word.characters)
print(visit(chars))
["", "a", "ab", "abc", "ac", "acb", "b", "ba", "bac", "bc", "bca", "c", "ca", "cab", "cb", "cba"]
Omitting the empty String
This results also contains the empty String but you can easily omit this value just update the function as shown below.
func visit(unused:[Character], used: [Character] = [Character]()) -> [String] {
var result = [String]()
if !used.isEmpty {
result.append(String(used))
}
for (index, char) in unused.enumerate() {
var unused = unused
unused.removeAtIndex(index)
var used = used
used.append(char)
result = result + visit(unused, used: used)
}
return result
}

Related

Swift 1.2, capture character from a word

My problem is how to get character from a word
The result I needed is
DisplayChar("asd",1)
and it will display "a"
func DisplayChar(word : String, number : Int) -> String{
let i: Int = count(word)
var result = 0
result = i - (i - number)
var str = ""
var j = 0
for j = 0; j < result; j++ {
str = str + word[j]
}
return str
}
DisplayChar("xyz", 2)
This code should work
let sentence = "Hello world"
let characters = Array(sentence)
print(characters[0]) // "H"
There are a couple good solutions in this answer that may work, two good ones duplicated below.
Convert to Array
let word = "test"
var firstChar = Array(word)[0] // t
(Note: this assumes a UTF8 or ASCII encoded string, but that is likely fine for school.)
Create Your Own Extension
First an extension of String to handle subscripts:
extension String {
subscript (i: Int) -> Character {
return self[self.startIndex.advancedBy(i)]
}
subscript (i: Int) -> String {
return String(self[i] as Character)
}
subscript (r: Range<Int>) -> String {
let start = startIndex.advancedBy(r.startIndex)
let end = start.advancedBy(r.endIndex - r.startIndex)
return self[Range(start ..< end)]
}
}
Then you can just use:
let word = "test"
var firstChar = word[0] // t
Swift strings have a method called substringToIndex, "asd".substringToIndex(1) will return "a".
I'm not sure if it works on Swift 1.2, though.

What's the closest I can get to discriminating an enum by a char?

I've written this question out many times, and have finally realized that my biggest problem is that I don't know how I want to represent this data, and that's making it really hard to reason about the rest of the code.
The way the data is represented in Python:
class LSP():
C_MASK_MAP={
"A":"Ch A",
"B":"Ch B",
"C":"Ch C",
"D":"Ch D",
"T":"Tmpr",
"Y":"Batt",
"L":"Acc"
}
ADC_CHANS= (
"Ch A",
"Ch B",
"Ch C",
"Ch D",
"Tmpr",
"Batt"
)
ADC_MAJORS = (
"Ch A",
"Ch B",
"Ch C",
)
My imaginary Rust code (I realize the names will need updating but are the same here for clarity):
enum C_MASK_MAP {
Ch_A = 'A',
Ch_B = 'B',
Ch_C = 'C',
Ch_D = 'D',
Tmpr = 'T',
Batt = 'Y',
Acc = 'L'
}
//...
let ADC_CHANS = [
C_MASK_MAP::Ch_A,
C_MASK_MAP::Ch_B,
C_MASK_MAP::Ch_C,
C_MASK_MAP::Ch_D,
C_MASK_MAP::Tmpr,
C_MASK_MAP::Batt
];
ADC_MAJORS = [
C_MASK_MAP::Ch_A,
C_MASK_MAP::Ch_B,
C_MASK_MAP::Ch_C,
];
I've considered making C_MASK_MAP a HashMap<char, &'static str>, but then I ran into a huge mess trying not to make a million copies of the strs everywhere and dealing with lifetimes while avoiding making Strings, and the syntactic mess that is a reference to a static str (&&'static str or something).
I think there'd be a real benefit to being able to use an enum (or similar) because the values wouldn't be as big and are more easily interchanged C_MASK_MAP.get(key).expect("invalid key") vs just casting.
Your strings are sentinel values; this is a common pattern in Python, but is not how things should be done in Rust: enums are what such things should be: you’re encoding the legal values in the type system.
You could end up with something like this:
#[derive(Clone, Copy)]
#[repr(u8)]
pub enum Mask {
ChA = b'A',
ChB = b'B',
ChC = b'C',
ChD = b'D',
Tmpr = b'T',
Batt = b'Y',
Acc = b'L',
}
// e.g. Mask::ChA.into() == 'A'
impl Into<char> for Mask {
fn into(self) -> char {
self as u8 as char
}
}
impl Mask {
// e.g. Mask::from('A') == Ok(Mask::ChA)
pub fn from(c: char) -> Result<Mask, ()> {
match c {
'A' => Ok(Mask::ChA),
'B' => Ok(Mask::ChB),
'C' => Ok(Mask::ChC),
'D' => Ok(Mask::ChD),
'T' => Ok(Mask::Tmpr),
'Y' => Ok(Mask::Batt),
'L' => Ok(Mask::Acc),
_ => Err(()),
}
}
// e.g. Mask::ChA.is_chan() == true
pub fn is_chan(&self) -> bool {
match *self {
Mask::ChA | Mask::ChB | Mask::ChC | Mask::ChD | Mask::Tmpr | Mask::Batt => true,
Mask::Acc => false,
}
}
// e.g. Mask::ChD.is_major() == false
pub fn is_major(&self) -> bool {
match *self {
Mask::ChA | Mask::ChB | Mask::ChC => true,
Mask::ChD | Mask::Tmpr | Mask::Batt | Mask::Acc => false,
}
}
}
If you wanted you could implement std::str::FromStr for Mask as well, which would allow "A".parse() == Ok(Mask::ChA):
impl FromStr for Mask {
type Err = ();
fn from_str(s: &str) -> Result<Mask, ()> {
match s {
"A" => Ok(Mask::ChA),
"B" => Ok(Mask::ChB),
"C" => Ok(Mask::ChC),
"D" => Ok(Mask::ChD),
"T" => Ok(Mask::Tmpr),
"Y" => Ok(Mask::Batt),
"L" => Ok(Mask::Acc),
_ => Err(()),
}
}
}
I suspect that is_chan et al. may be more suitable than ADC_CHANS et al., but if you do actually need them, they work fine (you could do [Mask; 6] too, but if you need to add new elements it’d change the type which is an API compatibility break if public):
pub static ADC_CHANS: &'static [Mask] = &[
Mask::ChA,
Mask::ChB,
Mask::ChC,
Mask::ChD,
Mask::Tmpr,
Mask::Batt,
];
pub static ADC_MAJORS: &'static [Mask] = &[
Mask::ChA,
Mask::ChB,
Mask::ChC,
];
Copying a &'static str (i.e. copying the reference only) has no cost. A deep copy of the string would be a clone and would be typed as a String.
If &'static str is too verbose for you, you can always define a type alias.
type Str = &'static str;
HashMap<char, &'static str> corresponds nicely to your original map. However, if you don't need the full range of char for the key and you don't actually need to have the value typed as a char anywhere besides indexing the map, you should use an enum instead, as that will restrict the legal values that can be used as keys.

sorted function in Swift 2

I'm sorting an Array like this:
var users = ["John", "Matt", "Mary", "Dani", "Steve"]
func back (s1:String, s2:String) -> Bool
{
return s1 > s2
}
sorted(users, back)
But I'm getting this error
'sorted' is unavailable: call the 'sort()' method on the collection
What should be the correct way to use the sort() method here?
Follow what the error message is telling you, and call sort on the collection:
users.sort(back)
Note that in Swift 2, sorted is now sort and the old sort is now sortInPlace, and both are to be called on the array itself (they were previously global functions).
Be careful, this has changed again in Swift 3, where sort is the mutating method, and sorted is the one returning a new array.
Another way to use closure is:
var numbers = [2,4,34,6,33,1,67,20]
var numbersSorted = numbers.sort( { (first, second ) -> Bool in
return first < second
})
Another way is to use closure in a simple way:
users.sort({a, b in a > b})
In swift 2.2 there are multiple ways we can use closures with sort function as follows.
Consider the array
var names:[String] = ["aaa", "ddd", "rrr", "bbb"];
The different options for sorting the array with swift closures are as added
Option 1
// In line with default closure format.
names = names.sort( { (s1: String, s2: String) -> Bool in return s1 < s2 })
print(names)
Option 2
// Omitted args types
names = names.sort( { s1, s2 in return s1 > s2 } )
print(names)
Option 3
// Omitted args types and return keyword as well
names = names.sort( { s1, s2 in s1 < s2 } )
print(names)
Option 4
// Shorthand Argument Names(with $ symbol)
// Omitted the arguments area completely.
names = names.sort( { $0 < $1 } )
print(names)
Option 5
This is the most simple way to use closure in sort function.
// With Operator Functions
names = names.sort(>)
print(names)
var array = [1, 5, 3, 2, 4]
Swift 2.3
let sortedArray = array.sort()
Swift 3.0
let sortedArray = array.sorted()

How can I concatenate strings only if they have passed a logical statement in Swift?

My challenge is twofold:
To pick individual strings from an array of similar strings, but only if a boolean test has been passed first.
"Finally" I need to concatenate any/all of the strings generated into one complete text and the entire code must be in Swift.
Illustration: A back of the envelope code for illustration of logic:
generatedText.text =
case Int1 <= 50 && Int2 == 50
return generatedParagraph1 = pick one string at RANDOM from a an array1 of strings
case Int3 =< 100
return generatedParagraph2 = pick one string at RANDOM from a an array2 of strings
case Int4 == 100
return generatedParagraph3 = pick one string at RANDOM from a an array3 of strings
...etc
default
return "Nothing to report"
and concatenate the individual generatedParagraphs
Attempt: Code picks a random element within stringArray1, 2 and 3.
Example of what the code returns:
---> "Sentence1_c.Sentence2_a.Sentence3_b."
PROBLEM: I need the code to ONLY pick an element if it has first passed a boolean. It means that the final concatenated string (concastString) could be empty, just contain one element, or several depending on how many of the bools were True. Does anyone know how to do this?
import Foundation
var stringArray1 = ["","Sentence1_a.", "Sentence1_b.", "Sentence1_c."]
var stringArray2 = ["","Sentence2_a.", "Sentence2_b.", "Sentence2_c."]
var stringArray3 = ["","Sentence3_a.", "Sentence3_b.", "Sentence3_c."]
let count1 = UInt32(stringArray1.count)-1
let count2 = UInt32(stringArray2.count)-1
let count3 = UInt32(stringArray3.count)-1
var randomNumberOne = Int(arc4random_uniform(count1))+1
var randomNumberTwo = Int(arc4random_uniform(count2))+1
var randomNumberThree = Int(arc4random_uniform(count3))+1
let concatString = stringArray1[randomNumberOne] + stringArray2[randomNumberTwo] + stringArray3[randomNumberThree]
Okay, I didn't pass a Bool, but I show concatenating three random strings from a [String]. I ran this in a playground.
import Foundation
var stringArray = [String]()
for var i = 0; i < 100; i++ {
stringArray.append("text" + "\(i)")
}
func concat (array: [String]) -> String {
let count = UInt32(stringArray.count)
let randomNumberOne = Int(arc4random_uniform(count))
let randomNumberTwo = Int(arc4random_uniform(count))
let randomNumberThree = Int(arc4random_uniform(count))
let concatString = array[randomNumberOne] + array[randomNumberTwo] + array[randomNumberThree]
return concatString
}
let finalString = concat(stringArray)

I want to store words in an array and then call one of the words

Why is it that when I store words in an array like this I can't call just on one of the words that I stored. I'll give you an example of what I mean. This is an example of a game that I am working on. I'm doing this in Playground in Xcode using Swift.
var miamiHeat = ["james", "wade", "mario", "allen", "bosh"]
var questionOne = "Can you name one player from the miami heat?"
var answerToQuestionOne = ["james", "wade", "mario", "allen", "bosh"]
func testIfCorrect(answerToQuestionOne: String) -> String {
if miamiHeat == answerToQuestionOne {
println("The answer is correct")
} else {
println("The answer is incorrect")
}
return answerToQuestionOne
}
println(testIfCorrect("James"))
The only way that it will print "The answer is correct" is if I type in all the players name into the last println code. When I type in one of the players name into the println code it returns "The answer is incorrect." I only need to enter one of the names to get the answer correct.....so how would I do that? Thank you.
You are comparing a string with an array, not checking whether the string equals any of the strings within the array.
You need to loop through all the elements in the array, and check equality for each one.
Also, here println(testIfCorrect("James")), you have an uppercase "J", whereas in the array of names it is lowercase (the comparison is case sensitive).
I have amended your code:
var miamiHeat = ["james", "wade", "mario", "allen", "bosh"]
var questionOne = "Can you name one player from the miami heat?"
var answersToQuestionOne = ["james", "wade", "mario", "allen", "bosh"]
func testIfCorrect(answerToQuestionOne: String) -> String {
var correctAnswer: Bool = false
for answer in miamiHeat {
if answer == answerToQuestionOne {
correctAnswer = true
}
}
if correctAnswer {
println("The answer is correct")
} else {
println("The answer is incorrect")
}
return answerToQuestionOne
}
println(testIfCorrect("james"))
I believe the issue is because you are comparing the entire structure miamiheat with the answerToQuestionOne. To fix this you could add a switch statement to check each of the possible values of miamiheat. This website has few examples:
https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/GuidedTour.html

Resources