I am preparing a task for a C# course I teach where the students have to write a calculator in order to learn how to work with basic GUI. However in the process I found that I cannot reproduce the behavior of a standard calculator in full. My implementation always misses some corner cases and the output differs from what the Windows Calculator does in its Standard mode.
The Wikipedia article describes the working of the calculator but it does not list how it handles corner cases. It says that a calculator has two registers X and Y and X is always displayed on the screen but it does not describe how values are pushed from one register to the other in corner cases.
Examples of corner cases include the input sequences:
"3 * 2 = =" - should display 6 and then 12
"3 - =" which results in 0 on the Windows Calculator but in -3 on my implementation
"3 * 2 = + 3"
"3 * 2 = 3 =" which strangely results in 6 on the Windows Calculator
Of course I can handle the corner cases using enough flags but I am sure standard calculators were implemented the way they were implemented because this way was the simplest. I cannot think of a simple way to implement all the cases so I am probably doing it wrong. I have a single variable called previousValue I use in place of the Y register and I parse the textbox value when doing calculation to simulate the X register. I also have a variable which indicates if the next digit input should override the textbox (X register) value. There is also a variable for the current operation which is initialized to None. Basically I force calculation every time an operator button or = is pressed and I set the input flag to true.
Here is the code for digit input (AddInput), operation input (InputOperation), = button click (btnCalculate_Click) and the methods they call into.
private void AddInput(string input)
{
if (shouldOverrideDigits)
{
previousNumber = Decimal.Parse(txtDigits.Text);
txtDigits.Text = input;
shouldOverrideDigits = false;
}
else
{
txtDigits.Text += input;
}
}
private void InputOperation(CalculatorOperations operation)
{
if (!shouldOverrideDigits)
{
Calculate();
}
currentOperation = operation;
}
private void btnCalculate_Click(object sender, EventArgs e)
{
if (shouldOverrideDigits)
{
Calculate();
}
else
{
decimal currentNumber = Decimal.Parse(txtDigits.Text);
Calculate();
previousNumber = currentNumber;
}
}
private decimal Calculate()
{
decimal currentNumber = Decimal.Parse(txtDigits.Text);
decimal result;
switch (currentOperation)
{
case CalculatorOperations.None:
{
result = currentNumber;
} break;
case CalculatorOperations.Addition:
{
result = previousNumber + currentNumber;
} break;
case CalculatorOperations.Subtraction:
{
result = previousNumber - currentNumber;
} break;
case CalculatorOperations.Multiplication:
{
result = previousNumber * currentNumber;
} break;
case CalculatorOperations.Division:
{
result = previousNumber / currentNumber;
} break;
default:
{
throw new Exception("Unexpected operation type");
}
}
shouldOverrideDigits = true;
txtDigits.Text = result.ToString();
return result;
}
Can someone help with a simple solution? If the original calculators were able to handle everything with what is effectively three variables it is unlikely that the solution in a modern language needs much more.
Interestingly every article on implementing a calculator on the Internet I could find does it wrong.
Related
Such a weird question, but I set up this code in a playground:
let currentNumber = "1999999999"
let absNumber = abs(Double(currentNumber)!)
var digitCount = 0
if absNumber > 999999999 {
for n in currentNumber {
if n.isNumber {
digitCount += 1
} else {
break
}
print(digitCount)
}
}
As written, this code gets evaluated and my for loop runs...however, if is set my string to "-1999999999", the for loop doesn't run. The absolute value of -1999999999 is 100% greater than 999999999, so what did I miss?
The thing you did not understand is the control flow operator. You can get the expected behavior just change a single line:
if n.isNumber {
digitCount += 1
} else {
break // here change to continue
}
to this:
if n.isNumber {
digitCount += 1
} else {
continue
}
However, I highly recommend you try LLDB in an Xcode Project, either a Commandline tool or app. The stepover tool is quite useful for such a logical problem.
I'm trying to detect the type of number a user enters into a textField. For example
if the user enters 1000 The program should return 1Kcs
if the user enters 12,000, The program should return 12Kcs
if the user enters 12,000,000 The program should return 12MCS
How do I go about this in swift?
Thousands - Kcs
Hundreds - Mcs
This should to the job
extension Int {
var unitFormatted: String {
let positive = self < 0 ? -self : self
switch positive {
case 1_000_000..<Int.max: return "\(self / 1_000_000)MCS"
case 1_000..<1_000_000: return "\(self / 1_000)Kcs"
default: return "\(self)"
}
}
}
Examples
0.unitFormatted // "0"
1.unitFormatted // "1"
1000.unitFormatted // "1Kcs"
12000.unitFormatted // "12Kcs"
12000000.unitFormatted // "12MCS"
Some variation of this to fit your needs should be fine:
var num = 12000000
switch num {
case 1000...999999:
print(String(num/1000) + "Kcs")
case 1000000...999999999:
print(String(num/1000000) + "Mcs")
default:
print(num)
}
So this is just something I'm doing for fun in the IBM Swift sandbox. I did a L-system algae in Scala recently and though it would be cool to do it in Swift to see how the language compares.
https://github.com/I2obiN/L-System-Algorithms-and-Fractals/blob/master/algae.scala
That's the Scala one to show you what I'm aiming for, and this is what I have in Swift;
/**
* Created by t.hood on 26/01/16
* L-System Algae
*
*/
import Foundation
// Mapping function for string
func stringmap(x: String) -> String {
var str = x;
// Replace characters in string
str = x.stringByReplacingOccurrencesOfString("A", withString: "AB") +
str.stringByReplacingOccurrencesOfString("B", withString: "A");
// Return mapped string;
return str;
}
func lsys() {
// Declarations
var iteration : Int = 2;
var x = 0;
var lsystem: String = "A";
let charA: Character = "A";
let charB: Character = "B";
while(x != iteration) {
print(lsystem)
// Iterate through characters in string
for chars in lsystem.characters {
lsystem = stringmap(lsystem);
}
// Inc count ..
x+=1
}
}
// Run ..
lsys();
The problem I'm having is in my mapping function. I need it to map x, print the result, then do the next map on str. The problem is I have the operator + between both maps and I can't get swift to print str after the first operation.
Anyone any ideas on how to get around this? If I could print str after the first replacements I think it would work.
I created a project in Xcode so I could use the debugger to see what's going on. Here's what I found.
I moved your print statement into the for loop so it would show the value of lsystem every time the loop executed.
The while loop executes twice, when x == 0 and 1
The first time through the while loop lsystem == 'A', so the for loop executes once. In stringmap(), the 'A' becomes 'ABA'.
'ABA' is printed.
The second time through the while loop, the for loop gets executed three times.
For loop 1: 'ABA' is sent to stringmap() and 'ABBABAAA' is returned.
For loop 2: 'ABBABAAA' is sent to stringmap() and 'ABBBABBABABABAAAAAAAA' is returned.
For loop 3: 'ABBBABBABABABAAAAAAAA' is sent to stringmap() and 'ABBBBABBBABBABBABBABABABABABABABABAAAAAAAAAAAAAAAAAAAAA' is returned.
I modified your stringmap() function to iterate through the string character by character and apply the grammar to each character, appending each change to a new string that was then returned to lsys().
Seven iterations of the while loop returned this, which agrees with what I see in the Wikipedia article about L-system.
Iteration 0: A
Iteration 1: AB
Iteration 2: ABA
Iteration 3: ABAAB
Iteration 4: ABAABABA
Iteration 5: ABAABABAABAAB
Iteration 6: ABAABABAABAABABAABABA
Iteration 7: ABAABABAABAABABAABABAABAABABAABAAB
Here's the code. This worked in a playground on my iMac, I'd expect it to work in the IBM Swift sandbox too.
func stringmap(x: String) -> String
{
var returnString = ""
for char in x.characters
{
switch (char)
{
case "A" :
returnString += "AB"
break
case "B":
returnString += "A"
break
default:
break
}
}
return returnString
}
func lsys()
{
// Declarations
let iteration : Int = 7;
var x = 0;
var lsystem: String = "A";
print("Iteration \(x): \(lsystem)")
while(x != iteration)
{
lsystem = stringmap(lsystem)
x++
print("Iteration \(x): \(lsystem)")
}
}
lsys()
Find below the imperative style code:
private boolean placePieceOnBoard(Results results,
ChessLayout chessLayout,
List<ChessPiece> piecesToPlace,
int pieceIndex,
int startOffset) {
if(pieceIndex == piecesToPlace.size()) {
results.addLayout(chessLayout);
return true;
}
else {
ChessPiece chessPiece = piecesToPlace.get(pieceIndex);
int offset = startOffset;
while(offset < chessLayout.getBoardLength()) {
int placedOffset = chessLayout.placePieceInNextAvailablePosition(chessPiece, offset);
if( placedOffset == ChessLayout.NULL_OFFSET )
break;
else {
logger.debug("piece {} ({}) moved", pieceIndex, chessPiece);
placePieceOnBoard(results, chessLayout.clone(), piecesToPlace, pieceIndex + 1, placedOffset + 1);
chessLayout.removeChessPiece(chessPiece);
offset = placedOffset + 1;
}
}
return false;
}
}
Here I am interested in knowing how to convert changes made to offset within the loop in a functional way, how to do early break from the loop etc.
This is a nice demonstration of one of Scala's great strengths - gradual, easy migration from imperative Java code to functional code.
To convert to Scala, you don't need to go 100% functional straight away. You can easily convert what you have to Scala as follows:
def placePieceOnBoard(results: Results,
chessLayout: ChessLayout,
piecesToPlace: List[ChessPiece],
pieceIndex: Int,
startOffset: Int) {
if (pieceIndex == piecesToPlace.size()) {
results.addLayout(chessLayout)
true
}
else {
val chessPiece = piecesToPlace.get(pieceIndex)
var offset = startOffset
while(offset < chessLayout.getBoardLength) {
val placedOffset = chessLayout.placePieceInNextAvailablePosition(chessPiece, offset)
if( placedOffset == ChessLayout.NULL_OFFSET )
break
else {
logger.debug("piece {} ({}) moved", pieceIndex, chessPiece)
placePieceOnBoard(results, chessLayout.clone(), piecesToPlace, pieceIndex + 1, placedOffset + 1)
chessLayout.removeChessPiece(chessPiece)
offset = placedOffset + 1
}
}
false
}
}
Note we already have some small improvements in verbosity: no more ;s, no redundant type signatures, mutable variables converted to constants where possible, eliminated return statements and function brackets. Note I changed the argument type of piecesToPlace to a scala list, you'll need to use the scala-java converters at the call site to make this compile.
Next, we can start making this more functional... however, this function probably isn't the place you should start, as you are calling state-mutating functions in several places. For example, you could start with ChessLayout:
chessLayout.removeChessPiece(chessPiece)
val placedOffset = chessLayout.placePieceInNextAvailablePosition(chessPiece, offset)
These methods mutate ChessLayout, which is not functional style. You could modify removeChessPiece to return a new ChessLayout with the piece removed, and placePieceInNextAvailablePosition could return a tuple of (ChessLayout, Int). Once you have stopped any functions called from placePieceOnBoard from mutating state, you can then convert it to functional style.
I'm working on integrating an IDTech swiper into my app and I've gotten pretty far along, added the library, registered notifications, unregistered them, and now I'm working on a function that connects the reader. I can't seem to figure out what I'm doing wrong here when I'm attempting to switch cases based on a return value.. could someone please help me?
func displayUmRet(operation: String, returnValue: UmRet) {
var string = ""
do {
switch returnValue {
case UMRET_SUCCESS: string = ""
case UMRET_NO_READER: string="No reader attached"
case UMRET_SDK_BUSY: string="Communication with reader in progress"
case UMRET_MONO_AUDIO: string="Mono audio enabled"
case UMRET_ALREADY_CONNECTED: string="Already connected"
case UMRET_LOW_VOLUME: string="Low volume"
case UMRET_NOT_CONNECTED: string="Not connected"
case UMRET_NOT_APPLICABLE: string="Not applicable to reader type"
case UMRET_INVALID_ARG: string="Invalid argument"
case UMRET_UF_INVALID_STR: string="Invalid firmware update string"
case UMRET_UF_NO_FILE: string="Firmware file not found"
case UMRET_UF_INVALID_FILE: string="Invalid firmware file"
default: string="<unknown code>"
}
} while (0)
// var retStatus = UMRET_SUCCESS==ret
//self.textResponse.text = "\(operation), \(retStatus), \(string)"
self.hexResponse.text = "";
}
You need to put a . before your cases:
enum UmRet {
case UMRET_SUCCESS, UMRET_FAILURE
}
var string = " "
let returnValue = UmRet.UMRET_SUCCESS
switch returnValue {
case .UMRET_SUCCESS: string = "y"
case .UMRET_FAILURE: string = "n"
}
Also, 0 isn't the same as false in Swift, so:
do {
...
} while (0)
Shouldn't work either.
And you don't need semicolons at the end of a line, so this:
self.hexResponse.text = "";
can be this:
self.hexResponse.text = ""
And finally, if your switch statement has every case for every case in your enum, you don't need a default case. (that's why mine didn't have one in the example)
By the way, ~= is just the operator for the pattern-matching function, which is what Swift does in a switch statement. It works kind of like the == function, for instance, Int ~= Int is the same as Int == Int. But it's a bit more versatile: for instance Range ~= Int, eg 0...3 ~= 2 returns whether or not the Int is in the range. (So true in this case) For enums, it matches cases to cases. In my example, it'll match UMRET_SUCCESS, and string will be set to y.