Ode to expressiveness

Reading /r/dailyprogrammer I found a typical programming problem, a change calculator: write a function that given certain amount of money, returns the minimal number of coins to change the money. The arbitrary values for those coins are 1, 5, 10 and 20 (this problem can be also be rendered in cents, but is pretty much the same). However, what most surprised me, it was compare the solutions provided by the users in JavaScript and Cobol:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

IDENTIFICATION DIVISION.

PROGRAM-ID.chgmaker.

DATE-WRITTEN.1/28/2013.

*AUTHOR Dr_Legacy

*REMARKS reddit dailyprogrammer challenge#119

ENVIRONMENT DIVISION.

CONFIGURATION SECTION.

INPUT-OUTPUT SECTION.

FILE-CONTROL.

DATA DIVISION.

FILE SECTION.

WORKING-STORAGE SECTION.

01AMOUNT-INPICX(10).

01NFRAC PICX(5).

01NFRAC9 REDEFINES NFRAC PIC9(5).

01N1 PICX(10).

01N2 PICX(10)VALUE ZEROS.

01N29 REDEFINES N2 PIC9(10).

01CHARCOUNT PIC99VALUE ZERO.

01CC2 PIC99VALUE ZERO.

01AMOUNT-WORKING PIC9(11)V99.

01QUARTER-VALUE PIC9V99VALUE0.25.

01DIME-VALUE PIC9V99VALUE0.10.

01NICKEL-VALUE PIC9V99VALUE0.05.

01PENNY-VALUE PIC9V99VALUE0.01.

01QUARTER-COUNT PIC9(11)VALUE ZERO.

01DIME-COUNT PIC9VALUE ZERO.

01NICKEL-COUNT PIC9VALUE ZERO.

01PENNY-COUNT PIC9VALUE ZERO.

01AMOUNT-OUT PICZ(10)9.

*****

PROCEDURE DIVISION.

*****

MAIN-LOGIC SECTION.

MAIN-BEGIN.

DISPLAY"CHANGE MAKING PROGRAM".

DISPLAY"ENTER AMOUNT".

ACCEPT AMOUNT-IN.

IFAMOUNT-INEQUAL SPACE THEN

GO TOEXIT-PROGRAM.

***old COBOL doesn'thave any really fancy stringfunctions

UNSTRING AMOUNT-IN

DELIMITED BY ALL SPACES

OR"."

INTO N1,NFRAC.

INSPECT NFRAC REPLACING ALL SPACE BY ZERO.

COMPUTE AMOUNT-WORKING ROUNDED=NFRAC9/100000.

IFN1 NOTEQUAL SPACE THEN

PERFORM VARYING CHARCOUNT FROM10BY-1

UNTIL N1(CHARCOUNT:1)NOT=SPACE

***reference modification.YOU KIDS HAVE IT EASYITELL YOU

END-PERFORM

COMPUTE CC2=10-CHARCOUNT+1

STRINGN1(1:CHARCOUNT)DELIMITED SIZE INTO N2

POINTER CC2

ADD AMOUNT-WORKING N29 GIVING AMOUNT-WORKING

.

DISPLAY"".

DIVIDE AMOUNT-WORKING BY QUARTER-VALUE

GIVING QUARTER-COUNT

REMAINDER AMOUNT-WORKING.

IFQUARTER-COUNT ISGREATER THAN ZERO

MOVE QUARTER-COUNT TOAMOUNT-OUT

DISPLAY"QUARTERS: "AMOUNT-OUT.

DIVIDE AMOUNT-WORKING BY DIME-VALUE

GIVING DIME-COUNT

REMAINDER AMOUNT-WORKING.

IFDIME-COUNT ISGREATER THAN ZERO

MOVE DIME-COUNT TOAMOUNT-OUT

DISPLAY"DIMES: "AMOUNT-OUT.

DIVIDE AMOUNT-WORKING BY NICKEL-VALUE

GIVING NICKEL-COUNT

REMAINDER AMOUNT-WORKING.

IFNICKEL-COUNT ISGREATER THAN ZERO

MOVE NICKEL-COUNT TOAMOUNT-OUT

DISPLAY"NICKELS: "AMOUNT-OUT.

DIVIDE AMOUNT-WORKING BY PENNY-VALUE

GIVING PENNY-COUNT

REMAINDER AMOUNT-WORKING.

IFPENNY-COUNT ISGREATER THAN ZERO

MOVE PENNY-COUNT TOAMOUNT-OUT

DISPLAY"PENNIES: "AMOUNT-OUT.

IFAMOUNT-WORKING ISGREATER THAN ZERO

DISPLAY"wtf ".

MAIN-END-PROGRAM.

GO TOEXIT-PROGRAM.

MAIN-EXIT.

EXIT.

/

DRLEGACY-MISC SECTION.

EXIT-PROGRAM.

EXIT PROGRAM.

Wow. 108 lines of code. Now let’s see a possible solution in JavaScript:

1

2

3

4

5

functioncoins(amount){

return[25,10,5,1].map(function(coin){

return[~~(amount/coin),amount%=coin][0];

});

}

What I really love about JavaScript is its expresiveness. Of course you could also write a similar program with Python or LISP or whatever, but let’s just take JavaScript as example. The things I like are:

Literal notation. Rather than creating an agreggator object or a collection, we can declare our array of coins in-place and call immeditaly the function .map upon it.

1

[25,10,5,1].map

Using literal expressions let us easily adapt or expand our solution. If the problem changes and now we need to return coins of 3, 7 and 15 value, we can do it right away!

1

[3,7,15]

Returning function types. Since functions in JavaScript are first class citizens, we can return them inside other functions. This let us specify clearly that our main function, coins(), is actually returning the result of certain algorithm or function

1

2

3

return[25,10,5,1].map(function(coin){

return[~~(amount/coin),amount%=coin][0];

});

Closures. A closure is an internal function or variable having access to the scope of an external function. We see a clear example of that when in our inner return type we build a two dimensional array, using the second position to re-assign the value of amount

1

amount%=coin

…ok, perhaps building a two dimensional array, making an assignment in the second position and returning only the first element [0] is kinda jerkoff, but closures are nevertheless quite powerful.

Add properties to objects on the fly. My own solution to this problem looks kinda like this (pretty much the same but more readable I believe)

1

2

3

4

5

6

7

8

functioncoins2(amount){

varres={};

[25,10,5,1].map(function(coin){

res[coin]=Math.floor(amount/coin);

amount=amount%coin;

});

returnres;

}

We can see the assignment of res[coin] as inserting a new key into an array, but the possibilities are much more powerful than that, since resis an object I could easily added a function to it or do basically whatever I want. Awesome!