I am writing a Caesar Cipher in Scala 3, I am writing an expression/function that iterates through each character of a string. Upon each iteration each character is converted to a ascii value, shifted, then converted back to character. The function prints, however the output terminates in "()" ...
import scala.io.StdIn.readLine
var message: String = "";
var shift: Int = 1;
def encrypt(messageToDecrypt: String, shiftAmt: Int): Unit =
var msgLen = messageToDecrypt.length
var dcrytArray = messageToDecrypt.toCharArray
var i : Int = 0
var shiftedCharArray = for i <- dcrytArray do print(((i.toInt + shiftAmt - 97) % 26 + 97).toChar)
#main def CeasarCipher(args: String*): Unit =
println("enter a phrase to encrypt: ")
var message = readLine()
var encryptedmessage = encrypt(message, shift)
println(encryptedmessage)
Why is the output terminating with "( )"? and how can I resolve?
Please don't use vars, arrays, mutable structures, and procedural loops, it hurts my eyes :( If you are going to spend time learning scala, might as well learn using it in the right way.
def shift(amt: Int)(x: Char) = ((x + amt - 97)%26+97).toChar
println(encryptedMessage.map(shift(shiftAmt)))
i got it, you have to use "yield" rather than "do" in the for loop
import scala.io.StdIn.readLine
var message: String = "";
var shift: Int = 1;
def encrypt(messageToDecrypt: String, shiftAmt: Int): String =
var msgLen = messageToDecrypt.length
var dcrytArray = messageToDecrypt.toCharArray
var i : Int = 1
var shiftedCharArray = for i <- dcrytArray yield ((i.toInt + shiftAmt - 97) % 26 + 97).toChar
shiftedCharArray.mkString("")
#main def CeasarCipher(args: String*): Unit =
println("enter a phrase to encrypt: ")
var message = readLine()
var encryptedmessage = encrypt(message, shift)
println(encryptedmessage)
Related
I Have a series of tests that need to pass one of them includes deleting the buffer between the defined region (which is between the marker and cursor) and inserting the cut text in the paste. I then need to set the cursor and marker to the beginning of the cut text (see below code for a better understanding)
class Buffer(s: String) {
import scala.collection.mutable.StringBuilder
import scala.io.StdIn
private var buffer: StringBuilder = new StringBuilder(s)
private var cursor: Int = 0 // cursor is in between characters
private var marker: Int = 0 // marker is in between characters
private var paste: String = ""
private def end: Int = buffer.length // the end of the line
private def lwr: Int = Math.min(marker, cursor)
private def upr: Int = Math.max(marker, cursor)
/*
* Accessor methods to return aspects of the state
*/
def getCursor: Int = cursor
def getMarker: Int = marker
def getString: String = buffer.toString
def getPaste: String = paste
Delete the contents of the defined region and save the cut string in the paste
buffer. This operation re-sets the cursor and the marker to the start of the
cut text. For example:
B U F F E R marker = 1
^ ^ cursor = 4
Then perform xd()
B E R marker = 1
^ cursor = 1
*/
I have written some code:
def xd() {
paste = buffer.substring(lwr, upr)
buffer = buffer.delete(lwr, upr)
cursor = end
marker = end
}
this seems to pass the other tests but does not set the marker and cursor.
Any suggestions please?
First in Scala you would try to have no mutable state (var).
Here is a solution for cut and paste that is immutable:
case class Buffer(s: String, paste: String, private val cursor: Int = 0, private val marker: Int = 0) {
def mark(str: String): Buffer = {
val startIndex = s.indexOf(str)
val endIndex = startIndex + str.length
Buffer(s, startIndex, endIndex)
}
def cut(): Buffer = {
Buffer(s.take(cursor) + s.drop(marker), // rest of the String
s.take(marker).drop(cursor)) // paste of the String
}
}
You can use it like this:
Buffer("hello there") // > Buffer(hello there,,0,0)
.mark("o t") // > Buffer(hello there,,4,7)
.cut() // > Buffer(hellhere,o t,0,0)
You see the result of each line.
Let me know if you need more support or if I misunderstood you.
I have this function that counts the number of adjacent repeated chars inside a String.
def adjacentCount( s: String ) : Int = {
var cont = 0
for (a <- s.sliding(2)) {
if (a(0) == a(1)) cont = cont + 1
}
cont
}
}
But I'm supposed to create a function that does exactly the same, but using only immutable variables or loop instructions, in a "purely" functional way.
You can just use the count method on the Iterator:
val s = "aabcddd"
s.sliding(2).count(p => p(0) == p(1))
// res1: Int = 3
I want to delete duplicate char in my string with using deleteCharAt method but it's giving me an exception
def removeDuplicate(str: String): String={
var sb = new StringBuilder(str);
for(i <-0 until str.length ){
for(z <- i+1 until str.length ){
if(str(i)==str(z)){
sb.deleteCharAt(i);
}
}
}
return sb.toString;}
As the error suggested, when i = str.length - 1, z = str.length which is out of index. And there is another problem with your code, which is you are removing character from a string while looping through it. It is usually not a good practice to do so since the string length changes every time you delete a character, and you need to keep track of that. An alternative and more intuitive way is to build a new string and add only characters that have not appeared in the new string:
def removeDuplicate(str: String):String = {
var sb = ""
for(i <- 0 until str.length) {
if(! (sb contains str(i))) {
sb += str(i)
}}
sb
}
scala> removeDuplicate("abbccssds")
res13: String = abcsd
scala> removeDuplicate("abbeedsff")
res14: String = abedsf
scala> removeDuplicate("abbeedsffgg")
res15: String = abedsfg
I am getting an error from a piece of code. I will only show one line of code, at least the line I believe is causing it from the error report. It is:
b = temp(temp.length-1).toInt; //temp is an ArrayBuffer[String]
the error is:
For input string: "z"
at java.lang.NumberFormatException.forInputString(NumberFormatException.java:48)
at java.lang.Integer.parseInt(Integer.java:449)
at java.lang.Integer.parseInt(Integer.java:499)
at scala.collection.immutable.StringLike$class.toInt(StringLike.scala:231)
at scala.collection.immutable.StringOps.toInt(StringOps.scala:31)
at Driver$.stringParse$1(Driver.scala:59)
at Driver$.main(Driver.scala:86)
at Driver.main(Driver.scala)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at scala.tools.nsc.util.ScalaClassLoader$$anonfun$run$1.apply(ScalaClassLoader.scala:78)
at scala.tools.nsc.util.ScalaClassLoader$class.asContext(ScalaClassLoader.scala:24)
at scala.tools.nsc.util.ScalaClassLoader$URLClassLoader.asContext(ScalaClassLoader.scala:88)
at scala.tools.nsc.util.ScalaClassLoader$class.run(ScalaClassLoader.scala:78)
at scala.tools.nsc.util.ScalaClassLoader$URLClassLoader.run(ScalaClassLoader.scala:101)
at scala.tools.nsc.ObjectRunner$.run(ObjectRunner.scala:33)
at scala.tools.nsc.ObjectRunner$.runAndCatch(ObjectRunner.scala:40)
at scala.tools.nsc.MainGenericRunner.runTarget$1(MainGenericRunner.scala:56)
at scala.tools.nsc.MainGenericRunner.process(MainGenericRunner.scala:80)
at scala.tools.nsc.MainGenericRunner$.main(MainGenericRunner.scala:89)
at scala.tools.nsc.MainGenericRunner.main(MainGenericRunner.scala)
From what I can tell, it is causing an issue with this. Since it is immutable, I know it cannot be changed. But I am not sure. I am basing this off of
at java.lang.NumberFormatException.forInputString(NumberFormatException.java:48)
Once I do something like my lone of code above, does it change the whole object? Temp is an ArrayBuffer[String]. So I am trying to access a string representation of a number, and convert it. But in doing so, does this change what it is and keep me from doing anything?
If you believe putting all my code will be helpful, let me know to edit it, but it is a lot and I don't want to annoy anybody. I appreciate anybody who can help me understand this!
*EDIT: MY CODE (Only here to help me figure out my error, but not necessary to look at. I just can't see where its giving me this error).
The point of my code is to parse either one of those strings at the top. It puts together and into one string and then reads the other two symbols to go with it. It parses str just fine, but it finds a problem when it reads "z" in str2, and "y" in str3. As one can see, the problem is with the second string after the and when recursing. Its also important to note that the string has to be in that form. So it can only be parsed like "(and x (and y z))", but not in any other way that makes it more convenient.
val str = "(and x y)";
val str2 = "(and x (and y z))"; //case with expression on th right side
val str3 = "(and (and x y) z)"; //case with expression ont he left side
var i = 0; //just counter used to loop through the finished parsed array to make a list
//var position = 0; //this is used for when passing it in the parser to start off at zero
var hold = new ArrayBuffer[String]();//finished array should be here
def stringParse ( exp: String, expreshHolder: ArrayBuffer[String] ): ArrayBuffer[String] = { //takes two arguments, string, arraybuffer
var b = 0; //position of where in the expression String I am currently in
var temp = expreshHolder; //holder of expressions without parens
var arrayCounter = 0;
if(temp.length == 0)
b = 0;
else {
b = temp(temp.length-1).toInt;
temp.remove(temp.length-1);
arrayCounter = temp.length;
} //this sets the position of wherever the string was read last plus removes that check from the end of the ArrayBuffer
//just counts to make sure an empty spot in the array is there to put in the strings
if(exp(b) == '(') {
b = b + 1;
while(exp(b) == ' '){b = b + 1;} //point of this is to just skip any spaces between paren and start of expression type
if(exp(b) == 'a') {
//first create the 'and', 'or', 'not' expression types to figure out
temp += exp(b).toString;
b = b+1;
temp(arrayCounter) = temp(arrayCounter) + exp(b).toString; //concatenates the second letter
b = b+1;
temp(arrayCounter) = temp(arrayCounter) + exp(b).toString; //concatenates the last letter for the expression type
//arrayCounter+=1;
//this part now takes the symbols and puts them in an array
b+=1;
while(exp(b) == ' ') {b+=1;} //just skips any spaces until it reaches the FIRST symbol
if(exp(b) == '(') {
temp += b.toString;
temp = stringParse(exp, temp);
b = temp(temp.length-1).toInt;
temp.remove(temp.length-1);
arrayCounter = temp.length-1
} else {
temp += exp(b).toString;
arrayCounter+=1; b+=1; }
while(exp(b) == ' ') {b+=1;} //just skips any spaces until it reaches the SECOND symbol
if(exp(b) == '(') {
temp += b.toString;
temp = stringParse(exp, temp);
b = temp(temp.length-1).toInt;
temp.remove(temp.length-1);
arrayCounter = temp.length-1
} else {
temp += exp(b).toString;
arrayCounter+=1;
b+=1;
}
temp;
} else { var fail = new ArrayBuffer[String]; fail +="failed"; fail;}
}
hold = stringParse(str2, ho );
for(test <- hold) println(test);
What does temp contain? Your code assumes that it contains Strings that can be converted to Ints, but it seems that you have a String "z" in there instead. That would produce the error:
scala> "z".toInt
java.lang.NumberFormatException: For input string: "z"
...
Here's a recreation of what temp might look like:
val temp = ArrayBuffer("1", "2", "z")
temp(temp.length-1).toInt //java.lang.NumberFormatException: For input string: "z"
So you need to figure out why some String "z" is getting into temp.
EDIT:
So you're adding "expressions" to temp (temp += exp(b).toString) and also adding indices (temp += b.toString). Then you're assuming that temp only holds indices (b = temp(temp.length-1).toInt). You need to decide what temp is for, and then use it exclusively for that purpose.
No, toInt doesn't change the object, it takes the object as an argument and returns an integer, leaving the object as is.
I can't understand you question because I can`t understand you code.
Let's try to simplify you code.
First of all: you have some expressions with expression type and list of operands:
scala> :paste
// Entering paste mode (ctrl-D to finish)
abstract sealed class Operand
case class IdentOperand(name: String) extends Operand { override def toString(): String = name }
case class IntOperand(i: Int) extends Operand { override def toString(): String = i.toString() }
case class ExprOperand(expr: Expression) extends Operand { override def toString(): String = expr.toString() }
case class Expression(exprType: String, operands: Seq[Operand]) {
override def toString(): String = operands.mkString("(" + exprType + " ", " ", ")")
}
// Exiting paste mode, now interpreting.
defined class Operand
defined class IdentOperand
defined class IntOperand
defined class ExprOperand
defined class Expression
scala> Expression("and", Seq(IdentOperand("x"), IdentOperand("y")))
res0: Expression = (and x y)
scala> Expression("and", Seq(IdentOperand("x"), ExprOperand(Expression("and", Seq(IdentOperand("y"), IdentOperand("z"))))))
res1: Expression = (and x (and y z))
scala> Expression("and", Seq(ExprOperand(Expression("and", Seq(IdentOperand("x"), IdentOperand("y")))), IdentOperand("z")))
res2: Expression = (and (and x y) z)
Now we have to parse strings to expressions of this type:
scala> import scala.util.parsing.combinator._
import scala.util.parsing.combinator._
scala> object ExspessionParser extends JavaTokenParsers {
| override def skipWhitespace = false;
|
| def parseExpr(e: String) = parseAll(expr, e)
|
| def expr: Parser[Expression] = "(" ~> exprType ~ operands <~ ")" ^^ { case exprType ~ operands => Expression(exprType, operands) }
| def operands: Parser[Seq[Operand]] = rep(" "~>operand)
| def exprType: Parser[String] = "and" | "not" | "or"
| def operand: Parser[Operand] = variable | exprOperand
| def exprOperand: Parser[ExprOperand] = expr ^^ (ExprOperand( _ ))
| def variable: Parser[IdentOperand] = ident ^^ (IdentOperand( _ ))
| }
defined module ExspessionParser
scala> ExspessionParser.parseExpr("(and x y)")
res3: ExspessionParser.ParseResult[Expression] = [1.10] parsed: (and x y)
scala> ExspessionParser.parseExpr("(and x (and y z))")
res4: ExspessionParser.ParseResult[Expression] = [1.18] parsed: (and x (and y z))
scala> ExspessionParser.parseExpr("(and (and x y) z)")
res5: ExspessionParser.ParseResult[Expression] = [1.18] parsed: (and (and x y) z)
And now (as far as I understand your code) we have to replace string operands (x, y, z) with integer values. Let's add these 2 methods to Expression class:
def replaceOperands(ints: Seq[Int]): Expression = replaceOperandsInner(ints)._2
private def replaceOperandsInner(ints: Seq[Int]): (Seq[Int], Expression) = {
var remainInts = ints
val replacedOperands = operands.collect{
case n: IdentOperand =>
val replacement = remainInts.head
remainInts = remainInts.tail
IntOperand(replacement)
case ExprOperand(e) =>
val (remain, replaced) = e.replaceOperandsInner(remainInts)
remainInts = remain
ExprOperand(replaced)
}
(remainInts, Expression(exprType, replacedOperands))
}
And now we can do this:
scala> ExspessionParser.parseExpr("(and (and x y) z)").get.replaceOperands(Seq(1, 2, 3))
res7: Expression = (and (and 1 2) 3)
And if you have integer values in string form, then you can just convert them first:
scala> Seq("1", "2", "3") map { _.toInt }
res8: Seq[Int] = List(1, 2, 3)
I want to take input from the user. Can you please tell me how to ask for user input as a string in Scala?
In Scala 2.11 use
scala.io.StdIn.readLine()
instead of the deprecated Console.readLine.
Here is a standard way to read Integer values
val a = scala.io.StdIn.readInt()
println("The value of a is " + a)
similarly
def readBoolean(): Boolean
Reads a Boolean value from an entire line from stdin.
def readByte(): Byte
Reads a Byte value from an entire line from stdin.
def readChar(): Char
Reads a Char value from an entire line from stdin.
def readDouble(): Double
Reads a Double value from an entire line from stdin.
def readFloat(): Float
Reads a Float value from an entire line from stdin.
def readInt(): Int
Reads an Int value from an entire line from stdin.
def readLine(text: String, args: Any*): String
Prints formatted text to stdout and reads a full line from stdin.
def readLine(): String
Reads a full line from stdin.
def readLong(): Long
Reads a Long value from an entire line from stdin.
def readShort(): Short
Reads a Short value from an entire line from stdin.
def readf(format: String): List[Any]
Reads in structured input from stdin as specified by the format specifier.
def readf1(format: String): Any
Reads in structured input from stdin as specified by the format specifier, returning
only the first value extracted, according to the format specification.
def readf2(format: String): (Any, Any)
Reads in structured input from stdin as specified by the format specifier, returning
only the first two values extracted, according to the format specification.
def readf3(format: String): (Any, Any, Any)
Reads in structured input from stdin as specified by the format specifier, returning
only the first three values extracted, according to the format specification.
Similarly if you want to read multiple user inputs from the same line ex: name, age, weight you can use the Scanner object
import java.util.Scanner
// simulated input
val input = "Joe 33 200.0"
val line = new Scanner(input)
val name = line.next
val age = line.nextInt
val weight = line.nextDouble
abridged from Scala Cookbook: Recipes for Object-Oriented and Functional Programming by Alvin Alexander
From the Scala maling list (formatting and links were updated):
Short answer:
readInt
Long answer:
If you want to read from the terminal, check out Console.scala.
You can use these functions like so:
Console.readInt
Also, for your convenience, Predef.scala
automatically defines some shortcuts to functions in Console. Since
stuff in Predef is always and everywhere imported automatically, you
can use them like so:
readInt
object InputTest extends App{
println("Type something : ")
val input = scala.io.StdIn.readLine()
println("Did you type this ? " + input)
}
This way you can ask input.
scala.io.StdIn.readLine()
You can take a user String input using readLine().
import scala.io.StdIn._
object q1 {
def main(args:Array[String]):Unit={
println("Enter your name : ")
val a = readLine()
println("My name is : "+a)
}
}
Or you can use the scanner class to take user input.
import java.util.Scanner;
object q1 {
def main(args:Array[String]):Unit={
val scanner = new Scanner(System.in)
println("Enter your name : ")
val a = scanner.nextLine()
println("My name is : "+a)
}
}
Simple Example for Reading Input from User
val scanner = new java.util.Scanner(System.in)
scala> println("What is your name") What is your name
scala> val name = scanner.nextLine()
name: String = VIRAJ
scala> println(s"My Name is $name")
My Name is VIRAJ
Also we can use Read Line
val name = readLine("What is your name ")
What is your name name: String = Viraj
In Scala 2:
import java.io._
object Test {
// Read user input, output
def main(args: Array[String]) {
// create a file writer
var writer = new PrintWriter(new File("output.txt"))
// read an int from standard input
print("Enter the number of lines to read in: ")
val x: Int = scala.io.StdIn.readLine.toInt
// read in x number of lines from standard input
var i=0
while (i < x) {
var str: String = scala.io.StdIn.readLine
writer.write(str + "\n")
i = i + 1
}
// close the writer
writer.close
}
}
This code gets input from user and outputs it:
[input] Enter the number of lines to read in: 2
one
two
[output] output.txt
one
two
Using a thread to poll the input-readLine:
// keystop1.sc
// In Scala- or SBT console/Quick-REPL: :load keystop1.sc
// As Script: scala -savecompiled keystop1.sc
#volatile var isRunning = true
#volatile var isPause = false
val tInput: Thread = new Thread {
override def run: Unit = {
var status = ""
while (isRunning) {
this.synchronized {
status = scala.io.StdIn.readLine()
status match {
case "s" => isRunning = false
case "p" => isPause = true
case "r" => isRunning = true;isPause = false
case _ => isRunning = false;isPause = false
}
println(s"New status is: $status")
}
}
}
}
tInput.start
var count = 0
var pauseCount = 0
while (isRunning && count < 10){
println(s"still running long lasting job! $count")
if (count % 3 == 0) println("(Please press [each + ENTER]: s to stop, p to pause, r to run again!)")
count += 1
Thread sleep(2000) // simulating heavy computation
while (isPause){
println(s"Taking a break ... $pauseCount")
Thread sleep(1000)
pauseCount += 1
if (pauseCount >= 10){
isPause = false
pauseCount = 0
println(s"Taking a break ... timeout occurred!")
}
}
}
isRunning = false
println(s"Computation stopped, please press Enter!")
tInput.join()
println(s"Ok, thank you, good bye!")
readLine() lets you prompt the user and read their input as a String
val name = readLine("What's your name? ")
please try
scala> readint
please try this method