SRL Archive - General

A Programming Challenge


Echo_

2013-01-18 19:11:22

Alright so I originally had to do this for my Computer Science class as part of a competition. The challenge is to write a command prompt calculator. You can use any programming language you want. It has to recieve input from the user and print the result (REPL). It has to support all the basic math operators (+, -, *, /, %). Optionally you can add functionality for symbol definition, similar to how Bjarne Stroustrup did with his calculator in his "C++ Programming Language" book:

table["pi"] = 3.1415926535897932385;

Have fun, there's more than one way to do this. I hope to see some of your solutions soon, and I will post mine 24 hours from now.

NKN

2013-01-18 21:58:20

Gah, I had one a longgg time ago.

Had all the basics, fractions, basic algebra.
Going to go look for it. (Was made with C++)

Echo_

2013-01-20 00:03:15

I guess I'll wait another day since nobody has posted code yet :/

Gucci

2013-01-20 00:14:31

I'm pretty new to C++ but here is mine:

#include <iostream>
#include <windows.h>
using namespace std;

void Add()
{
double a, b, c;
cout << "Enter the first number" << endl;
cin >> a;
cout << "Enter the second number" << endl;
cin >> b;
c = a + b;
cout << a;
cout << " + ";
cout << b;
cout << " is equal to: ";
cout << c << endl;
}

void Subtract()
{
double a, b, c;
cout << "Enter the first number" << endl;
cin >> a;
cout << "Enter the second number" << endl;
cin >> b;
c = a - b;
cout << a;
cout << " - ";
cout << b;
cout << " is equal to: ";
cout << c << endl;
}

void Multiply()
{
double a, b, c;
cout << "Enter the first number" << endl;
cin >> a;
cout << "Enter the second number" << endl;
cin >> b;
c = a * b;
cout << a;
cout << " * ";
cout << b;
cout << " is equal to: ";
cout << c << endl;
}

void Divide()
{
double a, b, c;
cout << "Enter the first number" << endl;
cin >> a;
cout << "Enter the second number" << endl;
cin >> b;
c = a / b;
cout << a;
cout << " / ";
cout << b;
cout << " is equal to: ";
cout << c << endl;
}

int main()
{
int input;

cout << "What operation to perform (Add(1), Subtract(2), Multiply(3), Divide(4))" << endl;
cin >> input;
switch ( input ) {
case 1:
Add();
break;
case 2:
Subtract();
break;
case 3:
Multiply();
break;
case 4:
Divide();
break;
default:
cout<<"Error, bad input, quitting\n";
break;

}
system("PAUSE");

}

nielsie95

2013-01-20 06:43:37

http://villavu.com/forum/showthread.php?t=52254 :)
Can be easily extended for constants (parsing is already there).

Emaziz

2013-01-20 07:44:12

#include <iostream>
#include <string>

static const int MAX_SIZE = 1000;

static const int operatorCount = 7;
static const char operators[operatorCount] = {
'=','+','-','*','/','%','^'
};
static const int constantCount = 4;
static const int constantLength = 7;
static double constantValue[constantCount] = {
3.14159265359, // pi
2.71828182846, // e
1337.0
0
};
static const char constants[constantCount][constantLength] = {
"pi",
"e",
"emaziz",
"zyt3x",
};

static const int variableCount = 26;
static char variables[26][MAX_SIZE];

