leetcode 295 median in stream, runtime error? - c++

Leetcode 295 is to find median in a data stream.
I want to use two heaps to implement it. which can make add a data from stream in O(logn), get the percentile in O(1).
left_heap is a min_heap which used to save the left data of requied percentile.
right_heap used to save data which is larger than percentile.
In class SortedStream, which can make add data o(logn) and make findMedian o(1)
#include <iostream>
#include <vector>
#include <climits>
#include <algorithm>
using namespace std;
class SortedStream {
public:
SortedStream(double percent, size_t rsize = 65536*16) : percent_(percent), reserve_size_(rsize) {
init();
}
void push(double v) { // time complexity, o(logn)
++size_;
double left_top = left_data_.back();
if (left_data_.empty() || v <= left_top) { left_data_.push_back(v); std::push_heap(left_data_.begin(), left_data_.end(), std::less<double>{}); }
else { right_data_.push_back(v); std::push_heap(right_data_.begin(), right_data_.end(), std::greater<double>{}); }
size_t idx = size_ * percent_ + 1;
size_t left_size = left_data_.size();
if (idx < left_size) {
// pop left top into right
std::pop_heap(left_data_.begin(), left_data_.end(), std::less<double>{});
double left_top = left_data_.back();
left_data_.pop_back();
right_data_.push_back(left_top);
std::push_heap(right_data_.begin(), right_data_.end(), std::less<double>{});
} else if (idx > left_size) {
// pop right top into left
std::pop_heap(right_data_.begin(), right_data_.end(), std::greater<double>{});
double right_top = right_data_.back();
right_data_.pop_back();
left_data_.push_back(right_top);
std::push_heap(left_data_.begin(), left_data_.end(), std::greater<double>{});
}
}
void init() {
size_t lsize = reserve_size_ * percent_ + 2;
left_data_.reserve(lsize);
right_data_.reserve(reserve_size_ - lsize + 2);
max_ = INT_MIN;
min_ = INT_MAX;
std::make_heap(left_data_.begin(), left_data_.end(), std::less<double>{});
std::make_heap(right_data_.begin(), right_data_.end(), std::greater<double>{});
size_ = 0;
}
size_t size() const { return size_; }
double max() const { return max_; }
double min() const { return min_; }
double percentile() const { // time complexity o(1)
return left_data_.back();
}
public:
double percent_;
size_t size_;
double max_, min_;
std::vector<double> left_data_, right_data_;
size_t reserve_size_;
};
class MedianFinder {
public:
MedianFinder() : ss(0.5){}
void addNum(int num) {ss.push(num);}
double findMedian() {return ss.percentile();}
SortedStream ss;
};
int main() {
MedianFinder* obj = new MedianFinder();
for (size_t i = 0; i< 15; ++i) {
obj->addNum(i);
double param_2 = obj->findMedian();
cout << "i = " << i << " median = " << param_2 << endl;
}
}
it's ok to run in my laptop, but when i submit in leetcode, it comes out:
Line 863: Char 45: runtime error: applying non-zero offset 18446744073709551608 to null pointer (stl_iterator.h)
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior /usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/bits/stl_iterator.h:868:45
I never see this error.
can you help on this?

