-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmagic_index.cpp
133 lines (121 loc) · 3.48 KB
/
magic_index.cpp
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
#include <iostream>
#include <optional>
#include <span>
#include <initializer_list>
#include <concepts>
#include <chrono>
template<std::integral T>
static std::optional<std::size_t> findMagicIndex1(const std::span<T> array)
{
for(std::size_t i = 0; i < array.size(); ++i)
if(static_cast<T>(i) == array[i])
return { i };
return { };
}
template<std::integral T>
static std::optional<std::size_t> findMagicIndex2(const std::span<T> array, std::size_t start, std::size_t end)
{
if(start >= end) return { };
std::size_t midIndex = (end + start) / 2;
if(static_cast<T>(midIndex) == array[midIndex])
return { midIndex };
auto result = findMagicIndex2(array, start, midIndex);
if(result)
return result;
return findMagicIndex2(array, midIndex + 1, end);
}
template<std::integral T>
static std::optional<std::size_t> findMagicIndex2(const std::span<T> array)
{
return findMagicIndex2(array, 0, array.size());
}
template<std::integral T>
static std::optional<std::size_t> findMagicIndex3(const std::span<T> array, std::size_t start, std::size_t end)
{
if(start >= end) return { };
std::size_t midIndex = (end - start) / 2;
if(array[midIndex] == static_cast<T>(midIndex))
return { midIndex };
auto result = findMagicIndex3(array, start, midIndex);
if(result)
return result;
// The right half of the array might contain a magic index only if value at 'midIndex' is less than 'midIndex'
if(array[midIndex] < static_cast<T>(midIndex))
return findMagicIndex3(array, midIndex + 1, end);
return { };
}
template<std::integral T>
static std::optional<std::size_t> findMagicIndex3(const std::span<T> array)
{
return findMagicIndex3(array, 0, array.size());
}
template<std::integral T>
struct Solution1
{
std::optional<std::size_t> operator()(const std::span<T> array)
{
return findMagicIndex1(array);
}
};
template<std::integral T>
struct Solution2
{
std::optional<std::size_t> operator()(const std::span<T> array)
{
return findMagicIndex2(array);
}
};
template<std::integral T>
struct Solution3
{
std::optional<std::size_t> operator()(const std::span<T> array)
{
return findMagicIndex3(array);
}
};
template<typename T>
static std::ostream& operator<<(std::ostream& stream, const std::span<const T> array)
{
stream << "{ ";
for(decltype(array.size()) i = 0; const auto& value : array)
{
stream << value;
if(++i < array.size())
stream << ", ";
}
stream << " }";
return stream;
}
template<template<typename> typename Sol, typename T>
static void runFindMagicIndex(const std::span<T> array)
{
std::cout << "Input: " << array << "\n";
auto start = std::chrono::steady_clock::now();
std::optional<std::size_t> index = Sol<T> { } (array);
auto end = std::chrono::steady_clock::now();
auto elapsed = std::chrono::duration_cast<std::chrono::duration<float, std::milli>>(end - start).count();
if(index)
std::cout << "Output: " << *index << "\n";
else
std::cout << "Output: not found\n";
std::cout << "Time taken: " << elapsed << " ms\n";
}
template<std::integral T>
static void run(std::initializer_list<T> array)
{
static std::size_t runCount = 0;
std::cout << "-----------RUN: " << runCount << " ----------\n";
++runCount;
std::cout << "**Solution 1**\n";
runFindMagicIndex<Solution1>(std::span { array });
std::cout << "**Solution 2**\n";
runFindMagicIndex<Solution2>(std::span { array });
std::cout << "**Solution 3**\n";
runFindMagicIndex<Solution3>(std::span { array });
}
int main()
{
run<int>({ -4, -2, 1, 0, 4, 5, 12, 12, 54, 65, 100 });
run<int>({ -4, -3, 100, 200 });
return 0;
}