struct expression {
private:
char expr[MAX_SIZE];
int findOperator(char& op) {
int paradepth = 0;
for(int j = 0; j < operatorCount; j++)
for(int i = 0; i < MAX_SIZE && expr[i] != 0; i++) {
if(expr[i] == '(') paradepth++; else if(expr[i] == ')') paradepth--;
else if(expr[i] == operators[j] && paradepth == 0) {
op = expr[i];
return i;
};
};
return -1;
};
public:
expression() { for(int i = 0; i < MAX_SIZE; i++) expr[i] = 0; };
expression(const char* cs) {
int rsize = 0;
for(int i = 0; i < MAX_SIZE && cs[i] != '\n'; i++)
if(cs[i] != ' ') expr[rsize++] = cs[i];
};

double parse() {
char op;
int oploc = findOperator(op);
if(oploc > -1) {
char lexpr[MAX_SIZE] = {0};
char rexpr[MAX_SIZE] = {0};
for(int i = 0; i < oploc; i++)
lexpr[i] = expr[i];
for(int i = 0; i < MAX_SIZE; i++)
rexpr[i] = expr[oploc+i+1];
double lexprres = expression(lexpr).parse();
double rexprres = expression(rexpr).parse();
switch(op) {
case '+':
return lexprres + rexprres;
case '-':
return lexprres - rexprres;
case '*':
return lexprres * rexprres;
case '/':
return lexprres / rexprres;
case '%':
return (int)lexprres % (int)rexprres;
case '^':
return pow(lexprres,rexprres);
case '=':
if(isalpha(lexpr[0]) && !isalpha(lexpr[1])) {
int var = tolower(lexpr[0])-97;
for(int i = 0; i < MAX_SIZE; i++)
variables[var][i] = rexpr[i];
std::cout << "Set variable '" << lexpr[0] << "' to " << rexpr << "." << std::endl;
return 0;
};
default:
std::cout << "WHAT KIND OF FUCKING OPERATOR IS THIS?!" << std::endl;
return 0;
};
} else {
// Check if it is paranthesis-expression, remove paranthesis
if(expr[0] == '(') {
char cs[MAX_SIZE] = { 0 };
int paradepth = 0;
for(int i = 1; i < MAX_SIZE && (expr[i] != ')' || paradepth != 0); i++) {
if(expr[i] == '(') paradepth++; else if(expr[i] == ')') paradepth--;
cs[i-1] = expr[i];
};
return expression(cs).parse();
};
// Check if function or constant
if(isalpha(expr[0])) {
// Check for constant
for(int i = 0; i < constantCount; i++)
for(int j = 0; j < constantLength; j++)
if(expr[j] != constants[i][j])
break;
else if(j == constantLength-1)
return constantValue[i];
// Check for variable
if(!isalpha(expr[1])) {
return expression(variables[tolower(expr[0])-97]).parse();
};
};
return _atof_l(expr,0);;
};
};
};

int main() {
char input[MAX_SIZE] = {0};
while(true) {
std::cout << "Enter a mathematical expression to calculate, or nothing to quit: " << std::endl;
for(int i = 0; i < MAX_SIZE; i++)
input[i] = 0;
std::cin.getline(input,1000);
if(input[0] == 0)
break;
double result = 0;
std::cout << expression(input).parse() << std::endl << std::endl;
};
std::cout << "See ya later, alligator!" << std::endl;
_sleep(1000);
};

Hey, this was fun! :D Only supports the basic operators but I think I'll add constants and trigonometric functions later. ^^,

EDIT: Forgot ^-operator
EDIT2: Crap, I just spilled soda all over my shirt!
EDIT3: Carrot soup is actually pretty tasty. Who would've known?! Now I has added paranthesis support!
EDIT4: WHUDDUP, now it even supports constants 'e' and 'pi' as well as variables which is any single letter and can be set with like "x = 5", or even freaking "y = x^2" and then you can change x and y will be changed as well! WHAT SORCERY IS THIS??? I shall go to work now.

CynicRus

2013-01-20 14:32:08

Very basic calc with 4 math operator support (+,-,*,/). Just for fun:
Language assembler.

;This program was created on assembler editor
.486
.model flat,stdcall
option casemap:none
WinMain proto :DWORD,:DWORD,:DWORD,:DWORD
include include\windows.inc
include include\user32.inc
include include\kernel32.inc


includelib lib\user32.lib
includelib lib\kernel32.lib

.data

ClassName db "SimpleWinClass",0
AppName db "JustCalc",0
MenuName db "FirstMenu",0

