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)
}
}
Related
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
}
private def reverseHelper(word: String): String = {
var result = new StringBuilder(word)
if (word.head.isUpper) {
result.setCharAt(0, word.head.toLower)
result.setCharAt(word.length - 1, word.last.toUpper)
}
result.reverse.result()
}
val formatString = str
.split("[.,!?: ]+")
.map(result => str.replaceFirst(result, reverseHelper(result)))
.foreach(println)
Example:
Input: What is a sentence?
Ouput: Tahw si a ecnetnes?
but i have Array[String]: Tahw is a sentence?, What si a sentence?, What is a sentence?, What is a ecnetnes?
How i can write this in right format?
Restoring the original capitalization is a bit tricky.
def reverser(s:Seq[Char], idx:Int = 0) :String = {
val strt = s.indexWhere(_.isLetter, idx)
if (strt < 0) s.mkString
else {
val end = s.indexWhere(!_.isLetter, strt)
val len = end - strt
val rev = Range(0,len).map{ x =>
if (s(strt+x).isUpper) s(end-1-x).toUpper
else s(end-1-x).toLower
}
reverser(s.patch(strt,rev,len), end)
}
}
testing:
reverser( "What, is A sEntence?")
//res0: String = Tahw, si A eCnetnes?
You can first split your string at a list of special characters and then reverse each individual word and store it in a temporary string. After that traverse the original string and temporary string and replace word matching any special characters with current character in temporary string.
private def reverseHelper(word: String): String = {
var result = new StringBuilder(word)
if (word.head.isUpper) {
result.setCharAt(0, word.head.toLower)
result.setCharAt(word.length - 1, word.last.toUpper)
}
result.reverse.result()
}
val tempStr = str
.split("[.,!?: ]+")
.map(result => reverseHelper(result))
.mkString("")
val sList = "[.,!?: ]+".toList
var curr = 0
val formatString = str.map(c => {
if(!sList.contains(c)) {
curr = curr + 1
tempStr(curr-1)
}
else c
})
Here's one approach that uses a Regex pattern to generate a list of paired strings of Seq(word, nonWord), followed by reversal and positional uppercasing of the word strings:
def reverseWords(s: String): String = {
val pattern = """(\w+)(\W*)""".r
pattern.findAllMatchIn(s).flatMap(_.subgroups).grouped(2).
map{ case Seq(word, nonWord) =>
val caseList = word.map(_.isUpper)
val newWord = (word.reverse zip caseList).map{
case (c, true) => c.toUpper
case (c, false) => c.toLower
}.mkString
newWord + nonWord
}.
mkString
}
reverseWords("He likes McDonald's burgers. I prefer In-and-Out's.")
//res1: String = "Eh sekil DlAnodcm's sregrub. I referp Ni-dna-Tuo's."
A version using split on word boundaries:
def reverseWords(string: String): String = {
def revCap(s: String): String =
s.headOption match {
case Some(c) if c.isUpper =>
(c.toLower +: s.drop(1)).reverse.capitalize
case Some(c) if c.isLower =>
s.reverse
case _ => s
}
string
.split("\\b")
.map(revCap)
.mkString("")
}
I want to split function argument list by arguments.
An argument can be a function invocation like:
foo(...)
or any sequence of character. For instance:
"fisrt_arg, some_foo(arg1, foo2(arg1, arg2, foo3()), arg3), third_arg"
I want to get:
List("first_arg", "some_foo(arg1, foo2(arg1, arg2, foo3())", "third_arg")
I implemented it as follows (DEMO):
private[this] def tokenizeArgumentList(argumentListExpression: String): List[String] = {
var functionInvokationCounter = 0
var previousArgumentPosition = 0
var arguments: List[String] = List()
for (i <- 0 until argumentListExpression.length)
argumentListExpression.charAt(i) match {
case '(' => functionInvokationCounter += 1
case ')' =>
if (functionInvokationCounter == 0)
0
else
functionInvokationCounter -= 1
case ',' if functionInvokationCounter == 0 =>
arguments :+= argumentListExpression.substring(previousArgumentPosition, i).trim
previousArgumentPosition = i + 1
case _ =>
}
arguments :+= argumentListExpression.substring(previousArgumentPosition).trim
arguments
}
It works, but looks ugly. 3 mutable variables and what I don't like most is this:
arguments :+= argumentListExpression.substring(previousArgumentPosition).trim
arguments
After iteration through the argumentListExpression's is done we have to attach the last argument.
Can we refactor it in more functional way? Maybe foldLeft would help...?
Recursion is divine. See - not a single var:
val s = "fisrt_arg, some_foo(arg1, foo2(arg1, arg2, foo3()), arg3), third_arg"
def tokenize (argumentlist: String): List[String] = {
def tokenize (arglist: List[Char], sofar: String, inList: Int): List[String] = arglist match {
case Nil => List (sofar)
case '(' :: tail => tokenize (tail, sofar + '(', inList + 1)
case ')' :: tail => tokenize (tail, sofar + ')', inList - 1)
case ',' :: tail => if (inList > 0) {
tokenize (tail, sofar + ',', inList)
} else {
sofar :: tokenize (tail, "", inList)
}
case c :: tail => tokenize (tail, sofar + c, inList)
}
tokenize (argumentlist.toList, "", 0)
}
tokenize (s)
The inList counts, how deep we are in the list.
If we woulnd't pass just the sofar-String, but the List-so-far too, we could make it tail-recursive, but it doesn't smell as if it might step too deep into functions with function as parameters, having functions as parameters, ...
Pitfall:
val s = "\"stringliteral w. (misleading brace\", f(a, b(c, d, e()), f), g"
You might like to apply some trimming in the end:
scala> val res = tokenize (s)
res: List[String] = List(fisrt_arg, " some_foo(arg1, foo2(arg1, arg2, foo3()), arg3)", " third_arg")
scala> res.mkString ("<", "><", ">")
res372: String = <fisrt_arg>< some_foo(arg1, foo2(arg1, arg2, foo3()), arg3)>< third_arg>
Indeed, foldLeft is a possibility. It helps us removing mutable variables (which we try to avoid in Scala):
val string =
"fisrt_arg, some_foo(arg1, foo2(arg1, arg2, foo3()), arg3), third_arg"
val result = (string :+ ',')
// The accumulator of foldLeft is a tuple (previous splits,
// current split, nbr of opened parentheses)
.foldLeft(List[String](), List[Char](), 0) {
// Opening of parenthesis (might be the first opening or not) =>
// increment nbr of opened parentheses to stop splitting:
case ((splits, currSplit, openPar), '(') =>
(splits, '(' :: currSplit, openPar + 1)
// Closing of parenthesis (might bring us back to 0, in which case
// we can start splitting again):
case ((splits, currSplit, openPar), ')') =>
(splits, ')' :: currSplit, openPar - 1)
// ',' (split char) and if the nbr of opened parentheses is 0 =>
// we can split!
case ((splits, currSplit, 0), ',') =>
(currSplit.reverse.mkString :: splits, Nil, 0)
// In any other case, we just add the new char to the current split:
case ((splits, currSplit, openPar), char) =>
(splits, char :: currSplit, openPar)
}
._1
.reverse
result.foreach(println)
which returns
List("fisrt_arg", "some_foo(arg1, foo2(arg1, arg2, foo3())", "arg3"))
foldLeft will traverse a sequence (in our case a List[Char]) to process each Char individually to fill an "accumulator" (List[String] to be returned).
Notice the initialization (string :+ ',') which allows us to also include the last split into the list of splits. Otherwise, at the end of foldLeft, we would have the last split in the second item (List[Char]) of the accumulator tuple instead of it being included in the first (List[String]).
My idea works out to be essentially the same as the other answer, except operating on the "word" level. I do not know that I am a fan of modifying the last element of the list in this way--the idea of carrying a "current split" would be an alternative.
val result = string
.split(",")
.foldLeft((0, List[String]())) {
case ((0, l), term) =>
(term.count(_ == '(') - term.count(_ == ')'), (term :: l))
case ((openCount, l), term) =>
val finalElt = l.head
(
openCount + term.count(_ == '(') - term.count(_ == ')'),
List(finalElt, term).mkString(",") :: l.tail)
}
._2
.reverse
How can I convert a string in Scala into a corresponding operator?
Given two integers and the string "+" I want the result of adding these two integers.
The last question is very simple:
def applyOperator(x: Int, y: Int, operator: String) = operator match {
case "+" => x + y
case "-" => x - y
...
}
You could try using Twitter's Eval library or reflection, but I wouldn't recommend it given the simpler solution.
For the first question: operators themselves aren't values, so you can't "convert a string into an operator". But you can come close: convert a string into a function which will add (or subtract, etc.) its arguments:
def stringToOperator(operator: String): (Int, Int) => Int = operator match {
case "+" => _ + _
case "-" => _ - _
...
}
You can even generalize it a bit to work not just on integers:
def stringToOperator[A: Numeric](operator: String): (A, A) => A = operator match { ... }
(This also applies to the first answer in the obvious way.)
This one
case class Evaluatee(v1: Int, operator: String, v2: Int)
object Evaluator {
def raw(s: String)(v1: Int, v2: Int) = s match {
case "+" => (v1 + v2)
case "-" => (v1 - v2)
case "*" => (v1 * v2)
case "/" => (v1 / v2)
}
def evaluate(evaluatee: Evaluatee) =
raw(evaluatee.operator)(evaluatee.v1, evaluatee.v2)
}
accomplishes this tests:
test("1+1=2"){
assert(Evaluator.evaluate(Evaluatee(1, "+", 1)) == 2)
}
test("2-1=1"){
assert(Evaluator.evaluate(Evaluatee(2, "-", 1)) == 1)
}
test("1+1=2 raw"){
assert(Evaluator.raw("+")(1,1) == 2)
}
We cannot just do something like 1 "+" 2 because I think the biggest feature of scala to can make an own DSL is the apply method but I can not just calling it with nothing, I'm pretty sure we always need to use () or {} for example List(1) we can't do List 1 but we can List{1}.
But try this maybe could work for you
case class NumOp (num1:Int){
def apply(op:String)(num2:Int):Int = {
op match {
case "+" => num1+num2
case "-" => num1-num2
case _ => 0
}
}
}
object ConvertsNumOp{
implicit def convert(a:Int):NumOp= NumOp(a)
}
import ConvertsNumOp._
scala> 2 ("-") (1)
res0: Int = 1
scala> 4 ("-") (2)
res1: Int = 2
scala> 4 ("+") (2)
res2: Int = 6
scala> 4 ("-") (2) ("+") (1) ("-") (8)
res0: Int = -5
You can do things dynamically so maybe could works.
EDITED:
Here is another version of NumOp maybe cleanest
case class NumOp(num1:Int) {
def apply(op:String):Int => Int = {
op match {
case "+" => num1.+_
case "-" => num1.-_
case _ => throw new NotImplementedError("Operator not implemented")
}
}
}
Using it dynamically
val numList = List(1,2,3,4,5,6,7,8,9,10);
val optList = List("+","-");
var retVal = for{ a <- numList; op <- optList }
yield (a)(op)(a)
I'm trying to read some worksheets using a filter, but the problem is that I can't get the cell values, when those cells are using cells
$objReader = PHPExcel_IOFactory::createReader('Excel5');
$objReader->setLoadSheetsOnly('Data Sheet #1');
$myFilter = new CellReadFilter(1, 7, range('A', 'F'));
$objReader->setReadDataOnly(true);
$objReader->setReadFilter($myFilter);
$objPHPExcel = $objReader->load('sampleData/example1.xls');
$loadedSheetNames = $objPHPExcel->getSheetNames();
foreach ($loadedSheetNames as $sheetIndex => $loadedSheetName) {
echo $sheetIndex, ' => ', $loadedSheetName, '<br />';
$sheetData = $objPHPExcel->getActiveSheet()->toArray(null,true,true,true);
var_dump($sheetData);
}
My excel file, on the F1 cell, I use the following formula: =C2, but the output of my script says that F1 is null and not 23.45 as expected.
0 => Data Sheet #1
array (size=3)
1 =>
array (size=6)
'A' => string 'Integer Numbers' (length=15)
'B' => float 123
'C' => float 234
'D' => float -345
'E' => float 456
'F' => null
2 =>
array (size=6)
'A' => string 'Floating Point Numbers' (length=22)
'B' => float 1.23
'C' => float 23.45
'D' => float 3.45E-6
'E' => float -45.678
'F' => float 56.78
3 =>
array (size=6)
'A' => string 'Strings' (length=7)
'B' => string 'Hello' (length=5)
'C' => string 'World' (length=5)
'D' => null
'E' => string 'PHPExcel' (length=8)
'F' => null
and my cell filter class looks like in the documentation sample:
class CellReadFilter implements PHPExcel_Reader_IReadFilter {
private $_startRow = 0;
private $_endRow = 0;
private $_column = array();
public function __construct($startRow, $endRow, $column) {
$this->_startRow = $startRow;
$this->_endRow = $endRow;
$this->_column = array_merge($column, array('AA'));
}
public function readCell($column, $row, $worksheetName = '') {
if ($row >= $this->_startRow && $row <= $this->_endRow) {
if (in_array($column, $this->_column)) { return true; }
}
return false;
}
}
Validation for you read filter, modify the readCell to test what criteria are being applied, and to identify which cells match the criteria and why they are being accepted/rejected:
public function readCell($column, $row, $worksheetName = '') {
echo 'Testing worksheet ', $worksheetName, 'row ', $row, ' column ', $column, PHP_EOL;
if ($row >= $this->_startRow && $row <= $this->_endRow) {
'Cell is within row range',PHP_EOL;
if (in_array($column, $this->_column)) {
'VALID: Cell is within column range',PHP_EOL;
return true;
}
'INVALID: Cell is outside column range',PHP_EOL;
} else {
'INVALID: Cell is outside row range',PHP_EOL;
}
return false;
}