Skip to content

Commit 3329ddb

Browse files
committed
Add Codility, CTCI and update folder structure
1 parent cfdf3fe commit 3329ddb

File tree

87 files changed

+1693
-2
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

87 files changed

+1693
-2
lines changed
+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
def solution(a)
2+
start_vals, end_vals = [], []
3+
a.each_with_index do |element, i|
4+
start_vals << (i - element)
5+
end_vals << (i + element)
6+
end
7+
start_vals.sort!
8+
end_vals.sort!
9+
10+
end_vals.each do |end_val|
11+
12+
end
13+
end
14+
15+
def intersect?(arr, index_a, index_b)
16+
min_a, min_b = arr[index_a] - index_a, arr[index_b] - index_b
17+
#puts "min_a: #{min_a}, min_b: #{min_b}"
18+
range_a = ((index_a - arr[index_a])..(index_a + arr[index_a])).to_a
19+
range_b = ((index_b - arr[index_b])..(index_b + arr[index_b])).to_a
20+
#puts "range_a: #{range_a}, range_b: #{range_b}"
21+
return true if range_a.include?(min_b) || range_b.include?(min_a)
22+
false
23+
end
24+
# test code
25+
=begin
26+
require_relative "./1-disc_intersections.rb"
27+
a = [1, 2, 5, 1, 20]
28+
intersect?(a, 0, 3)
29+
=end
+101
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
# iteration #1, O(n**2) (naive)
2+
=begin
3+
[1, 5, 2, 1, 4, 0]
4+
0 1 2 3 4 5
5+
--> center => radius = { 0: 1, 1: 5, 2: 2, 3: 1, 4: 4, 5: 0 }
6+
rages = [ [-1, 1], [-4, 6], [1, 4], [2, 5], [0, 8], [5, 5] ]
7+
8+
1 (-1, 1):
9+
5 (-4, 6): a starts inside b, so count += 1
10+
11+
5 (-4, 6):
12+
1 (-1, 1):
13+
=end
14+
15+
def solution(a)
16+
# naive - loop through and check all others
17+
count = 0
18+
a.each_with_index do |disc_out, i_out|
19+
a.drop(i_out+1).each_with_index do |disc_in, i_in|
20+
next if i_out == i_in
21+
count += 1 if overlaps?(range(a, i_out), range(a, i_in))
22+
end
23+
end
24+
count
25+
end
26+
27+
def range(arr, i)
28+
((i - arr[i])..(i + arr[i])).to_a
29+
end
30+
31+
def overlaps?(range_a, range_b)
32+
return true if range_a.last >= range_b.first
33+
end
34+
35+
a = [1, 5, 2, 1, 4, 0]
36+
solution(a)
37+
38+
39+
=begin
40+
## want to find the # of intersections of the intervals [i-A[i], i+A[i]].
41+
* If discs 1, 2, 3, 4, 5 exist, 1 and 2 can only intersect once.
42+
* Disc n can't intersect with itself.
43+
44+
## strategy
45+
* Maintain a sorted array (call it starts) containing all the ``i-A[i]`` values
46+
* Maintain another sorted array (call it ends) containing the end values ``i+A[i]``
47+
* Walk the array ``starts``
48+
* For the current interval, do a binary search to see where the right endpoint
49+
of the interval (i.e. i+A[i]) will go, called the RANK. Then you know it intersects
50+
all the
51+
52+
53+
=end
54+
# iteration #2 - (hopefully) optinal
55+
def solution(a)
56+
# want to know the number of discs that start, stop
57+
# at each position. Then we can calculate how many
58+
# intersections there are.
59+
60+
# create a hash with default start, stop values set to 0
61+
events = Hash.new{ |h, k| h[k] = {:start => 0, :stop => 0}}
62+
63+
# store the start, stop vals for each element in a
64+
a.each_index do |i|
65+
events[i - a[i]][:start] += 1
66+
events[i + a[i]][:stop] += 1
67+
end
68+
69+
# so now event[i][:start] is the start val for a[i]
70+
# sort the events
71+
sorted_events = events.sort_by { |index, val| index}
72+
sorted_events.map! {|n| n[1]}
73+
74+
# so now sorted_events[i] tells us how many starts and stops occured at (i, 0).
75+
76+
# iterate over our sorted array of hashes which tell us how many discs start and end at each position. There are two cases we need to worry about:
77+
# 1) how many discs are already going when the new disc starts: (e[:start] * past_start)
78+
# 2) if multiple discs start at the same position (e[:start] * (e[:start]-1) / 2)
79+
80+
# 1) if there are 3 discs that we're in the middle of and a new disc starts, it intersects with all 3 of them. If there are 3 discs we're in the middle of and 2 new discs start, each of them will intersect with the 3 existing ones, making six interactions.
81+
# 2) If multiple discs start at the same location, some math is required. It's groups of 2, so the number of intersections at each index is n*(n-1)/2 - for if multiple discs start at that index - plus n*past_starts for when discs are already in progress when we start a new one. Add them all together and you have your solution.
82+
83+
past_starts = 0
84+
intersects = 0
85+
sorted_events.each do |event|
86+
intersects += event[:start] * (event[:start]-1) / 2 + event[:start] * past_starts
87+
past_starts += event[:start]
88+
past_starts -= event[:stop]
89+
end
90+
91+
intersects
92+
#puts "events: #{events}"
93+
end
94+
95+
96+
97+
98+
99+
100+
101+

Diff for: 1_codility/1_disc_intersections/notes.md

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
### The Problem (from [Codility]())
2+
3+
### Strategy
4+
5+
### Solution - Ruby
6+
### Solution - Java
7+
### Solution - Go
8+
9+
### Thoughts
10+

Diff for: 1_codility/2_missing_integer/2-missing_integer.rb

+60
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
# iteration 1
2+
def solution(a)
3+
# write your code in Ruby 2.2
4+
# the answer can't be greater than 100,000, so we don't care about values larger than that
5+
# so remove them:
6+
a.delete_if {|x| x > 100000 || x < 1}
7+
elements = {}
8+
a.each do |element|
9+
elements[element.to_s] = true
10+
end
11+
1.upto(100000).each do |i|
12+
return i unless elements[i.to_s]
13+
end
14+
end
15+
16+
# score: 88% (failed the case where the array is literally just (1..100,000).to_a which makes the answer 100,001
17+
# time: 13 minutes
18+
19+
# iteration 2
20+
def solution(a)
21+
# write your code in Ruby 2.2
22+
# max 100,000 elements, so don't care about >100,000 vals# also don't care about negatives
23+
a.delete_if{ |x| x < 0 || x > 100000 }
24+
# likely decreased the number of elements so might as well limit the number of loops necessary
25+
# could also do .uniq here to potentially decrease it further, but I think that's unnecessary
26+
max_count = a.size
27+
28+
# keep track of elements via keys in a hash
29+
included_vals = {}
30+
a.each do |element|
31+
included_vals[element.to_s] ||= true
32+
end
33+
1.upto(max_count+1).each do |i|
34+
return i unless included_vals[i.to_s]
35+
end
36+
37+
end
38+
39+
# score: 100%
40+
# time: 13:43 (wrote on paper first)
41+
42+
43+
44+
45+
46+
47+
48+
49+
50+
51+
52+
53+
54+
55+
56+
57+
58+
59+
60+

Diff for: 1_codility/2_missing_integer/notes.md

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
### The Problem (from [Codility]())
2+
3+
### Strategy
4+
5+
### Solution - Ruby
6+
### Solution - Java
7+
### Solution - Go
8+
9+
### Thoughts
10+

Diff for: 1_codility/3_count_div/3-count_div.rb

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
def solution(a, b, k)
2+
if a % k == 0
3+
# first is a, then a+k, then a+2k then a+3k... up to b
4+
# in other words, (B-A)/K + 1
5+
return (b-a)/k + 1
6+
else
7+
# first is the multiple of K right before A, and so on.
8+
# so (B - (A - A%K)) / 2
9+
return (b-(a-a%k))/k
10+
end
11+
end

Diff for: 1_codility/3_count_div/notes.md

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
### The Problem (from [Codility]())
2+
3+
### Strategy
4+
5+
### Solution - Ruby
6+
### Solution - Java
7+
### Solution - Go
8+
9+
### Thoughts
10+