ButtonClassName db "button",0
EditClassName db "edit",0
LabelClassName DB "STATIC", 0


ButtonText2 db "+",0
ButtonText3 db "-",0
ButtonText4 db "*",0
ButtonText5 db "/",0

text1 db "Number1",0
text2 db "Number2",0

dlg db "ok",0


format db '%d',0

.data?
op1 dd 0
op2 dd 0
result dd 0

string db 30 DUP(0)
hInstance HINSTANCE ?
CommandLine LPSTR ?

hwndButton HWND ?
hwndButton2 HWND ?
hwndButton3 HWND ?
hwndButton4 HWND ?


hwndEdit HWND ?
hwndEdit2 HWND ?


hwndLabell DD ?
hwndLabell2 DD ?






.const
ButtonID equ 1
Button2ID equ 2
Button3ID equ 3
Button4ID equ 12

EditID equ 4
Edit2ID equ 5

LabelID EQU 8
Label2ID equ 9




.code
start:

invoke GetModuleHandle, NULL
mov hInstance,eax
invoke GetCommandLine
mov CommandLine,eax
invoke WinMain, hInstance,NULL,CommandLine, SW_SHOWDEFAULT
invoke ExitProcess,eax


WndProc proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
.IF uMsg==WM_DESTROY
invoke PostQuitMessage,NULL
.ELSEIF uMsg==WM_CREATE

invoke CreateWindowEx, NULL,ADDR LabelClassName, NULL,WS_CHILD or WS_VISIBLE ,12, 1, 130, 15, hWnd, LabelID,hInstance, NULL
mov hwndLabell, eax
invoke SetWindowText, hwndLabell, ADDR text1

invoke CreateWindowEx, NULL,ADDR LabelClassName, NULL,WS_CHILD or WS_VISIBLE ,12, 41, 130, 15, hWnd, Label2ID,hInstance, NULL
mov hwndLabell2, eax
invoke SetWindowText, hwndLabell2, ADDR text2

invoke CreateWindowEx,WS_EX_CLIENTEDGE, ADDR EditClassName,NULL,WS_CHILD or WS_VISIBLE or WS_BORDER or ES_LEFT or ES_AUTOHSCROLL or ES_NUMBER,12,18,160,25,hWnd,EditID,hInstance,NULL
mov hwndEdit,eax
invoke SetFocus, hwndEdit

invoke CreateWindowEx,WS_EX_CLIENTEDGE, ADDR EditClassName,NULL,WS_CHILD or WS_VISIBLE or WS_BORDER or ES_LEFT or ES_AUTOHSCROLL or ES_NUMBER,12,60,160,25,hWnd,Edit2ID,hInstance,NULL
mov hwndEdit2,eax


invoke CreateWindowEx,NULL, ADDR ButtonClassName,ADDR ButtonText2,WS_CHILD or WS_VISIBLE or BS_DEFPUSHBUTTON,15,100,22,25,hWnd,ButtonID,hInstance,NULL
mov hwndButton,eax

invoke CreateWindowEx,NULL, ADDR ButtonClassName,ADDR ButtonText3,WS_CHILD or WS_VISIBLE or BS_DEFPUSHBUTTON,60,100,22,25,hWnd,Button2ID,hInstance,NULL
mov hwndButton2,eax

invoke CreateWindowEx,NULL, ADDR ButtonClassName,ADDR ButtonText4,WS_CHILD or WS_VISIBLE or BS_DEFPUSHBUTTON,105,100,22,25,hWnd,Button3ID,hInstance,NULL
mov hwndButton3,eax

invoke CreateWindowEx,NULL, ADDR ButtonClassName,ADDR ButtonText5,WS_CHILD or WS_VISIBLE or BS_DEFPUSHBUTTON,150,100,22,25,hWnd,Button4ID,hInstance,NULL
mov hwndButton4,eax




.ELSEIF uMsg==WM_COMMAND
mov eax,wParam
.IF lParam==0

.ELSE


.IF ax==ButtonID
shr eax,16
.IF ax==BN_CLICKED
invoke GetDlgItemInt,hWnd,EditID,0,1
mov op1,eax

invoke GetDlgItemInt,hWnd,Edit2ID,0,1
add eax,op1
invoke wsprintf,addr string,addr format,eax
invoke MessageBox,0,addr string,addr dlg,MB_OK
.ENDIF
.ENDIF



.IF ax==Button2ID
shr eax,16
.IF ax==BN_CLICKED
invoke GetDlgItemInt,hWnd,EditID,0,1
mov op1,eax

invoke GetDlgItemInt,hWnd,Edit2ID,0,1
sub eax,op1
neg eax
invoke wsprintf,addr string,addr format,eax
invoke MessageBox,0,addr string,addr dlg,MB_OK

.ENDIF
.ENDIF

.IF ax==Button4ID
shr eax,16
.IF ax==BN_CLICKED
invoke GetDlgItemInt,hWnd,Edit2ID,0,1
mov ebx,eax
invoke GetDlgItemInt,hWnd,EditID,0,1
div ebx

invoke wsprintf,addr string,addr format,eax
invoke MessageBox,0,addr string,addr dlg,MB_OK
.ENDIF
.ENDIF

.IF ax==Button3ID
shr eax,16
.IF ax==BN_CLICKED
invoke GetDlgItemInt,hWnd,EditID,0,1
mov op1,eax

invoke GetDlgItemInt,hWnd,Edit2ID,0,1
imul eax,op1
invoke wsprintf,addr string,addr format,eax
invoke MessageBox,0,addr string,addr dlg,MB_OK





.ENDIF
.ENDIF
.ENDIF



.ELSE
invoke DefWindowProc,hWnd,uMsg,wParam,lParam
ret
.ENDIF
xor eax,eax
ret
WndProc endp


WinMain proc hInst:HINSTANCE,hPrevInst:HINSTANCE,CmdLine:LPSTR,CmdShow:DWORD
LOCAL wc:WNDCLASSEX
LOCAL msg:MSG
LOCAL hwnd:HWND
mov wc.cbSize,SIZEOF WNDCLASSEX
mov wc.style, CS_HREDRAW or CS_VREDRAW
mov wc.lpfnWndProc, OFFSET WndProc
mov wc.cbClsExtra,NULL
mov wc.cbWndExtra,NULL
push hInst
pop wc.hInstance
mov wc.hbrBackground,COLOR_BTNFACE+1
mov wc.lpszMenuName,OFFSET MenuName
mov wc.lpszClassName,OFFSET ClassName
invoke LoadIcon,NULL,IDI_APPLICATION
mov wc.hIcon,eax
mov wc.hIconSm,eax
invoke LoadCursor,NULL,IDC_ARROW
mov wc.hCursor,eax
invoke RegisterClassEx, addr wc
INVOKE CreateWindowEx,WS_EX_CLIENTEDGE,ADDR ClassName,ADDR AppName,\
WS_SYSMENU,CW_USEDEFAULT,\
CW_USEDEFAULT,200,200,NULL,NULL,\
hInst,NULL
mov hwnd,eax
INVOKE ShowWindow, hwnd,SW_SHOWNORMAL
INVOKE UpdateWindow, hwnd
.WHILE TRUE
INVOKE GetMessage, ADDR msg,NULL,0,0
.BREAK .IF (!eax)
INVOKE TranslateMessage, ADDR msg
INVOKE DispatchMessage, ADDR msg
.ENDW
mov eax,msg.wParam
ret
WinMain endp


end start


nielsie95

2013-01-20 16:05:14

Now you're just showing off :p Pretty cool, though :)

Echo_

2013-01-20 16:40:39

One thing I saw was that some don't have a failsafe for division by 0 ;)

So far the examples have been great, it's interesting looking at how each of you approaching parsing the string and splitting into tokens. And I definitely didn't expect to see a windows assembly program :p

Emaziz

2013-01-20 16:45:57

Hah, I forgot about null division, but turns out the double-type can divide by zero, you just get 1.#INF :D

Recursive

2013-01-20 17:03:44

@CynicRus

That's amazing one could do something like that with assembler. Do you have any recommended reads for assembler I could tap into? We are programming with MIPS at school.

CynicRus

2013-01-20 22:39:47

From: [Re]cUrSivE
@CynicRus

That's amazing one could do something like that with assembler. Do you have any recommended reads for assembler I could tap into? We are programming with MIPS at school.


Well, I think http://www.amazon.com/dp/0471375233/?tag=stackoverfl08-20 or http://www.amazon.com/The-Assembly-Programming-Master-Book/dp/1931769362and http://www.tik.ee.ethz.ch/education/lectures/TI1/materials/assemblylanguageprogdoc.pdf and http://en.wikibooks.org/wiki/Category:MIPS_Assembly.

Echo_

2013-01-21 02:44:17

Alright here's my 25 lines of terror:

#!/usr/bin/perl

use strict;
use warnings;

my %symbols;
my $instructions = <<'END';
--------------------------------------------------------------------
Instructions
--------------------------------------------------------------------
* Enter any mathematical equation to have it solved
* Define symbols with the form $symbols{symbol_name} = symbol_value
* Use symbols with the form $symbols{symbol_name}
--------------------------------------------------------------------
END

sub instructions { print $instructions, 'USER> ' }

instructions;
while (<STDIN>) {
chomp;
if ($_ eq 'quit') { print 'Goodbye!'; last }
elsif ($_ eq 'instructions') { instructions; next }
print eval, "\nUSER> ";
}

Like I said, more than one way to do it ;)

CynicRus

2013-01-21 03:02:52

Basic calculator on the Java Script:)


<SCRIPT LANGUAGE="JavaScript">
<!-- Begin
var FKeyPad = document.Keypad;
var Accum = 0;
var FlagNewNum = false;
var PendingOp = "";
function NumPressed (Num) {
if (FlagNewNum) {
FKeyPad.ReadOut.value = Num;
FlagNewNum = false;
}
else {
if (FKeyPad.ReadOut.value == "0")
FKeyPad.ReadOut.value = Num;
else
FKeyPad.ReadOut.value += Num;
}
}
function Operation (Op) {
var Readout = FKeyPad.ReadOut.value;
if (FlagNewNum && PendingOp != "=");
else
{
FlagNewNum = true;
if ( '+' == PendingOp )
Accum += parseFloat(Readout);
else if ( '-' == PendingOp )
Accum -= parseFloat(Readout);
else if ( '/' == PendingOp )
Accum /= parseFloat(Readout);
else if ( '*' == PendingOp )
Accum *= parseFloat(Readout);
else
Accum = parseFloat(Readout);
FKeyPad.ReadOut.value = Accum;
PendingOp = Op;
}
}
function Decimal () {
var curReadOut = FKeyPad.ReadOut.value;
if (FlagNewNum) {
curReadOut = "0.";
FlagNewNum = false;
}
else
{
if (curReadOut.indexOf(".") == -1)
curReadOut += ".";
}
FKeyPad.ReadOut.value = curReadOut;
}
function ClearEntry () {
FKeyPad.ReadOut.value = "0";
FlagNewNum = true;
}
function Clear () {
Accum = 0;
PendingOp = "";
ClearEntry();
}
function Neg () {
FKeyPad.ReadOut.value = parseFloat(FKeyPad.ReadOut.value) * -1;
}
function Percent () {
FKeyPad.ReadOut.value = (parseFloat(FKeyPad.ReadOut.value) / 100) * parseFloat(Accum);
}
</SCRIPT>

xdarkshadowx

2013-01-21 03:03:02

Lmao, I built one forever ago in java. Been so long since I've coded in java… damn. It could do summations and a bunch of stuff lol. was really good practice.