LINUX.ORG.RU

История изменений

Исправление wota, (текущая версия) :

~$ cat 1.cpp
#include <algorithm>
#include <cstdint>
#include <cstdio>
#include <cstring>
#include <vector>

#define BUF_SIZE 65536
FILE* in;
	
const char* getline( uint32_t pos, char* buf )
{
	fseek( in, pos, SEEK_SET );
	return fgets( buf, BUF_SIZE, in );
}

int main( int argc, char** argv )
{
	in = fopen( argv[ 1 ], "rb" );
	
	char	 buf0[ BUF_SIZE ];
	char	 buf1[ BUF_SIZE ];
	uint32_t offset = 0;
	
	std::vector<uint32_t> lines;
	
	char buf[ BUF_SIZE ];
	while( fgets( buf, BUF_SIZE, in ) )
	{
		uint32_t new_offset = ftell( in );
		
		auto pos = std::lower_bound( 
			lines.begin(), lines.end(), offset,
			[&]( uint32_t a, uint32_t b ) { int c = strcmp( getline( a, buf0 ), getline( b, buf1 ) ); return c ? c < 0 : a < b; } );

		lines.insert( pos, offset );
		fseek( in, offset = new_offset, SEEK_SET );
	}
	
	FILE* out = fopen( argv[ 2 ], "wt" );
	for( uint32_t pos : lines )
	{
		getline( pos, buf0 );
		fwrite( buf0, strlen( buf0 ), 1, out );
	}
	
	fclose( out );
}

~$ g++ -std=c++11 -Ofast 1.cpp && time ./a.out big.txt out.txt

real	0m1.857s
user	0m0.692s
sys	0m1.164s
~$ du -h big.txt
6,2M	big.txt
~$ du -h out.txt
6,2M	out.txt
~$ wc -l out.txt 
128457 out.txt
~$ wc -l big.txt 
128457 big.txt

и что забавно - проигрывает самому тупому решению в лоб, хотя понятно, что на больших размерах вставка станет гораздо дороже

П.С. хотя проигрывает наверняка из-за мусора в конце выхлопа

Исходная версия wota, :

~$ cat 1.cpp
#include <algorithm>
#include <cstdint>
#include <cstdio>
#include <cstring>
#include <vector>

#define BUF_SIZE 65536
FILE* in;
	
const char* getline( uint32_t pos, char* buf )
{
	fseek( in, pos, SEEK_SET );
	return fgets( buf, BUF_SIZE, in );
}

int main( int argc, char** argv )
{
	in = fopen( argv[ 1 ], "rb" );
	
	char	 buf0[ BUF_SIZE ];
	char	 buf1[ BUF_SIZE ];
	uint32_t offset = 0;
	
	std::vector<uint32_t> lines;
	
	char buf[ BUF_SIZE ];
	while( fgets( buf, BUF_SIZE, in ) )
	{
		uint32_t new_offset = ftell( in );
		
		auto pos = std::lower_bound( 
			lines.begin(), lines.end(), offset,
			[&]( uint32_t a, uint32_t b ) { int c = strcmp( getline( a, buf0 ), getline( b, buf1 ) ); return c ? c < 0 : a < b; } );

		lines.insert( pos, offset );
		fseek( in, offset = new_offset, SEEK_SET );
	}
	
	FILE* out = fopen( argv[ 2 ], "wt" );
	for( uint32_t pos : lines )
	{
		getline( pos, buf0 );
		fwrite( buf0, strlen( buf0 ), 1, out );
	}
	
	fclose( out );
}

~$ g++ -std=c++11 -Ofast 1.cpp && time ./a.out big.txt out.txt

real	0m1.857s
user	0m0.692s
sys	0m1.164s
~$ du -h big.txt
6,2M	big.txt
~$ du -h out.txt
6,2M	out.txt
~$ wc -l out.txt 
128457 out.txt
~$ wc -l big.txt 
128457 big.txt

и что забавно - проигрывает самому тупому решению в лоб, хотя понятно, что на больших размерах вставка станет гораздо дороже