Diff for: 1_codility/4_distinct/4-distinct.rb

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
def solution(a)
2+
# can't be more than 100,000 values, so we could track them all in a hash etc.
3+
# I think I can just loop through and store the elements as keys in a hash with
4+
# val true, then count the size of the resulting hash.
5+
elements = {}
6+
a.each do |element|
7+
elements[element.to_s] ||= true
8+
end
9+
elements.size
10+
end

Diff for: 1_codility/4_distinct/notes.md

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
### The Problem (from [Codility]())
2+
3+
### Strategy
4+
5+
### Solution - Ruby
6+
### Solution - Java
7+
### Solution - Go
8+
9+
### Thoughts
10+

Diff for: 1_codility/5_dominator/5-dominator.rb

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
def solution(a)
2+
# I'm not sure about the O(1) space requirement but my idea is to store counts in a hash table
3+
# with keys corresponding to the elements that have appeared, and values for their counts.
4+
return -1 unless a.is_a?(Array) && a.size > 0
5+
6+
val_counts = {}
7+
a.each_with_index do |element, i|
8+
val_counts[element.to_s] ||= 0
9+
val_counts[element.to_s] += 1
10+
return i if val_counts[element.to_s] > (a.size/2)
11+
end
12+
-1
13+
14+
end

Diff for: 1_codility/5_dominator/notes.md

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
### The Problem (from [Codility]())
2+
3+
### Strategy
4+
5+
### Solution - Ruby
6+
### Solution - Java
7+
### Solution - Go
8+
9+
### Thoughts
10+

Diff for: 1_codility/6_max_profit/6-max_profit.rb

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
def solution(a)
2+
return 0 if a.size < 2
3+
return 0 if a.size == 2 && a[1] <= a[0]
4+
5+
low_so_far = a.first
6+
max_profit = 0
7+
# for each price in a
8+
a.each do |price|
9+
# set max_profit to price-low_so_far if that difference is greater than the current max_profit
10+
diff_here = price - low_so_far
11+
max_profit = diff_here if diff_here > max_profit
12+
low_so_far = price if price < low_so_far
13+
end
14+
max_profit
15+
end

Diff for: 1_codility/6_max_profit/notes.md

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
### The Problem (from [Codility]())
2+
3+
### Strategy
4+
5+
### Solution - Ruby
6+
### Solution - Java
7+
### Solution - Go
8+
9+
### Thoughts
10+

Diff for: 1_codility/7_max_slice_sum/7-max_slice_sum.go

+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package subarray
2+
3+
func subarray(A []int) int {
4+
// keep track of:
5+
// runningMax
6+
// maxHere
7+
// simpleMax
8+
// totalMax
9+
10+
if len(A) == 0 { return -1 }
11+
if len(A) == 1 { return A[0] }
12+
var runningMax int = 0
13+
var maxHere int
14+
var simpleMax int = A[0]
15+
var totalMax int = 0
16+
17+
for i := 0; i < len(A); i++ {
18+
maxHere = intMax(runningMax+A[i], A[i])
19+
runningMax = intMax(maxHere, 0)
20+
simpleMax = intMax(simpleMax, A[i])
21+
totalMax = intMax(runningMax, totalMax)
22+
}
23+
24+
if totalMax == 0 { return simpleMax }
25+
return totalMax
26+
}
27+
28+
func intMax(a int, b int) int {
29+
if a > b {
30+
return a
31+
} else {
32+
return b
33+
}
34+
}

Diff for: 1_codility/7_max_slice_sum/7-max_slice_sum.rb

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
def max_slice_sum(a)
2+
# return -1 in case of invalid input
3+
return -1 unless a.is_a?(Array) && a.size > 0
4+
# if there's only one element, return it
5+
return a.first if a.size == 1
6+
7+
# sum we're currently adding to
8+
running_sum = 0
9+
max_so_far = 0
10+
11+
a.each do |el|
12+
# max at this element
13+
max_current = (el + running_sum) > el ? (el + running_sum) : el
14+
running_sum = max_current > 0 ? max_current : 0
15+
max_so_far = max_so_far > running_sum ? max_so_far : running_sum
16+
end
17+
18+
# deal with the situation where there are no positive elements
19+
max_so_far == 0 ? a.max : max_so_far
20+
end
21+

0 commit comments

Comments
 (0)