Changeset 410

Show
Ignore:
Timestamp:
08/01/06 15:35:32 (4 years ago)
Author:
vasi
Message:

damn gdb sucks

Files:
1 modified

Legend:

Unmodified
Added
Removed
  • icfp2006/trunk/black/black.cpp

    r408 r410  
    11#include <cstdio> 
     2#include <iostream> 
     3#include <iomanip> 
     4#include <fstream> 
     5 
     6#include <string> 
    27#include <vector> 
     8#include <iterator> 
     9#include <ext/numeric> 
     10 
    311using namespace std; 
     12using namespace __gnu_cxx; 
     13 
     14 
     15// Type magic 
     16typedef char (&no_tag)[1];  
     17typedef char (&yes_tag)[2];  
     18 
     19#define HAS_TRAIT(trait) \ 
     20        template <typename T> struct has_##trait { \ 
     21                template <typename U> static no_tag helper(...); \ 
     22                template <typename U> static yes_tag helper(int, \ 
     23                        typename U::trait* = 0); \ 
     24                enum { value = sizeof(helper<T>(0)) == sizeof(yes_tag) }; \ 
     25        }; \ 
     26 
     27HAS_TRAIT(const_iterator); 
     28 
     29 
     30// Dumping 
     31template <typename T> void dump(const T& n, ostream &os = cout); 
     32template <typename T> void dump_short(const T& n, ostream& os = cout); 
    433 
    534 
     
    1140                : dest(p_dest), plinks(p_plinks) { } 
    1241}; 
    13  
    14 class BlackKnot { 
    15         vector<MarbleResult> m_results; 
     42ostream& operator<<(ostream& os, const MarbleResult& r) { 
     43        return (os << "{ dest: " << r.dest << ",  plinks: " << r.plinks << " }"); 
     44} 
     45 
     46 
     47struct Switcher { 
     48        unsigned line; 
     49        unsigned pos; 
     50         
     51        Switcher(unsigned p_line = 0, unsigned p_pos = 0) 
     52                : line(p_line), pos(p_pos) { } 
     53}; 
     54ostream& operator<<(ostream& os, const Switcher& sw) { 
     55        return (os << "{ line: " << sw.line << ",  pos: " << sw.pos << " }"); 
     56} 
     57 
     58 
     59struct BlackKnot { 
     60        vector<MarbleResult> results; 
     61         
     62        typedef vector<Switcher> Solution; 
     63         
     64        BlackKnot(const char *specfile); 
     65         
     66        Solution solve() const; 
     67        void output_solution(const Solution& soln, ostream& os = cout) const; 
     68         
     69        unsigned size() const { return results.size(); } 
     70}; 
     71ostream& operator<<(ostream& os, const BlackKnot& black); 
     72 
     73 
     74class Solver {   
     75        const BlackKnot& black; 
     76         
     77        BlackKnot::Solution     switchers; 
     78        vector<unsigned>        marbles;                // What marble in each position? 
     79        vector<unsigned>        plinks_left; 
     80        unsigned                        line, pos; 
     81         
     82        bool findSwitcher(); 
     83        bool addSwitcher(); 
     84        void removeSwitcher(); 
     85         
     86        void doSwitch(const Switcher& sw, bool forward); 
     87        bool checkDone() const; 
    1688         
    1789public: 
    18         BlackKnot(const char *specfile); 
    19         void dump() const; 
    20 }; 
     90        Solver(const BlackKnot& p_black); 
     91        BlackKnot::Solution solve(); 
     92 
     93        friend ostream& operator<<(ostream& os, const Solver& s); 
     94}; 
     95ostream& operator<<(ostream& os, const Solver& s); 
    2196 
    2297 
    2398int main(int argc, char **argv) { 
    24         const char *spec = argc >= 1 ? argv[1] : NULL; 
    25         BlackKnot knot(spec); 
    26         knot.dump(); 
    27 //      knot.solve(); 
     99        const char *specfile = argc >= 1 ? argv[1] : NULL; 
     100        BlackKnot knot(specfile); 
     101        dump(knot.results); 
     102         
     103        BlackKnot::Solution soln = knot.solve(); 
     104        knot.output_solution(soln); 
     105         
     106        return 0; 
    28107} 
    29108 
    30109 
    31110BlackKnot::BlackKnot(const char *specfile) { 
    32         FILE *file = specfile ? fopen(specfile, "r") : stdin; 
    33         unsigned source, dest, plinks; 
    34          
    35         while (fscanf(file, " %u -> ( %u , %u ) \n", &source, &dest, &plinks) 
    36                         == 3) { 
    37                 if (source >= m_results.size()) { 
    38                         m_results.resize(source + 1); 
    39                 } 
    40                 m_results[source] = MarbleResult(dest, plinks); 
    41         } 
    42          
    43         fclose(file); 
    44 } 
    45  
    46 void BlackKnot::dump() const { 
    47         for (size_t i = 0; i < m_results.size(); ++i) { 
    48                 printf("%zu -> (%u,%u)\n", i, m_results[i].dest, m_results[i].plinks); 
    49         } 
    50 } 
     111        ifstream infile; 
     112        istream* is; 
     113        if (specfile) { 
     114                infile.open(specfile); 
     115                is = &infile; 
     116        } else { 
     117                is = &cin; 
     118        }        
     119         
     120        string s; 
     121        while (getline(*is, s)) { 
     122                // No good C++ replacement for scanf 
     123                unsigned source, dest, plinks; 
     124                if (sscanf(s.c_str(), " %u -> ( %u , %u ) \n", 
     125                                &source, &dest, &plinks) != 3) { 
     126                        cerr << "Error reading: '" << s << "'" << endl; 
     127                        break; 
     128                } 
     129                 
     130                if (source >= results.size()) { 
     131                        results.resize(source + 1); 
     132                } 
     133                results[source] = MarbleResult(dest, plinks); 
     134        } 
     135         
     136        if (infile.is_open()) { 
     137                infile.close(); 
     138        } 
     139} 
     140 
     141void BlackKnot::output_solution(const BlackKnot::Solution& soln, 
     142                ostream& os) const { 
     143        BlackKnot::Solution::const_iterator iter = soln.begin(); 
     144        unsigned line = 0; 
     145         
     146        while (iter != soln.end()) { 
     147                unsigned pos = 0; 
     148                while (pos < size()) { 
     149                        if (iter != soln.end() 
     150                                        && iter->line == line && iter->pos == pos) { 
     151                                os << "><"; 
     152                                pos += 2; 
     153                                ++iter; 
     154                        } else { 
     155                                os << "|"; 
     156                                ++pos; 
     157                        } 
     158                } 
     159                os << "\n"; 
     160                ++line; 
     161        } 
     162} 
     163 
     164ostream& operator<<(ostream& os, const BlackKnot& black) { 
     165        for (unsigned i = 0; i < black.size(); ++i) { 
     166                const MarbleResult& r = black.results[i]; 
     167                os << i << " -> (" << r.dest << "," << r.plinks << ")\n"; 
     168        } 
     169        return os; 
     170} 
     171 
     172BlackKnot::Solution BlackKnot::solve() const { 
     173        return Solver(*this).solve(); 
     174} 
     175 
     176Solver::Solver(const BlackKnot& p_black) 
     177                : black(p_black), marbles(p_black.size()), line(0), pos(0) 
     178{ 
     179        iota(marbles.begin(), marbles.end(), 0); 
     180         
     181        plinks_left.reserve(black.size()); 
     182        vector<MarbleResult>::const_iterator iter; 
     183        for (iter = black.results.begin(); iter != black.results.end(); ++iter) { 
     184                plinks_left.push_back(iter->plinks); 
     185        } 
     186} 
     187 
     188BlackKnot::Solution Solver::solve() { 
     189        findSwitcher(); 
     190        return switchers; 
     191} 
     192 
     193 
     194bool Solver::findSwitcher() { 
     195        // Don't allow a completely empty line 
     196        unsigned last_line = line + 1; 
     197         
     198        while (line <= last_line) { 
     199                if (pos < black.size() - 1) { 
     200                        if (addSwitcher()) { 
     201                                if (findSwitcher()) { 
     202                                        return true; 
     203                                } else { 
     204                                        removeSwitcher(); 
     205                                } 
     206                        } 
     207                        ++pos; 
     208                } else { 
     209                        pos = 0; 
     210                        ++line; 
     211                        if (checkDone()) { 
     212                                return true; 
     213                        } 
     214                } 
     215        } 
     216        return false; 
     217} 
     218 
     219void Solver::doSwitch(const Switcher& sw, bool forward) { 
     220        unsigned orig_right = marbles[forward ? pos + 1 : pos]; 
     221        int plink_delta = forward ? -1 : +1; 
     222        plinks_left[orig_right] += plink_delta; 
     223         
     224        swap(marbles[pos], marbles[pos+1]); 
     225} 
     226 
     227 
     228bool Solver::addSwitcher() { 
     229        Switcher sw(line, pos); 
     230         
     231        unsigned right = marbles[pos + 1]; 
     232        if (plinks_left[right] == 0) { 
     233                return false; 
     234        } 
     235        doSwitch(sw, true); 
     236         
     237        switchers.push_back(sw); 
     238        pos += 2; // Line gets fixed in findSwitcher 
     239        return true; 
     240} 
     241 
     242void Solver::removeSwitcher() { 
     243        Switcher sw(switchers.back()); 
     244        switchers.pop_back(); 
     245         
     246        doSwitch(sw, false); 
     247         
     248        line = sw.line; 
     249        pos = sw.pos; 
     250} 
     251 
     252bool Solver::checkDone() const { 
     253        for (unsigned i = 0; i < black.size(); ++i) { 
     254                const MarbleResult& result = black.results[i]; 
     255                if (plinks_left[i] != 0 || marbles[result.dest] != i) { 
     256                        return false; 
     257                } 
     258        } 
     259        return true; 
     260} 
     261 
     262ostream& operator<<(ostream& os, const Solver& s) { 
     263        // TODO 
     264        return os; 
     265} 
     266 
     267 
     268// Normal types 
     269template <typename T, bool U> struct Dumper { 
     270        static void dump(const T& n, ostream& os, unsigned) { os << n; } 
     271        static void dump_short(const T& n, ostream& os) { os << n; } 
     272}; 
     273 
     274// Containers 
     275template <typename T> struct Dumper<T, true> { 
     276        typedef typename T::value_type U; 
     277         
     278        static void dump(const T& n, ostream& os, unsigned indent) { 
     279                string s1(indent, ' '), s2(indent + 1, ' '); 
     280                os << "{\n"; 
     281                 
     282                typename T::const_iterator iter = n.begin(); 
     283                unsigned idx = 0; 
     284                for ( ; iter != n.end(); ++idx, ++iter) { 
     285                        os << s2 << setw(3) << idx << ". "; 
     286                        Dumper<U, has_const_iterator<U>::value>::dump(*iter, os, 
     287                                indent + 2); 
     288                        os << ",\n"; 
     289                } 
     290                os << s1 << "}"; 
     291        } 
     292         
     293        static void dump_short(const T& n, ostream& os) { 
     294                os << "{ "; 
     295                typename T::const_iterator iter = n.begin(); 
     296                if (iter != n.end()) 
     297                        os << *iter++; 
     298                while (iter != n.end()) 
     299                        os << ", " << *iter++; 
     300                os << " }" << endl; 
     301        } 
     302}; 
     303 
     304 
     305template <typename T> void dump(const T& n, ostream &os) { 
     306        Dumper<T, has_const_iterator<T>::value>::dump(n, os, 0); 
     307        os << endl; 
     308} 
     309 
     310template <typename T> void dump_short(const T& n, ostream& os) { 
     311        Dumper<T, has_const_iterator<T>::value>::dump_short(n, os); 
     312        os << endl; 
     313}