I like your (OP's) idea that Heap can be used to solve the task, heap of smaller and larger values. Also as #ArminMontigny suggested one can use std::priority_queue instead of plain heap, because priority queue is based on heap and adds easy to use helper methods. Regular heap is a kind of low-level backend for priority queue.
Based on these two suggestions and inspired by your interesting question I decide to implement short (30 lines) solution for your task (it uses random numbers as example input):
Try it online!
#include <queue>
#include <random>
#include <iostream>
int main() {
std::mt19937_64 rng{123};
std::priority_queue<int> smaller;
std::priority_queue<int, std::vector<int>, std::greater<int>> larger;
for (size_t i = 0; i < 100; ++i) {
int n = rng() % 1000;
if (smaller.empty() || n <= smaller.top())
smaller.push(n);
else
larger.push(n);
while (smaller.size() + 1 < larger.size()) {
smaller.push(larger.top());
larger.pop();
}
while (larger.size() + 1 < smaller.size()) {
larger.push(smaller.top());
smaller.pop();
}
double median = smaller.size() == larger.size() ?
(smaller.top() + larger.top()) / 2.0 :
smaller.size() < larger.size() ? larger.top() : smaller.top();
std::cout << "n = " << n << " med = " << median << " | ";
if ((i + 1) % 4 == 0)
std::cout << std::endl;
}
}
Output:
n = 504 med = 504 | n = 771 med = 637.5 | n = 101 med = 504 | n = 790 med = 637.5 |
n = 380 med = 504 | n = 388 med = 446 | n = 888 med = 504 | n = 406 med = 455 |
n = 53 med = 406 | n = 240 med = 397 | n = 749 med = 406 | n = 438 med = 422 |
n = 566 med = 438 | n = 238 med = 422 | n = 741 med = 438 | n = 817 med = 471 |
n = 810 med = 504 | n = 376 med = 471 | n = 816 med = 504 | n = 503 med = 503.5 |
n = 599 med = 504 | n = 264 med = 503.5 | n = 704 med = 504 | n = 132 med = 503.5 |
n = 740 med = 504 | n = 391 med = 503.5 | n = 563 med = 504 | n = 778 med = 533.5 |
n = 768 med = 563 | n = 136 med = 533.5 | n = 964 med = 563 | n = 368 med = 533.5 |
n = 653 med = 563 | n = 941 med = 564.5 | n = 976 med = 566 | n = 680 med = 582.5 |
n = 546 med = 566 | n = 200 med = 564.5 | n = 387 med = 563 | n = 698 med = 564.5 |
n = 562 med = 563 | n = 251 med = 562.5 | n = 257 med = 562 | n = 735 med = 562.5 |
n = 822 med = 563 | n = 212 med = 562.5 | n = 576 med = 563 | n = 368 med = 562.5 |
n = 783 med = 563 | n = 964 med = 564.5 | n = 234 med = 563 | n = 805 med = 564.5 |
n = 952 med = 566 | n = 162 med = 564.5 | n = 936 med = 566 | n = 493 med = 564.5 |
n = 88 med = 563 | n = 313 med = 562.5 | n = 580 med = 563 | n = 274 med = 562.5 |
n = 353 med = 562 | n = 701 med = 562.5 | n = 882 med = 563 | n = 249 med = 562.5 |
n = 19 med = 562 | n = 482 med = 554 | n = 327 med = 546 | n = 402 med = 525 |
n = 379 med = 504 | n = 521 med = 512.5 | n = 977 med = 521 | n = 550 med = 533.5 |
n = 434 med = 521 | n = 82 med = 512.5 | n = 581 med = 521 | n = 134 med = 512.5 |
n = 532 med = 521 | n = 860 med = 526.5 | n = 562 med = 532 | n = 225 med = 526.5 |
n = 907 med = 532 | n = 837 med = 539 | n = 671 med = 546 | n = 785 med = 548 |
n = 593 med = 550 | n = 533 med = 548 | n = 471 med = 546 | n = 352 med = 539.5 |
n = 388 med = 533 | n = 532 med = 532.5 | n = 310 med = 532 | n = 135 med = 532 |
n = 323 med = 532 | n = 81 med = 526.5 | n = 849 med = 532 | n = 577 med = 532 |
n = 643 med = 532 | n = 956 med = 532.5 | n = 204 med = 532 | n = 383 med = 532 |
Regarding your question about Sanitizer error - this sanitizer is a part of CLang. You can download Clang yourself and try it out on your home laptop, to reproduce exactly same error.
To get same error add option -fsanitize=undefined, when compiling using CLang at home.
For Windows CLang can be downloaded from this page. Also on Windows if you have great package manager Chocolatey, then you can install CLang + LLVM through short command choco install llvm.
For Linux CLang can be installed through sudo apt install clang.
Also you can use great online website GodBolt, by this link, at given link I already chosen CLang for compilation and put necessary options -std=c++11 -O0 -fsanitize=undefined, so you have just to start coding in the window to the left-handside when you open the link.

You have one minor problem
In the line
double left_top = left_data_.back();
At the very beginning, the std::vector "left_data" will be empty. If you try to access the last element of an empty vector, you will get an runtime error.
If you modify this line to for example:
double left_top = left_data_.empty()?0.0:left_data_.back();
Then your program will work as you expect it to work.
I personally find the approach a a little bit too complicated. Maybe you could use a std::multiset or a std::priority_queue. Especially the std::priority_queue will also implement a max-heap and a min-hep for you, without out the overhead of calling std::vectors heap functions.
But I am still in favor of the std::multiset . . .

Related

Decompressing a netCDF file

I have a comrpessed netCDF file called in.nc with a (_DeflateLevel=4). I want to decompress the file.
I've already tried using the following command but it doesn't change anything:
nccopy -d 0 in.nc out.nc
Here are the in.nc specifications:
time_counter = UNLIMITED ; // (12 currently)
y = 552 ;
x = 552 ;
variables:
float Q16c(time_counter, y, x) ;
Q16c:long_name = "Deep Sediment Particulate organic Matter" ;
Q16c:units = "mg C/m2" ;
Q16c:online_operation = "average" ;
Q16c:interval_operation = "900 s" ;
Q16c:interval_write = "1 month" ;
Q16c:cell_methods = "time: mean (interval: 900 s)" ;
Q16c:_FillValue = 1.e+20f ;
Q16c:missing_value = 1.e+20f ;
Q16c:coordinates = "time_centered nav_lat nav_lon" ;
Q16c:_Storage = "chunked" ;
Q16c:_ChunkSizes = 1, 552, 552 ;
Q16c:_DeflateLevel = 4 ;
Q16c:_Endianness = "little" ;

Interpreting mysql connector c++ field Value's raw 4 bytes to a date

In the current database, I select all from a pet table, there is exactly 1 record and it has two DATE field, one for the birth date and one for the death date.
My record has a value for the birth date and a NULL for the death date.
Header files
#include <iostream>
#include <mysqlx/xdevapi.h>
using directives
using ::std::cout;
using ::std::endl;
using namespace ::mysqlx;
First I connect the session
Session sess("<session uri>");
Then I output some information about the table
std::string schema_name = sess.getDefaultSchemaName();
cout << "schema_name : " << schema_name << endl;
Schema db_schema = sess.getSchema( schema_name, true );
std::string table_name { "pet" };
Table pet_table = db_schema.getTable( table_name, true );
cout << "table " << table_name << " has " << pet_table.count() << " row(s). is_view=" << std::boolalpha << pet_table.isView() << std::endl;
Finally I prepare my query
std::stringstream query_writer;
query_writer << "SELECT * FROM " << table_name;
std::string query_str = query_writer.str();
SqlStatement query = sess.sql(query_str);
Then get my results:
SqlResult res = query.execute();
Row pet;
while( (pet = res.fetchOne()) ) {
int count = res.getColumnCount();
for( int column = 0; column < count; column++ ) {
const Column& current_column = res.getColumn( column );
const Value& field_value = pet[column];
const std::string& field_name = current_column.getColumnName();
Type field_type= current_column.getType();
// HOW to Interpret this?
const bytes& raw_bytes = field_value.getRawBytes();
}
}
It was pointed out to me that DATE fields encoding are described in this link:
https://dev.mysql.com/doc/internals/en/date-and-time-data-type-representation.html
but non-null DATE field raw_bytes is 4 bytes long, not 3 bytes long, so where is the correct documentation?
Originally, the table had a DATE field, now it is changed for a DATETIME field:
mysql> describe pet;
+---------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+---------+-------------+------+-----+---------+-------+
| name | varchar(20) | YES | | NULL | |
| owner | varchar(20) | YES | | NULL | |
| species | varchar(20) | YES | | NULL | |
| sex | char(1) | YES | | NULL | |
| birth | datetime | YES | | NULL | |
| death | datetime | YES | | NULL | |
+---------+-------------+------+-----+---------+-------+
6 rows in set (0.00 sec)
Here are the records in the tabe:
mysql> select * from pet;
+----------+-------+---------+------+---------------------+-------+
| name | owner | species | sex | birth | death |
+----------+-------+---------+------+---------------------+-------+
| Puffball | Diane | hamster | f | 1999-03-30 00:00:00 | NULL |
+----------+-------+---------+------+---------------------+-------+
1 row in set (0.00 sec)
We had the same issue and developed the following C++20 helper methods for production use with mysqlx (MySQL Connector/C++ 8.0 X DevAPI) to properly read DATE, DATETIME and TIMESTAMP fields:
#pragma once
#include <vector>
#include <cstddef>
#include <chrono>
#include <mysqlx/xdevapi.h>
namespace mysqlx {
static inline std::vector<uint64_t>
mysqlx_raw_as_u64_vector(const mysqlx::Value& in_value)
{
std::vector<uint64_t> out;
const auto bytes = in_value.getRawBytes();
auto ptr = reinterpret_cast<const std::byte*>(bytes.first);
auto end = reinterpret_cast<const std::byte*>(bytes.first) + bytes.second;
while (ptr != end) {
static constexpr std::byte carry_flag{0b1000'0000};
static constexpr std::byte value_mask{0b0111'1111};
uint64_t v = 0;
uint64_t shift = 0;
bool is_carry;
do {
auto byte = *ptr;
is_carry = (byte & carry_flag) == carry_flag;
v |= std::to_integer<uint64_t>(byte & value_mask) << shift;
++ptr;
shift += 7;
} while (is_carry && ptr != end && shift <= 63);
out.push_back(v);
}
return out;
}
static inline std::chrono::year_month_day
read_date(const mysqlx::Value& value)
{
const auto vector = mysqlx_raw_as_u64_vector(value);
if (vector.size() < 3)
throw std::out_of_range{"Value is not a valid DATE"};
return std::chrono::year{static_cast<int>(vector.at(0))} / static_cast<int>(vector.at(1)) / static_cast<int>(vector.at(2));
}
static inline std::chrono::system_clock::time_point
read_date_time(const mysqlx::Value& value)
{
const auto vector = mysqlx_raw_as_u64_vector(value);
if (vector.size() < 3)
throw std::out_of_range{"Value is not a valid DATETIME"};
auto ymd = std::chrono::year{static_cast<int>(vector.at(0))} / static_cast<int>(vector.at(1)) / static_cast<int>(vector.at(2));
auto sys_days = std::chrono::sys_days{ymd};
auto out = std::chrono::system_clock::time_point(sys_days);
auto it = vector.begin() + 2;
auto end = vector.end();
if (++it == end)
return out;
out += std::chrono::hours{*it};
if (++it == end)
return out;
out += std::chrono::minutes{*it};
if (++it == end)
return out;
out += std::chrono::seconds{*it};
if (++it == end)
return out;
out += std::chrono::microseconds{*it};
return out;
}
} //namespace
Which can then be used as follows:
auto row = table.select("datetime", "date").execute().fetchOne();
auto time_point = read_date_time(row[0]);
auto year_month_day = read_date(row[1]);
I've read your question and the whole discussion on dev.mysql before making my own topic because I had exactly the same question. It's been a while since you asked this, but here is the answer: How is date encoded/stored in MySQL?
In a nutshell, the last two bytes are the month and the day respectively, and the first two encode the year so that you can calculate them using the following equation:
N1 - 128 + N2 * 128
It seems that the logic of encoding is to erase the most significant bit of the first number and to write the second number from this erased bit like this:
2002 from 210 and 15:
1101 0010 -> _101 0010;
0000 1111 + _101 0010 -> 0111 1101 0010
2048 from 128 and 16:
1000 0000 -> _000 0000
0001 0000 + _000 0000 -> 1000 0000 0000
From here (getBytes() part) https://dev.mysql.com/doc/dev/connector-cpp/8.0/classmysqlx_1_1abi2_1_1r0_1_1_row.html
I've found out that:
The raw bytes are as received from the server. In genral the value
is represented using x-protocol encoding that corresponds to the type
and other meta-data of the given column. This meta-data can be
accessed via Column object returned by RowResult#getColumn() method.
Values of type DATE and TIMESTAMP use the same representation as
DATETIME, with time part empty in case of DATE values.

Timer interpretation

If i run Stata's timer:
timer on 1
(code lines)
timer off 1
timer list 1
I cannot read the result:
timer list 1
1: 325.15 / 2 = 162.5725
The next time the timer produces:
timer list 1
1: 622.47 / 3 = 207.4883
It seems it is dividing 325.15 by 2, dividing 622.47 by 3.
Why? What does pre-division number mean? What does post-division number mean?
I tried reading the manual on the topic and other information online but I couldn't find any answer.
The first number is the time elapsed in seconds and the second is the number of times the timer was turned on and off.
Using the example from the help file:
program tester
version 13
forvalues repeat=1(1)100 {
timer on 1
quietly summarize price
timer off 1
}
timer list 1
return list
end
And the toy dataset auto.dta:
sysuse auto, clear
timer clear 1
tester
1: 0.01 / 100 = 0.0001
scalars:
r(N) = 74
r(sum_w) = 74
r(mean) = 6165.256756756757
r(Var) = 8699525.974268788
r(sd) = 2949.495884768919
r(min) = 3291
r(max) = 15906
r(sum) = 456229
r(t1) = .008
r(nt1) = 100
tester
1: 0.02 / 200 = 0.0001
scalars:
r(N) = 74
r(sum_w) = 74
r(mean) = 6165.256756756757
r(Var) = 8699525.974268788
r(sd) = 2949.495884768919
r(min) = 3291
r(max) = 15906
r(sum) = 456229
r(t1) = .017
r(nt1) = 200
If you clear the timer again:
timer clear 1
tester
1: 0.01 / 100 = 0.0001
scalars:
r(N) = 74
r(sum_w) = 74
r(mean) = 6165.256756756757
r(Var) = 8699525.974268788
r(sd) = 2949.495884768919
r(min) = 3291
r(max) = 15906
r(sum) = 456229
r(t1) = .007
r(nt1) = 100

Subsetting using a Bool-Vector in Rcpp-Function (problems of a Rcpp Beginner...)

Problem description (think of a membership with different prices for adults and kids):
I am having two data sets, one containing age and a code. A second dataframe "decodes" the codes to numeric values dependent someone is a kid or adult. I know want to match the codes in both data sets and receive a vector that contains numeric values for each customer in the data set.
I can make this work with standard R-functionalities, but since my original data contains several million observations I would like to speed up computation using the Rcpp package.
Unfortunately I do not succeed, especially how to perform the subsetting based on a logical vector as I would do it in R. I am quite new to Rcpp and have no experience with C++ so I am maybe missing some very basic point.
I attached a minimum working example for R and appreciate any kind of help or explanation!
library(Rcpp)
raw_data = data.frame(
age = c(10, 14, 99, 67, 87, 54, 12, 44, 22, 8),
iCode = c("code1", "code2", "code3", "code1", "code4", "code3", "code2", "code5", "code5", "code3"))
decoder = data.frame(
code = c("code1","code2","code3","code4","code5"),
kid = c(0,0,0,0,100),
adult = c(100,200,300,400,500))
#-------- R approach (works, but takes ages for my original data set)
calc_value = function(data, decoder){
y = nrow(data)
for (i in 1:nrow(data)){
position_in_decoder = (data$iCode[i] == decoder$code)
if (data$age[i] > 18){
y[i] = decoder$adult[position_in_decoder]
}else{
y[i] = decoder$kid[position_in_decoder]
}
}
return(y)
}
y = calc_value(raw_data, decoder)
#--------- RCPP approach (I cannot make this one work) :(
cppFunction(
'NumericVector calc_Rcpp(DataFrame df, DataFrame decoder) {
NumericVector age = df["age"];
CharacterVector iCode = df["iCode"];
CharacterVector code = decoder["code"];
NumericVector adult = decoder["adult"];
NumericVector kid = decoder["kid"];
const int n = age.size();
LogicalVector position;
NumericVector y(n);
for (int i=0; i < n; ++i) {
position = (iCode[i] == code);
if (age[i] > 18 ) y[i] = adult[position];
else y[i] = kid[position];
}
return y;
}')
There is no need to go for C++ here. Just use R properly:
raw_data = data.frame(
age = c(10, 14, 99, 67, 87, 54, 12, 44, 22, 8),
iCode = c("code1", "code2", "code3", "code1", "code4", "code3", "code2", "code5", "code5", "code3"))
decoder = data.frame(
code = c("code1","code2","code3","code4","code5"),
kid = c(0,0,0,0,100),
adult = c(100,200,300,400,500))
foo <- merge(raw_data, decoder, by.x = "iCode", by.y = "code")
foo$res <- ifelse(foo$age > 18, foo$adult, foo$kid)
foo
#> iCode age kid adult res
#> 1 code1 10 0 100 0
#> 2 code1 67 0 100 100
#> 3 code2 14 0 200 0
#> 4 code2 12 0 200 0
#> 5 code3 54 0 300 300
#> 6 code3 99 0 300 300
#> 7 code3 8 0 300 0
#> 8 code4 87 0 400 400
#> 9 code5 44 100 500 500
#> 10 code5 22 100 500 500
That should also work for large data sets.

Boost Spirit: parse a section of an input

I have thousands of lines of input, that each line consists of 3 ints and a comma at the and that look like this:
5 6 10,
8 9 45,
.....
How can I create a grammar that parses only a certain section of an input, for example first 100 lines or from line 1000 to 1200 and ignores the rest.
My grammar currently looks like this:
qi::int_ >> qi::int_ >> qi::int_ >> qi::lit(",");
But obviously it parses the whole input.
You could just seek up to the interesting point and parse 100 lines there.
A sketch on how to skip 100 lines from just spirit:
Live On Coliru
#define BOOST_SPIRIT_DEBUG
#include <boost/spirit/include/qi.hpp>
#include <boost/fusion/adapted/std_tuple.hpp>
#include <tuple>
namespace qi = boost::spirit::qi;
int main() {
using It = boost::spirit::istream_iterator;
using Tup = std::tuple<int, int, int>;
It f(std::cin >> std::noskipws), l;
std::vector<Tup> data;
using namespace qi;
if (phrase_parse(f, l,
omit [ repeat(100) [ *(char_ - eol) >> eol ] ] >> // omit 100 lines
repeat(10) [ int_ >> int_ >> int_ >> ',' >> eol ], // parse 10 3-tuples
blank, data))
{
int line = 100;
for(auto tup : data)
std::cout << ++line << "\t" << boost::fusion::as_vector(tup) << "\n";
}
}
When tested with some random input like
od -Anone -t d2 /dev/urandom -w6 | sed 's/$/,/g' | head -200 | tee log | ./test
echo ============== VERIFY WITH sed:
nl log | sed -n '101,110p'
It'll print something expected, like:
101 (15400 5215 -20219)
102 (26426 -17361 -6618)
103 (-15311 -6387 -5902)
104 (22737 14339 16074)
105 (-28136 21003 -11594)
106 (-11020 -32377 -4866)
107 (-24024 10995 22766)
108 (3438 -19758 -10931)
109 (28839 22032 -7204)
110 (-25237 23224 26189)
============== VERIFY WITH sed:
101 15400 5215 -20219,
102 26426 -17361 -6618,
103 -15311 -6387 -5902,
104 22737 14339 16074,
105 -28136 21003 -11594,
106 -11020 -32377 -4866,
107 -24024 10995 22766,
108 3438 -19758 -10931,
109 28839 22032 -7204,
110 -25237 23224 26189,
Just because I want to learn more about Spirit X3, and because the worlds would like to know more about this upcoming version of the library, here's a more intricate version that shows a way to dynamically filter lines according to some expression.
In this case the lines are handled by this handler:
auto handle = [&](auto& ctx) mutable {
using boost::fusion::at_c;
if (++line_no % 10 == 0)
{
auto& attr = x3::_attr(ctx);
data.push_back({ at_c<0>(attr), at_c<1>(attr), at_c<2>(attr) });
}
};
As you'd expect every 10th line is included.
Live On Coliru
#include <boost/spirit/home/x3.hpp>
#include <boost/spirit/include/support_istream_iterator.hpp>
#include <iostream>
namespace x3 = boost::spirit::x3;
int main() {
using It = boost::spirit::istream_iterator;
It f(std::cin >> std::noskipws), l;
struct Tup { int a, b, c; };
std::vector<Tup> data;
size_t line_no = 0;
auto handle = [&](auto& ctx) mutable {
using boost::fusion::at_c;
if (++line_no % 10 == 0)
{
auto& attr = x3::_attr(ctx);
data.push_back({ at_c<0>(attr), at_c<1>(attr), at_c<2>(attr) });
}
};
if (x3::phrase_parse(f, l, (x3::int_ >> x3::int_ >> x3::int_) [ handle ] % (',' >> x3::eol), x3::blank))
{
for(auto tup : data)
std::cout << tup.a << " " << tup.b << " " << tup.c << "\n";
}
}
Prints e.g.
g++ -std=c++1y -O2 -Wall -pedantic -pthread main.cpp -o test
od -Anone -t d2 /dev/urandom -w6 | sed 's/$/,/g' | head -200 | tee log | ./test
echo ============== VERIFY WITH perl:
nl log | perl -ne 'print if $. % 10 == 0'
-8834 -947 -8151
13789 -20056 -11874
6919 -27211 -19472
-7644 18021 13523
-20120 16923 -11419
27772 31149 14005
3540 4894 -24790
10698 10223 -30397
-22533 -32437 -13665
25813 3264 -16414
11453 11955 18268
5092 27052 17930
10915 6493 20432
-14380 -6085 -25430
18599 6710 17279
22049 22259 -32189
1048 14621 6452
-24996 10856 29429
3537 -26338 19623
-4117 6617 14009
============== VERIFY WITH perl:
10 -8834 -947 -8151,
20 13789 -20056 -11874,
30 6919 -27211 -19472,
40 -7644 18021 13523,
50 -20120 16923 -11419,
60 27772 31149 14005,
70 3540 4894 -24790,
80 10698 10223 -30397,
90 -22533 -32437 -13665,
100 25813 3264 -16414,
110 11453 11955 18268,
120 5092 27052 17930,
130 10915 6493 20432,
140 -14380 -6085 -25430,
150 18599 6710 17279,
160 22049 22259 -32189,
170 1048 14621 6452,
180 -24996 10856 29429,
190 3537 -26338 19623,
200 -4117 6617 14009,