-
Notifications
You must be signed in to change notification settings - Fork 5
/
euler-node.coffee
170 lines (143 loc) · 4.23 KB
/
euler-node.coffee
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
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
# Written on Node 5.x but should work most places
_ = require "underscore"
fs = require "fs"
# Helper/utilities
add = (a, b) -> a + b
mult = (a, b) -> a * b
sum = (xs) -> _(xs).reduce add, 0
product = (xs) -> _(xs).reduce mult, 1
isEven = (n) -> 0 == n % 2
atoi = (s) -> parseInt s, "decimal, bitches"
String.prototype.startsWith = (prefix) -> 0 == this.indexOf prefix
String.prototype.reverse = () -> @split("").reverse().join("")
loadFileSync = (fn) ->
size = fs.statSync(fn).size
fd = fs.openSync fn, "r"
buffer = new Buffer size
offset = 0 # Within the buffer
remaining = size
position = 0 # Within the file
while true
bytesRead = fs.readSync fd, buffer, offset, remaining, position
offset += bytesRead
position += bytesRead
remaining = remaining - bytesRead
break if remaining <= 0
fs.closeSync fd
buffer.toString "utf-8"
###########################
# LET THE SOLUTIONS BEGIN #
###########################
# Euler #1
# Answer: 233168
#
# If we list all the natural numbers below 10 that are multiples of 3 or 5, we
# get 3, 5, 6 and 9. The sum of these multiples is 23.
#
# Find the sum of all the multiples of 3 or 5 below 1000.
exports.euler1 = -> sum (n for n in [3..999] when n % 3 == 0 or n % 5 == 0)
# Euler #2
# Answer: 4613732
#
# Each new term in the Fibonacci sequence is generated by adding the previous
# two terms. By starting with 1 and 2, the first 10 terms will be:
#
# 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, ...
#
# By considering the terms in the Fibonacci sequence whose values do not
# exceed four million, find the sum of the even-valued terms.
exports.euler2 = ->
acc = 0
a = 0
b = 1
while true
curFib = a + b
break unless curFib <= 4000000
if isEven curFib
acc += curFib
a = b
b = curFib
acc
# Euler #4
# Answer:
#
# A palindromic number reads the same both ways. The largest palindrome made
# from the product of two 2-digit numbers is 9009 = 91 99.
#
# Find the largest palindrome made from the product of two 3-digit numbers.
#
isPalindrome = (n) ->
s = "" + n
s.reverse() == s
# NOTE: Could problably be optimized but this will be more than fast enough.
exports.euler4 = ->
result = 0
for i in [100..999]
for j in [100..999]
product = i * j
result = product if product > result and isPalindrome product
result
# Euler #31
# Answer: 73682
#
# In England the currency is made up of pound, £, and pence, p, and there are
# eight coins in general circulation:
#
# 1p, 2p, 5p, 10p, 20p, 50p, £1 (100p) and £2 (200p).
#
# It is possible to make £2 in the following way:
#
# 1x£1 + 1x50p + 2x20p + 1x5p + 1x2p + 3x1p
#
# How many different ways can £2 be made using any number of coins?
ways = (target, coins) ->
a = (0 for n in [0..target])
a[0] = 1
for c in coins
for n in [c..(target + 1)]
a[n] += a[n - c]
a[target]
exports.euler31 = -> ways 200, [1, 2, 5, 10, 20, 50, 100, 200]
# Euler #8
# Answer: 40824
#
# Find the greatest product of five consecutive digits in the 1000-digit
# number.
#
# <number redacted, found in inputs/8/number.txt>
exports.euler8 = ->
e8Number = loadFileSync "inputs/8/number.txt"
windowWidth = 5
maxProduct = 0
lastIndex = e8Number.length - windowWidth - 1
for index in [0..lastIndex]
window = e8Number.substring index, index + windowWidth
window = (c for c in window)
xs = _(window).map atoi
p = product xs
maxProduct = p if p > maxProduct
maxProduct
####################
# END OF SOLUTIONS #
####################
#
# Everything below is the "main" machinery.
#
# Technically there's an exploit here but I don't care.
run = (number) ->
label = "euler" + number
displayEuler label, exports[label]
displayEuler = (label, euler) ->
console.log label + ": " + euler()
run_all = ->
for own label, euler of exports
if label.startsWith "euler"
displayEuler label, euler
if require.main == module
do main = ->
args = process.argv.slice 2 # Get rid of "node/coffee" and filename.
if args.length <= 0
do run_all
else
for number in args
run number