Skip to content

Instantly share code, notes, and snippets.

@kovrov
Created July 26, 2010 22:37
Show Gist options
  • Save kovrov/491364 to your computer and use it in GitHub Desktop.
Save kovrov/491364 to your computer and use it in GitHub Desktop.
privet_q1
5: D F
1: C D A
4: B A
7: E A
9: B C
350: A B
#include <string>
#include <fstream>
#include <vector>
#include <map>
#include <iostream>
using namespace std;
vector<string> split(const string& value, const string& separator)
{
vector<string> res;
string::size_type pos_start = 0;
string::size_type pos_end = value.find_first_of(separator);
while (string::npos != pos_end)
{
if (pos_end - pos_start > 0)
res.push_back(value.substr(pos_start, pos_end - pos_start));
pos_start = pos_end + 1;
pos_end = value.find_first_of(separator, pos_start);
}
if (value.length() > pos_start)
res.push_back(value.substr(pos_start));
return res;
}
string join(vector<string>& value, const string& separator)
{
string res;
for (vector<string>::iterator it = value.begin(); it != value.end(); it++)
{
res += (*it) + separator;
}
return res;
}
int main()
{
ifstream ifs("c:/data/desktop/data.txt");
string line;
map<string, vector<string> > res;
while (getline(ifs, line))
{
vector<string> digit_and_letters = split(line, ":");
vector<string> letters = split(digit_and_letters[1], " ");
for (vector<string>::iterator it = letters.begin(); it != letters.end(); it++)
{
res[*it].push_back(digit_and_letters[0]);
}
}
for (map<string, vector<string> >::iterator it = res.begin(); it != res.end(); it++)
{
cout << (*it).first << ": " << join((*it).second, " ") << endl;
}
return 0;
}
import std.stream;
import std.string;
import std.stdio;
void main()
{
Stream file = new BufferedFile("c:/data/desktop/data.txt");
scope (exit) file.close();
string[][string] res;
foreach (string line; file)
{
string[] digit_and_letters = split(line, ":");
foreach (string letter; split(digit_and_letters[1]))
{
res[letter.dup] ~= digit_and_letters[0].dup;
}
}
foreach (string letter; res.keys.sort)
{
writefln("%s: %s", letter, join(res[letter], " "));
}
}
#!/usr/bin/perl
use strict;
my $fh = exists $ARGV[0] ? $ARGV[0] : 'datafile';
open(FH, $fh) || die qq/Cannot open <$fh> for reading: "$!"/;
local $/;
$_ = <FH>;
my $h = {};
map push(@{$h->{$_}}, $1), split(/\s+/, substr($2, 1)) while /^(\d+):((?:\s+[A-Z])+)/mg;
print qq/$_: ${\join(' ', sort @{$h->{$_}})}\n/ foreach sort keys %$h;
#!/usr/bin/python
file = open('c:/data/desktop/data.txt', 'r')
try:
res = {}
for line in file:
(digit, letters) = line.split(':')
for char in letters.split():
if char in res:
res[char] += digit
else:
res[char] = [digit]
finally:
file.close()
for char, digits in sorted(res.iteritems()):
print "%s: %s" % (char, " ".join(digits))
import std.stream;
import std.string;
import std.stdio;
void main()
{
Stream file = new BufferedFile("c:/data/desktop/data.txt");
scope (exit) file.close();
const max_chars = 'z' - 'A';
char[1024][max_chars] res;
foreach (string line; file)
{
string[] digit_and_letters = split(line, ":");
foreach (string letter; split(digit_and_letters[1]))
{
res[cast(uint)letter[0]-'A'][0] = digit_and_letters[0][0];
}
}
foreach (letter, chars; res)
{
if (chars[0])
writefln("%s: %s", cast(char)(letter+'A'), chars[0]);
}
}
#include <iostream>
#include <vector>
int main()
{
using namespace std;
vector< vector<int> > data;
data.reserve(256);
int number;
char colon;
while ( (cin >> number >> colon) && colon == ':' )
{
char buffer[1024];
while ( cin.get(buffer, sizeof(buffer)) && cin.gcount() != 0 )
{
for ( int i = 0; i < cin.gcount(); ++i )
{
if ( buffer[i] != ' ' )
{
size_t index = buffer[i]&0xff;
if ( index > data.size() )
data.resize(index+1);
data[index].push_back(number);
}
}
}
cin.clear();
}
for ( vector< vector<int> >::iterator i = data.begin(); i != data.end(); ++i )
{
if ( !i->empty() )
{
cout << char(i-data.begin()) << ':';
for ( vector<int>::const_iterator j = i->begin(); j != i->end(); ++j )
cout << ' ' << *j;
cout << '\n';
}
}
}
@limansky
Copy link

Haskell solution without using of any parsing libraries:

import System.IO
import qualified Data.Map as M
import Data.Char (isDigit, isAlpha)

calculate :: String -> M.Map String [Int]
calculate c = foldr processLine M.empty $ lines c
    where processLine v m = foldr processDigits m (letters rest)
              where (num, rest) = span isDigit v  
                    letters s = words $ dropWhile (not . isAlpha) s
                    processDigits k m = M.insertWith (++) k [val] m
                    val = read num

prettify m = unlines $ M.foldrWithKey f [] m
    where f k v a = (k ++ ": " ++ (unwords $ map show v)) : a

main = do 
    h <- openFile "data.txt" ReadMode
    d <- hGetContents h
    putStr . prettify $ calculate d

@limansky
Copy link

The second option is to use parsing library like Parsec. This way allows to make parser code more clear, more extensible and to check the input file format.

import System.IO
import qualified Data.Map as M
import Text.ParserCombinators.Parsec
import Control.Monad (liftM)
import Data.Char (isSpace)

file = endBy line newline

line = do
    num <- liftM read (many1 digit) :: GenParser Char st Int
    string ": "
    chars <- letter `sepBy` char ' '
    return $ zip chars (repeat [num])

trimR = reverse . dropWhile isSpace . reverse

-- To reduce parser complexity the trailing spaces are removed before parsing
calculate s = case parse file "" (unlines . map trimR . lines $ s) of
    Right v -> prettify $ M.fromListWith (++) (concat v)
    Left  _ -> "Cannot parse data."

prettify m = unlines $ M.foldrWithKey f [] m
    where f k v a = (k : ": " ++ (unwords $ map show v)) : a

main = do
    h <- openFile "data.txt" ReadMode
    d <- hGetContents h
    putStr . calculate $ d ++ "\n"

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment