2
\$\begingroup\$

Your code has to provide the following functions:

read(x)

Reads a complex number from the standard input. It has to accept and evaluate something in the form of for example 1.42 + 3i.

print(x)

Prints the complex number in the form of, for example 1.23 - 4.32i

add(x,y)
sub(x,y)
mult(x,y)
div(x,y)

Adds, subtracts, multiplies and respectively divides the two complex numbers.

It is enough if your functions are accurate to two digits after the decimal point, of course, it can be more if you so wish. The input will never have more than two digits after the decimal point.

Any language without native support for complex numbers may be used. Similarly, libraries or other language features which deal with complex numbers are not permitted. The point is, you have to do all the handling of complex numbers by yourself.

Scoring

This is a code golf. The score is the sum of the lengths of the function bodies. For example, int add(int a, int b) {return a+b;} will have a length of 11 because of return a+b. Your solution must have a main program which demonstrates the use of the functions (for easier evaluation of your solution), but it will not be part of the scoring.

You can store the complex numbers in any way you wish, but the functions must have exactly the same amount of parameters as in the above description.

EDIT: For languages that support it, you can use operator overloading instead of the add, sub, etc. functions.

EDIT 2: To prohibit the cheap #define all_your_code_here A, I'll try to clarify the "only function bodies count" better: every character in the code counts, except for the overhead required to declare and define the functions and the libraries required to do basic I/O. By basic I/O I still mean no language features which directly deal with complex numbers. The main or equivalent where you call these functions don't count but you are not allowed to do anything besides using those functions for demonstrative purpose.

\$\endgroup\$
6
  • 1
    \$\begingroup\$ any bonus for operator overload (in languages that support it)? \$\endgroup\$ Commented Oct 14, 2012 at 11:29
  • \$\begingroup\$ You're obviously talking about languages that use the word "function" in the way C does, like Python, Lisp, JavaScript etc.. But read and print aren't actually functions (they have side-effects), so in a more rigorous language you can't define them in that precise way. Are those languages "out", or may we use the corresponding signatures (e.g. read :: IO ComplexNum and print :: ComplexNum -> IO() in Haskell)? Or why shall we not rather define functions to parse / build strings, rather than perform actual IO? \$\endgroup\$ Commented Oct 14, 2012 at 15:05
  • \$\begingroup\$ If only the function bodies count, are any lines of e.g. standard library includes for free, or permitted at all? \$\endgroup\$ Commented Oct 14, 2012 at 15:10
  • 1
    \$\begingroup\$ @leftaroundabout: includes are free, unless they deal with complex numbers, in which case they are not permitted. The point is, you have to do all the handling of complex numbers by yourself. \$\endgroup\$
    – vsz
    Commented Oct 14, 2012 at 15:19
  • 2
    \$\begingroup\$ -1 Boring and not very well specified. The mathematical definitions of the operations are really quite simple, so the most interesting part is the IO (not that it's really interesting), and in those parts the level of detail for what is acceptable is insufficient. \$\endgroup\$ Commented Oct 14, 2012 at 21:43

6 Answers 6

4
\$\begingroup\$

APL (33 + 16 + 1 + 1 + 14 + 17 = 82)

APL does have support for complex numbers if you use it (of the format 5J6, like Python's 5+6j), but it is of course not used.

I represent complex numbers as a 2-tuple of regular numbers, (A B) where A is the real part and B is the imaginary part. This means I can use APL's + and - operators directly, as they can be used on multidimensional types. (i.e. 1+2 3 4 gives 3 4 5 and 1 2+20 10 gives 21 12).

An APL function is represented as {body}. Functions are first-class objects. I have counted the function body without the braces, except for + and - which I've counted as 1 each.

read  ← {⎕ML←3⋄(1,1-2×'-'∊⍵)×⍎¨⍵⊂⍨⍵∊'.',⎕D} ⍝ 33 chars
print ← {⍕(⊃⍵)'+'(⊃⌽⍵)'i'}                   ⍝ 16 chars
add   ← +                                      ⍝ 1 char
sub   ← -                                      ⍝ 1 char
mul   ← {(-/⍺×⍵),+/⍺×⌽⍵}                      ⍝ 14 chars
div   ← {⍺mul 1 ¯1×⍵÷+/⍵*2}                   ⍝ 17 chars

Usage: (clarification: APL is evaluated right-to-left so this is actually calculating 8+9i ÷ 5+6i.)

      print (read⍞) div (read⍞)
5 + 6i
8 + 9i
1.540983607 + ¯0.04918032787 i
\$\endgroup\$
2
  • \$\begingroup\$ print←{∊⍵,¨'+i'} \$\endgroup\$
    – Adám
    Commented Oct 26, 2016 at 19:06
  • \$\begingroup\$ read←{⍎¨w⊂⍨'-+'∊⍨w←'+',⍵~' i'} \$\endgroup\$
    – Adám
    Commented Oct 26, 2016 at 19:10
3
\$\begingroup\$

D (205 chars)

import stdio;

struct Complex{
  real a,b;

  this(real a,real b){
      this.a=a;
      this.b=b;
  }

  static Complex read(){
      Complex c;
      readf("%f%+fi",&c.a,&c.b);
      return c;
  }

  /** does both addition and substraction */
  Complex opOpBinary(op)(Complex o)if(op=="+"||op=="-"){
    mixin("return Complex(a"~op~"o.a,b"~op~"o.b);");
  }

  Complex opBinary(op)(Complex o)if(op=="*"){
    return Complex(a*o.a-b*o.b,a*o.b+b*o.a);
  }

  Complex opBinary(op)(Complex o)if(op=="/"){
    real z=c**2+d**2
    return this*Complex(o.a/z,-o.b/z);
  }

  void write(){
     writef("%f%+fi",a,b);
  }

}

using operator overloading

I didn't count the constructor

\$\endgroup\$
1
  • 1
    \$\begingroup\$ +1 for showcasing some of the most hideous syntax I've ever seen in any language. \$\endgroup\$ Commented Oct 14, 2012 at 21:42
1
\$\begingroup\$

Python, 131 chars

add=lambda (a,b),(c,d):(a+c,b+d)
sub=lambda (a,b),(c,d):(a-c,b-d)
mul=lambda (a,b),(c,d):(a*c-b*d,a*d+b*c)
def div(x,(c,d)):z=c**2+d**2;return mul(x,(c/z,-d/z))
def _print(x):print"%f+%fi"%x
read=lambda:tuple(map(float,raw_input()[:-1].split('+')))

x=read()
y=read()
_print(add(x,y))
_print(sub(x,y))
_print(mul(x,y))
_print(div(x,y))

Makes lots of use of lambda unpacking, which I'm not including in my "body" count. (I'm counting everything after the first :). Kinda cheating, but I'm not really sure how to count it otherwise.

\$\endgroup\$
2
  • \$\begingroup\$ Doesn't work with e.g. 1 - 3i this way. \$\endgroup\$ Commented Oct 14, 2012 at 18:37
  • \$\begingroup\$ @leftaroundabout: true. The input format hasn't really been well-specified (e.g. is 3 passed as 3 or 3+0i?). \$\endgroup\$ Commented Oct 14, 2012 at 18:46
1
\$\begingroup\$

C# – 369 (I guess)

Func<float,float,float[]>C=(x,y)=>new[]{x,y};
Func<float[]>read=()=>{var m=new Regex(@"(\d*(\.\d*)?) *([+-]) *(\d*(\.\d*)?)i").Match(Console.ReadLine()).Groups;return C(float.Parse(m[1].Value),float.Parse(m[2].Value+m[4].Value));};
Action<float[]>print=x=>{Console.WriteLine("{0} {1} {2}i",x[0],x[1]>=0?"+":"-",Math.Abs(x[1]));};
Func<float[],float[],float[]>add=(x,y)=>C(x[0]+y[0],x[1]+y[1]);
Func<float[],float[],float[]>sub=(x,y)=>C(x[0]-y[0],x[1]-y[1]);
Func<float[],float[],float[]>mul=(x,y)=>C(x[0]*y[0]-x[1]*y[1],x[0]*y[1]+x[1]*y[0]);
Func<float[],float[],float[]>div=(x,y)=>mul(x,C(y[0],-y[1])).Select(_=>_/(y[0]*y[0]+y[1]*y[1])).ToArray();

var a = read();
var b = read();
var c = C(3, -7);
var d = C(2, 5);
var e = div(a,c);
var f = mul(b,d);
var g = add(e,f);
print(g);

Not sure about the character counting definition, really…

\$\endgroup\$
1
\$\begingroup\$

Haskell 698

Counted everything before main. This question struck me as being too straight forward, so I did everything in my power to make my answer more interesting. Also Haskell borks if you redefine Prelude functions (div, print, read), so I renamed those.

import Control.Arrow 
import Control.Monad
import Control.Applicative
import Data.List.Split
a=uncurry(***)
f!g=a(f,g)
j=join(!)
f%b=a$j f b
add=((+)%)
sub=((-)%)
o=join
g#h=(*)<$>g.fst<*>h.snd
c=o.curry
m=add<$>c((fst#fst)!(snd#fst))<*>c((negate.(snd#snd))!(fst#snd))
mul=curry m
b`d1v`c=b`mul`(j (/uncurry(+)(j(^2)c)).second negate$c)
s :: (Show a) => (a, a) -> String
s=uncurry(++).first(++" ").second((++"i").(let g('-':x)="- "++x;g x="+ "++x in g)).j show
pr1nt :: (Show a) => (a, a) -> IO ()
pr1nt=putStrLn.s
t=filter(`notElem`" i")
re4d :: (Read a, Num a) => String -> (a, a)
re4d s|elem '+'s=(\[x,y]->j(read.t)(x,y)).splitOn"+"$s
      |0<1=(\[x,y]->read!(negate.read.t)$(x,y)).splitOn"-"$s

main= do
  let p = pr1nt
  a <- fmap re4d getLine
  b <- fmap re4d getLine
  p $ a `add` b
  p $ a `sub` b
  p $ a `mul` b
  p $ a `d1v` b

This spits a "non-exhaustive pattern-match in input" if the input given does not match "a (+|-) bi".

\$\endgroup\$
2
  • \$\begingroup\$ I'm fairly certain that you could do import Prelude hiding (div,print,read) as long as you don't plan on ever using those functions. If you do need them you can probably import them qualified. \$\endgroup\$
    – Matt
    Commented Oct 15, 2012 at 17:48
  • \$\begingroup\$ I know that's possible, I just didn't want to sacrifice char count :P. \$\endgroup\$
    – walpen
    Commented Oct 15, 2012 at 21:31
0
\$\begingroup\$

Pascal, 317 bytes

The simple data type complex belongs to Extended Pascal’s vocabulary (ISO standard 10206). However, Standard Pascal – as laid out by ISO standard 7185 – does not support complex numbers. Complying with the task specification, the following implementation is restricted to SP.

Note, the routine read had to be renamed to readComplex, otherwise Pascal’s built‑in read procedure will become unavailable. Similarly, the word div is a reserved word (identifies the integer division operator) and had to be renamed, too (for the purposes of scoring a three-letter identifier has been chosen).

program basicOperationsOnComplexNumbers(input, output);
    type
        complex = record
                r: real;
                j: real;    
            end;
        { In _Standard_ Pascal a `function` can
          only return _simple_ data type values. }
        complexReference = ↑complex;
    
    var
        { These are used for the test in the main block.
          Standard Pascal has a strict block order
          (`label` → `const` → `type` → `var` → routines → `begin … end`)
          therefore these are “global” variables. }
        x, y: complex;
    
    { Reads a `complex` in Cartesian (rectangular) format. }
    procedure readComplex(var x: complex);
        begin
            { The `Ln` is necessary so the rest of the line
              (in particular the `'i'`) is consumed, too. }
            readLn(x.r,x.j)
        end;
    
    { Prints a `complex` in Cartesian (rectangular) format. }
    procedure print(x: complex);
        begin
            { For non-negative `real` values a space (`' '`) is printed.
              Therefore we will need to print the plus sign ourselves. }
            write(x.r);if x.j≥0 then write('+');write(x.j,'i')
        end;
    
    { Returns the sum of two `complex` numbers. }
    function add(x, y: complex): complexReference;
        var
            { The implicitly defined result variable
              bearing the function’s name (here `'add'`)
              accepts only _complete_ assignments
              (this ensures there are no _partially_ defined results).
              Therefore we will need a temporary result variable. }
            z: complexReference;
        begin
            x.r≔x.r+y.r;x.j≔x.j+y.j;new(z);z↑≔x;add≔z
        end;
    
    { Returns the difference of two `complex` numbers. }
    function sub(x, y: complex): complexReference;
        var
            z: complexReference;
        begin
            x.r≔x.r−y.r;x.j≔x.j−y.j;new(z);z↑≔x;sub≔z
        end;
    
    { Returns the product of two `complex` numbers. }
    function mult(x, y: complex): complexReference;
        var
            z: complexReference;
        begin
            new(z);z↑.r≔x.r*y.r−x.j*y.j;z↑.j≔x.r*y.j+x.j*y.r;mult≔z
        end;
    
    { Returns the quotient of two `complex` numbers.
      CAUTION: DOES NOT CHECK FOR NON-ZERO DIVISOR. }
    function quo(x, y: complex): complexReference;
        var
            z: complexReference;
        begin
            new(z);with z↑do begin
            r≔y.r*y.r+y.j*y.j;j≔r;r≔(x.r*y.r+x.j*y.j)/r;j≔(x.j*y.r−x.r*y.j)/j
            end;quo≔z
        end;
    
    { === MAIN ========================================================= }
    begin
        readComplex(x);
        readComplex(y);
        
        write('       sum: '); print( add(x, y)↑); writeLn;
        write('difference: '); print( sub(x, y)↑); writeLn;
        write('   product: '); print(mult(x, y)↑); writeLn;
        write('  quotient: '); print( quo(x, y)↑); writeLn
    end.

Example input:

-3.00 + 2.00i
-2.72 + 0.00i

Example output (subject to implementation-defined behavior):

       sum: -5.7200000000000006e+00+ 2.0000000000000000e+00i
difference: -2.7999999999999980e-01+ 2.0000000000000000e+00i
   product:  8.1600000000000001e+00-5.4400000000000004e+00i
  quotient:  1.1029411764705881e+00-7.3529411764705876e-01i

RosettaCode │ FreePascal Compiler Wiki │ GNU Pascal Compiler Programmer’s Guide

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.