-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathzipfsong_cpp_fast.cpp
More file actions
108 lines (95 loc) · 3.2 KB
/
zipfsong_cpp_fast.cpp
File metadata and controls
108 lines (95 loc) · 3.2 KB
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
//*******************************************
// Spotify puzzle #2 - Zipf's song
// Gustav Andersson - 200921
// gustav.k.andersson@gmail.com
//
// Solved by dumping the input from memory quickly and without processing. Don't copy
// any string data, but use string_views that point into this memory (an improvement
// over old c-style string)
//*******************************************
#include <iostream>
#include <vector>
#include <algorithm>
#include <functional>
#include <chrono>
#include <string_view>
// Save a few cycles by replacing atoi() with a version that assumes positive integers and no characters in string
inline uint64_t unsafe_strtol(const std::string_view& s)
{
uint64_t res{0};
for (auto c : s)
{
res = (res * 10) + (c - '0');
}
return res;
}
class Song
{
public:
Song(std::string_view name, int64_t rating) : _name(name), _rating(rating) {}
const std::string_view& name() const { return _name; };
friend bool operator< (const Song& lhs, const Song& rhs){ return lhs._rating < rhs._rating; };
friend bool operator> (const Song& lhs, const Song& rhs){ return rhs < lhs; };
private:
std::string_view _name;
int64_t _rating;
};
void parse_songs(const int songs, std::vector<Song>& song_list, char* mem, size_t mem_size)
{
song_list.reserve(songs);
std::cin.read(mem, mem_size);
const char* c = mem;
const char* end = mem + mem_size;
std::string_view plays;
int song_pos = 1;
int str_len = 0;
while (song_pos <= songs && ++c < end)
{
if (*c == ' ')
{
plays = std::string_view(c - str_len, str_len);
str_len = 0;
++c;
}
else if (*c == '\n')
{
auto listens = unsafe_strtol(plays);
auto title = std::string_view(c - str_len, str_len);
song_list.emplace_back(title, listens * song_pos++);
str_len = 0;
++c;
}
++str_len;
}
return;
}
void print_songs(const std::vector<Song>& song_list, int no_songs)
{
for (int i = 0; i < no_songs; ++i)
{
std::cout << song_list[i].name() << '\n';
}
return;
}
int main()
{
std::chrono::steady_clock::time_point startTime = std::chrono::steady_clock::now();
std::ios::sync_with_stdio (false);
std::string input;
std::getline(std::cin, input);
auto input_view = std::string_view(input);
int pos = input_view.find(" ");
int no_songs = unsafe_strtol(input_view.substr(0, pos));
int no_outputs = unsafe_strtol(input_view.substr(pos + 1));
// Assume max 30 chars per title and 20 chars for number of plays + whitespaces
size_t mem_size = no_songs * 50;
char* string_area = static_cast<char*>(malloc(mem_size));
std::vector<Song> song_list;
parse_songs(no_songs, song_list, string_area, mem_size);
stable_sort(song_list.begin(), song_list.end(), std::greater<Song>());
print_songs(song_list, no_outputs);
delete string_area;
std::chrono::steady_clock::time_point endTime = std::chrono::steady_clock::now();
std::cout << "Ex. time: " << std::chrono::duration_cast<std::chrono::milliseconds>(endTime - startTime).count() << " ms" << std::endl;
return 0;
}