def move(s: String){
if(s.equals("l")){
al()
}else if(s.equals("r")){
ar()
}else if(s.equals("u")){
au()
}else if(s.equals("d")){
ad()
} }
the code above is something I have tried but doesn't work. It should be able to get multiple strings like (lrudd) in one line and each letter equals to a function.
so if lrudd is entered the al(), ar(), au(), ad(), ad() function should be done, its a 2d game so the player should move al()- which is left, ar()- which is right, ar()- which up and ad(),twice as down is entered twice (dd)
You'll want to map() over the String in order to evaluate each Char individually.
def move(s: String) = s.map {
case 'l' => al()
case 'r' => ar()
case 'u' => au()
case 'd' => ad()
case _ => //report error
}
Related
I want to change each word that matches the synonym list randomly by another synonym or itself (to randomly keep this keyword).
I test if a string (input) contains one element of an array (words). If it's true, I want to randomly replace this with the element of this same list.
var input = "This is an amazing text blob where this word amazing is replaced by a random word from list_of_words. Isn't this amazing!";
words_synonym = ["amazing", "formidable", "great", "smart"];
// first condition --> true if "input" contain one element of "words_synonym"
input = input.toLowerCase();
console.log(words_synonym.some(word => input.includes(word)));
after, I want to replace the "element" that validated the condition with a random element of the same array (words_synonym).
But I can't select this element. I have just true or false
var random_word = words_synonym[Math.floor(Math.random() * (words_synonym.length))]
input = input.replace(element, random_word, 0)
thanks
The way you have it right now, you're checking if any of the synonyms match any of the words (via words_synonym.some(word => input.includes(word))). In order to do what you want, you'll need both the position of the target word and the new word, neither of which you have now. To do this, you'll want to break apart your nested loops.
The code words_synonym.some(word => input.includes(word)) is equivalent to:
let has_synonym = false;
for (word of words_synonym) { // this is a loop
if (input.includes(word)) { // this is also a loop
has_synonym = true;
break;
}
}
console.log(has_synonym);
So to fix your main issue, just replace includes with indexOf.
To handle the case of replacing all of the tokens, I would suggest keeping track of the token you have replaced outside of the loop, otherwise you end up replacing each token many times which may become very expensive. To do this, just keep track of your starting position outside of the loop and increment it with the end index of the replacement word. indexOf already takes a start argument for exactly this use case!
const input = "This is an amazing text blob where this word amazing is replaced by a random word from list_of_words. Isn't this amazing!";
const words_synonym = ["amazing", "formidable", "great", "smart"];
let output = input;
let start = 0; // index of the end of the last replaced token
for (word of words_synonym) {
let index = output.indexOf(word, start);
while (index >= 0) {
const new_word = words_synonym[Math.floor(Math.random() * (words_synonym.length))];
output = output.substr(0, index) + new_word + output.substr(index + word.length, output.length);
start = index + new_word.length + 1; // increment the start
index = output.indexOf(word, start);
}
}
console.log("input: ", input);
console.log("output: ", output);
You can use method find:
words_synonym.find(word => input.includes(word))
Which returns
The value of the first element in the array that satisfies the
provided testing function. Otherwise, undefined is returned.
from docs:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/find
i have modify answer of dantiston and i have include a loop in order to change all the word match "words_synonym".
But there is a problem. The program don't check all the word of "words_synonym" but only the first with indexof.
var input = "This is an amazing text blob where this word amazing is replaced by a random word from list_of_words. Isn't this amazing!";
words_synonym = ["amazing", "formidable", "great", "smart"];
let output = input;
for (word of words_synonym) {
let index = output.indexOf(word);
if (index >= 0) {
console.log(word);
var indexes = [], i = -1;
while ((i = output.indexOf(word, i+1)) != -1){
index=output.indexOf(word, i);
var new_word = words_synonym[Math.floor(Math.random() * (words_synonym.length))];
output = output.substr(0, index) + new_word + output.substr(index + word.length, output.length);
}
}
}
console.log("input: ", input);
console.log("output: ", output);
I wanna know how to ask user input for a string. For example:
when user input is asked "lruud" is entered
Enter letters: lruud
and I want it the return should be:
Left
right
up
up
down
left = l, right = r, etc.
So basically it should return the result in the order the letters are entered.
The code below is what I have tried where al() is move left, ar() is move right etc
def move(s: String) {
if(s == "l"){
al()
}else if(s == "r"){
ar()
}else if(s == "u"){
au()
}else if(s == "d"){
ad()
}
}
You can read in a string from standard input using
val s = scala.io.StdIn.readLine()
Scala implicitly considers String to be a Scala collection, in particular an IndexedSeq which means you can call standard collections methods on it such as map to transform it. For example
def move(s: Char): String = {
if (s == 'l') "left"
else if (s == 'r') "right"
else if (s == 'u') "up"
else if (s == 'd') "down"
else throw new RuntimeException("Bad input")
}
"lruud".map(move)
// res4: IndexedSeq[String] = ArraySeq(left, right, up, up, down)
Mapping over a String reads each Char in the string and passes it to the move method for transformation.
Here's one way to go about this.
val action :Map[Char,String] =
Map('d'->"down",'l'->"left",'r'->"right",'u'->"up")
.withDefault(c => s"$c?")
val moves :Seq[String] =
io.StdIn.readLine("Enter letters: ").map(c =>action(c.toLower))
println("\ndirections:\n" + moves.mkString(" ","\n ",""))
testing:
Enter letters: lLdRbu
directions:
left
left
down
right
b?
up
I want to convert each digit in a number to an int. Here is my code
for (in <- lines) {
for (c <- in) {
val ci = c.toInt
if (ci == 0) {
// do stuff
}
}
}
The result I get is the ascii code, i.e. a 1 gives 49. I'm looking for the value 1.
The answer is trivial, I know. I'm trying to pull myself up with my own bootstraps until my Scala course begins in two weeks. Any assistance gratefully accepted.
One possible solution is:
for(in <- lines) {
in.toString.map(_.asDigit).foreach { i =>
if(i == 1) {
//do stuff
}
}
}
And more compact w/ output:
lines.foreach(in => in.toString.map(_.asDigit).filter(_ == 1).foreach(i => println(s"found $i in $in.")))
If lines is already a collection of Strings, omit the .toString on in.toString.
You can have this:
val number = 123456
//convert Int to String and do transformation for each character to Digit(Int)
val digitsAsList = number.toString.map(_.asDigit)
This will result to digitizing the number. Then with that Collection, you can do anything from filtering, mapping, zipping: you can checkout the the List api on this page: http://www.scala-lang.org/api/2.11.8/#scala.collection.immutable.List
Hope that's help.
I want to make a function which compares strings.
I don't want to use equal operators (==), I want it worked only with Swift language.
First I made a function which takes 2 strings, and returns bool type.
then I looped these strings with for in syntax.
And want to compare these characters, if strings have equal value, it should return true, if not, then false. Is there any better way?
func isEqual(str1:String, str2:String) -> Bool {
var result = false
for char in str1 {
}
for char2 in str2 {
}
//Compare characters.
return result
}
== works fine with Strings in Swift. For educational purposes
(as I conclude from your comment "because I'm practicing...")
you can implement it as:
func myStringCompare(str1 : String, str2 : String) -> Bool {
if count(str1) != count(str2) {
return false
}
for (c1, c2) in zip(str1, str2) {
if c1 != c2 {
return false
}
}
return true
}
zip(str1, str2) returns a sequence of pairs from the given
sequences, this is a convenient way to enumerate the strings
"in parallel".
Once you have understood how it works, you can shorten it,
for example to:
func myStringCompare(str1 : String, str2 : String) -> Bool {
return count(str1) == count(str2) && !contains(zip(str1, str2), { $0 != $1 })
}
Comparing the string length is necessary because the zip() sequence
terminates as soon as one of the strings is exhausted. Have a look at
#drewag's answer to In Swift I would like to "join" two sequences in to a sequence of tuples
for an alternative Zip2WithNilPadding sequence.
If you don't want to use the built-in zip() function (again for
educational/self-learning purposes!) then you can use the fact
that Strings are sequences, and enumerate them in parallel using
the sequence generator. This would work not only for strings but
for arbitrary sequences, as long as the underlying elements can
be tested for equality, so let's make it a generic function:
func mySequenceCompare<S : SequenceType where S.Generator.Element : Equatable>(lseq : S, rseq : S) -> Bool {
var lgen = lseq.generate()
var rgen = rseq.generate()
// First elements (or `nil`):
var lnext = lgen.next()
var rnext = rgen.next()
while let lelem = lnext, relem = rnext {
if lelem != relem {
return false
}
// Next elements (or `nil`):
lnext = lgen.next()
rnext = rgen.next()
}
// Are both sequences exhausted?
return lnext == nil && rnext == nil
}
Tests:
mySequenceCompare("xa", "xb") // false
mySequenceCompare("xa", "xa") // true
mySequenceCompare("a", "aa") // false
mySequenceCompare("aa", "a") // false
My solution differ a little as I didn't know about the zip operator, I guess is not as efficient as the one post by Martin great use of tuple.
Great question alphonse
func isEqual(str1:String, str2:String) -> Bool {
if count(str1) != count(str2){
return false
}
for var i = 0; i < count(str1); ++i {
let idx1 = advance(str1.startIndex,i)
let idx2 = advance(str2.startIndex,i)
if str1[idx1] != str2[idx2]{
return false
}
}
return true
}
As pointed by Martin each string needs its own index, as explained by him:
"The "trick" is that "🇩🇪" is an "extended grapheme cluster" and consists of two Unicode code points, but counts as one Swift character."
Link for more details about extended grapheme cluster
I'm trying to make a string scrambler and de-scrambler in scala by replacing characters with a string, then replacing the string with the original character to de-scramble it. However, that is not possible as the map function in scala takes characters and not strings. Here is my code
object Main{
def main(args: Array[String]){
val hello = Scrambler.scramble("How about that bacon?")
println(hello)
val bye = Scrambler.deScrambler(hello)
println(bye)
}
}
object Scrambler {
def scramble(s: String) = {
s map {
//Since it takes a char and replaces with a string, everything works fine
case ' ' => "WOOPIE"
case 'a' => "fIRST"
case 'b' => "sECOND"
case 'c' => "tHIRD"
case 'd' => "fOURTH"
case 'e' => "fITH"
case 'f' => "sIXTH"
case 'g' => "sEVENTH"
case 'h' => "eIGHTH"
case 'i' => "nINTH"
case 'j' => "tENTH"
case 'k' => "eLEVENTH"
case 'l' => "tWELFTH"
case 'm' => "tHIRTEENTH"
case 'n' => "fOURTEENTH"
case 'o' => "fIFTEENTH"
case 'p' => "sIXTEENTH"
case 'q' => "sEVENTEENTH"
case 'r' => "eIGHTEENTH"
case 's' => "nINETEENTH"
case 't' => "tWENTIETH"
case 'u' => "tWENTYFIRST"
case 'v' => "tWENTYSECOND"
case 'w' => "tWENTYTHIRD"
case 'x' => "tWENTYFOURTH"
case 'y' => "tWENTYFIFTH"
case 'z' => "tWENTYSIXTH"
case 'A' => "First"
case 'B' => "Second"
case 'C' => "Third"
case 'D' => "Fourth"
case 'E' => "Fifth"
case 'F' => "Sixth"
case 'G' => "Seventh"
case 'H' => "Eighth"
case 'I' => "Ninth"
case 'J' => "Tenth"
case 'K' => "Eleventh"
case 'L' => "Twelfth"
case 'M' => "Thirteenth"
case 'N' => "Fourteenth"
case 'O' => "Fifteenth"
case 'P' => "Sixteenth"
case 'Q' => "Seventeenth"
case 'R' => "Eighteenth"
case 'S' => "Nineteenth"
case 'T' => "Twentieth"
case 'U' => "Twentyfirst"
case 'V' => "Twentysecond"
case 'W' => "Twentythird"
case 'X' => "Twentyfourth"
case 'Y' => "Twentyfifth"
}
}.mkString
def deScrambler(s: String) = {
s map {
/*Here, however, it attempts to replace 'WOOPIE' with ' '
* which is not permitted
*/
case "WOOPIE" => ' '
case "fIRST" => 'a'
}
}
}
Any suggestions on how I can do this? Perhaps I just have not been wording my searches correctly, but I cannot find a alternative
How about adding a separator after each word in the scrambler function and then splitting the string in the deScrambler function based on that separator. Here is an example:
object Main{
def main(args: Array[String]){
val hello = Scrambler.scramble("hello there !")
println(hello)
val bye = Scrambler.deScrambler(hello)
println(bye)
}
}
object Scrambler {
def scramble(s: String) = {
s map {
case ' ' => "WOOPIE"
case 'e' => "fITH"
case 'h' => "eIGHTH"
case 'l' => "tWELFTH"
case 'o' => "fIFTEENTH"
case 'r' => "eIGHTEENTH"
case 't' => "tWENTIETH"
case _ => "uKnown"
}
}.mkString("-") // add a separator between scrambled words
def deScrambler(s: String) = {
// split the string based on the separator to get back the
// the scrambled words
s.split("-") map {
case "WOOPIE" => ' '
case "fITH" => 'e'
case "eIGHTH" => 'h'
case "tWELFTH" => 'l'
case "fIFTEENTH" => 'o'
case "eIGHTEENTH" => 'r'
case "tWENTIETH" => 't'
case _ => "!"
}
}.mkString
}
Sample output looks like this:
eIGHTH-fITH-tWELFTH-tWELFTH-fIFTEENTH-WOOPIE-tWENTIETH-eIGHTH-fITH-eIGHTEENTH-fITH-WOOPIE-uKnown
hello there !
You can implement your Decramble as:
object Main {
def main(args: Array[String]) {
val hello = Scrambler.scramble("How about that bacon?")
println(hello)
val bye = Scrambler.deScrambler(hello)
println(bye)
}
}
object Scrambler {
val l = List(("WOOPIE", " "), ("fIRST", "a"), ("sECOND", "b") and so on.....)
def fd(lt: List[(String, String)], str: String): String = {
if (lt == Nil) str
else fd(lt.tail, str.replaceAll(lt.head._1, lt.head._2))
}
def deScrambler(s: String) = {
fd(l, s)
}
}