1. C++ / Говнокод #15363

    +32

    1. 01
    2. 02
    3. 03
    4. 04
    5. 05
    6. 06
    7. 07
    8. 08
    9. 09
    10. 10
    11. 11
    12. 12
    13. 13
    14. 14
    15. 15
    16. 16
    17. 17
    18. 18
    19. 19
    20. 20
    21. 21
    22. 22
    23. 23
    24. 24
    25. 25
    26. 26
    27. 27
    28. 28
    29. 29
    30. 30
    31. 31
    32. 32
    33. 33
    34. 34
    35. 35
    36. 36
    37. 37
    38. 38
    39. 39
    40. 40
    41. 41
    42. 42
    43. 43
    44. 44
    45. 45
    46. 46
    47. 47
    48. 48
    49. 49
    50. 50
    51. 51
    52. 52
    53. 53
    54. 54
    55. 55
    56. 56
    #include <iostream>
    #include <vector>
    #include <map>
    #include <algorithm>
    #include <iterator>
    #include <iomanip>
    using namespace std;
    
    vector<string> bracesExpressionExamples = {
    	"({[{}]{}[]})",
    	"({}}{[{}]{}[]})",
    	"({[{}]{}[]}",
    	"({[{}]{}]})",
    	"({[{}{}[]})",
    	"",
    	"{}"
    };
    
    string openBrace = "({[";
    string closeBrace = ")}]";
    
    typedef map<char, char> otc;
    const otc& openToCloseBrace(){
    	static const otc o2c([](){
    		otc o2c;
    		transform(
    			openBrace.begin(), openBrace.end(),
    			closeBrace.begin(),
    			inserter(o2c, o2c.begin()),
    			[](const char open, const char close){return make_pair(open, close);}
    		);
    		return o2c;
    	}());
    	return o2c; 
    }
    
    bool checkBraces (const string& e){
    	vector<char> s;
    	for(const char b: e)
    		if(string::npos!=openBrace.find(b))
    			s.push_back(openToCloseBrace().at(b));
    		else if(string::npos!=closeBrace.find(b) && (!s.empty()) && b==s.back())
    			s.pop_back();
    		else return false;
    	return s.empty();
    }
    
    int main() {
    	cout<<boolalpha;
    	transform(
    		bracesExpressionExamples.begin(),
    		bracesExpressionExamples.end(),
    		ostream_iterator<bool>(cout, "\n"),
    		checkBraces);
    	return 0;
    }

    http://ideone.com/AbO4tw
    Кот с собеседований.
    Проверка правильности расстановки скобок для каждого выражения из bracesExpressionExamples.

    Запостил: USB, 05 Марта 2014

    Комментарии (63) RSS

    • От претендента требуется знание крестов и хаскеля.

      Мне не нравится, что он намутил в
      otec& openToCloseBrace

      Красиво, но на читабильность наплювал. За это я думаю его не брать. В ответ он спросил а как бы ты это сделал? Я помялся. Так что стоило ему ответить?
      Ответить
      • > крестов и хаскеля
        > хаскеля
        О_о
        Ответить
      • > на читабильность наплювал
        Ну разве что в генерации мапа муть какая-то, и называть тип otc совсем не айс. Вектор вместо стека еще смущает. Остальное вполне читаемо.

        P.S. Что прога на хаскеле, что прога на крестах не обрабатывают другие символы, помимо скобок. Это нормально?
        Ответить
        • Написать функцию, фильтрующую только нужные символы, и задача сводится к общему случаю.
          Ответить
      • > как бы ты это сделал?
        Может, так:
        static const std::map<char, char> otc {
          {'(', ')'}, {'[', ']'}, {'{', '}'},
        };

        ?
        Ответить
      • char getPair (char c)
        {
          switch(c)
          {
            case '(' : return ')';
            case '[' : return ']';
            case '{' : return '}';
            defailt : return \0;
          };
        }
        Ответить
    • наворочено пипец

      Дожили: люди знаю хачкель, но не знают, что проверять сбалансированность скобок надо с помощью стека.
      Ответить
      • > но не знают, что проверять сбалансированность скобок надо с помощью стека
        Знают:
        s.push_back(openToCloseBrace().at(b))
        (!s.empty()) && b==s.back()
        s.pop_back();
        Просто не тот контейнер юзают.
        Ответить
        • А, да, с утра не разглядел, позор мне. В принципе, стэк - лишь адаптер для вектора. Но написано всё равно слишком мудрёно.
          Ответить
          • А что мудрено кроме openToCloseBrace? Как бы это написал нормальный человек? stack можно использовать. Это тоже минус кандидату.
            Ответить
            • Тупо и не меньше по размеру, зато, будучи написано в простом текстовом редакторе, скомпилировалось и заработало с первого раза:
              http://ideone.com/wZv8AD
              Также исправлен недостаток (?), упомянутый бормандом.
              Ответить
              • В checkBraces ~ is_balanced ты почти также все написал:
                #include <vector>
                #include <string>
                #include <iostream>
                
                static const std::vector<std::string> EXAMPLES = {
                    	"({[{}]{}[]})",
                        "({}}{[{}]{}[]})",
                        "({[{}]{}[]}",
                        "({[{}]{}]})",
                        "({[{}{}[]})",
                        "",
                        "{}",
                        "(i (am so [lispish]))",
                };
                
                static const char eof = char(-1);
                static const std::string open_braces  = "({[";
                static const std::string close_braces = ")}]";
                
                inline char matching_brace(char c)
                {
                    const std::size_t i = close_braces.find(c);
                    return i != std::string::npos ? open_braces[i] : eof;
                }
                
                static bool is_balanced(const std::string &s)
                {
                    std::string brace_stack;
                
                    for (auto c : s) {
                        if (open_braces.find(c) != std::string::npos) {
                            brace_stack.push_back(c);
                            continue;
                        }
                
                        const char pair = matching_brace(c);
                        if (pair != eof) {
                            if (!brace_stack.empty() && brace_stack.back() == pair) {
                                brace_stack.pop_back();
                            } else {
                                return false;
                            }
                        }
                    }
                
                    return brace_stack.empty();
                }
                
                int main()
                {
                    std::cout << std::boolalpha;
                    for (const auto & e : EXAMPLES) {
                        std::cout << is_balanced(e) << "\n";
                    }
                    return 0;
                }
                Ответить
                • > В checkBraces ... ты почти также все написал
                  да, там автор кода в топике всё правильно сделал, это я затупил.

                  В общем, в действительности из претензий только неуместный тяжеловесный map и чрезмерное умничанье с transform.
                  Ответить
                • Тонко
                  Ответить
            • даже лучше без лишних функций:
              #include <vector>
              #include <string>
              #include <iostream>
              
              static std::vector<std::string> EXAMPLES = {
                  	"({[{}]{}[]})",
                      "({}}{[{}]{}[]})",
                      "({[{}]{}[]}",
                      "({[{}]{}]})",
                      "({[{}{}[]})",
                      "",
                      "{}",
                      "(i (am so [lispish]))",
              };
              
              static std::string open_braces  = "({[";
              static std::string close_braces = ")}]";
              
              static bool is_balanced(const std::string &s)
              {
                  std::string brace_stack;
              
                  for (auto c : s) {
                      if (open_braces.find(c) != std::string::npos) {
                          brace_stack.push_back(c);
                          continue;
                      }
              
                      const std::size_t pair_at = close_braces.find(c);
                      if (pair_at != std::string::npos) {
                          if (!brace_stack.empty() &&
                               brace_stack.back() == open_braces[pair_at]) {
                              brace_stack.pop_back();
                          } else {
                              return false;
                          }
                      }
                  }
              
                  return brace_stack.empty();
              }
              
              int main()
              {
                  std::cout << std::boolalpha;
                  for (const auto & e : EXAMPLES) {
                      std::cout << is_balanced(e) << "\n";
                  }
                  return 0;
              }
              Ответить
              • Вообще в треде не хватает годного перловца, питониста или сишника, который написал бы это невероятно коротко.
                Ответить
                • > сишника
                  В сишечке нет нормального стека из коробки, кратко врядли получится. Разве что ради ржаки держать стейт в сегменте стека, надеясь, что глубина вложенности скобок не будет слишком большой.
                  Ответить
                • В тред призываются безумные сишники, способные сократить этот код (или найти в нём ошибку):
                  #include <stdio.h>
                  #include <string.h>
                  
                  const char * is_balanced(const char * s, int b) {
                      char c;
                      while ((c = *s++)) switch (c) {
                      case '(': case '[': case '{':
                          if (!(s = is_balanced(s, c))) return NULL;
                          continue;
                      case ']': case '}': --c;
                      case ')':
                          return --c == b ? s : NULL;
                      }
                      return s;
                  }
                  
                  int main()
                  {
                      static char *examples[] = {
                          "({[{}]{}[]})", "({}}{[{}]{}[]})", "({[{}]{}[]}",
                          "({[{}]{}]})",  "({[{}{}[]})",     "",  "{}",
                          "(i (am so [lispish]))",
                      };
                      int i = 0, n = sizeof examples / sizeof examples[0];
                      while (i < n)
                          printf("%s\n", is_balanced(examples[i++], -1) ? "true": "false");
                      return 0;
                  }
                  Ответить
                • Python:

                  def brackets_match(string):
                      string = re.sub(r'[^{}[\]()]', '', string)
                      next = ''
                      while string != next:
                          next = string
                          string = re.sub(r'\[\]|\{\}|\(\)', '', string)
                      return not string
                  
                  test_set = ["({[{}]{}[]})", "({}}{[{}]{}[]})", "({[{}]{}[]}", "({[{}]{}]})",
                              "({[{}{}[]})", "", "{}"]
                  for t in test_set:
                      print brackets_match(t)
                  Ответить
                  • def brackets_match(string):
                        string, next = re.sub(r'[^{}[\]()]', '', string), ''
                        while string != next:
                            next, string = string, re.sub(r'\[\]|\{\}|\(\)', '', string)
                        return not string

                    Даже так, если хочется удавиться за каждую строчку.
                    Ответить
        • > Просто не тот контейнер юзают.

          использование вектора вместо стека как по мне это признак того что у чудака уже есть практический опыт работы.
          Ответить
    • (defparameter *test-brackets*
        '("({[{}]{}[]})" "({}}{[{}]{}[]})" "({[{}]{}[]}" "({[{}]{}]})"
          "({[{}{}[]})" "" "{}"))
      
      (defun brackets-match-p (string)
        (iter
          (with last-open := nil)
          (with pairs := '((#\( . #\)) (#\[ . #\]) (#\{ . #\})))
          (for char :in-string string)
          (case char
            ((#\( #\[ #\{) (push char last-open))
            ((#\) #\] #\})
             (if (char= (car (rassoc char pairs)) (car last-open))
                 (pop last-open)
                 (return))))
          (finally (return (null last-open)))))
      
      (mapcar #'brackets-match-p *test-brackets*)
      ;; (T NIL NIL NIL NIL T T)


      О, давно не было специальных олимпиад!
      Ответить
    • показать все, что скрытоГоспода, а зачем мутить стек если все и так просто:

      #include <iostream>
      #include <string>
      #include <list>
      #include <algorithm>
      #include <iterator>
      
      using namespace std;
      
      list<string> bracesExpressionExamples = {
      	"({[{}]{}[]})",
      	"({}}{[{}]{}[]})",
      	"({[{}]{}[]}",
      	"({[{}]{}]})",
      	"({[{}{}[]})",
      	"",
      	"{}"
      };
      
      bool is_balanced(std::string s) {
      	int counts[3] = {0};
      	for (char ch : s) {
      		switch (ch) {
      			case '(': counts[0]++; break;
      			case ')': counts[0]--; break;
      			case '[': counts[1]++; break;
      			case ']': counts[1]--; break;
      			case '{': counts[2]++; break;
      			case '}': counts[2]--; break;
      			default: break;
      		}
      	}
      	return counts[0] + counts[1] + counts[2] == 0;
      }
      
      int main(int, char**) {
      	cout << boolalpha;
      	transform(bracesExpressionExamples.begin(),
      		bracesExpressionExamples.end(),
      		ostream_iterator<bool>(cout, "\n"),
      		is_balanced);
      	return 0;
      }


      http://ideone.com/bYmhC8
      Ответить
      • ({)}
        Ответить
      • Со стеком получилось даже короче на одну строку (если не учитывать инклуды):

        #include <iostream>
        #include <string>
        #include <list>
        #include <stack>
        #include <map>
        #include <algorithm>
        #include <iterator>
        
        using namespace std;
        
        list<string> bracesExpressionExamples = {
        	"({[{}]{}[]})",
        	"({}}{[{}]{}[]})",
        	"({[{}]{}[]}",
        	"({[{}]{}]})",
        	"({[{}{}[]})",
        	"",
        	"{}"
        };
        
        bool is_balanced(std::string s) {
        	static map<char, char> opposite_braces = { {']', '['}, {'}', '{'}, {')', '('} };
        	stack<char> braces;
        	for (char ch : s) {
        		if (string("(){}[]").find(ch) != string::npos) {
        			if (!braces.empty() && braces.top() == opposite_braces[ch]) {
        				braces.pop();
        				continue;
        			}
        			braces.push(ch);
        		}
        	}
        	return braces.empty();
        }
        
        int main(int, char**) {
        	cout << boolalpha;
        	transform(bracesExpressionExamples.begin(),
        		bracesExpressionExamples.end(),
        		ostream_iterator<bool>(cout, "\n"),
        		is_balanced);
        	return 0;
        }
        Ответить
        • > list<string>
          > is_balanced(std::string s)
          > string("(){}[]").find(ch)

          с++ ведь не ваш основной язык программирования?
          Ответить
          • Каюсь, есть такое дело. Просто иногда проскакивает ностальгия по первому языку программирования)
            А как было бы правильно, и в чем косяки? если вас не затруднит ответить, конечно же)
            Ответить
            • 1. list нужен очень редко, в основном ради неинвалидируемых итераторов. vector практически всегда предпочтительней.
              2. Передача строки по значению сомнительна, копия тут ни к чему. Тут лучше передавать константную ссылку.
              3. string("(){}[]") в теории может приводить к аллокации новой временной строки на каждой итерации цикла.

              Мне ещё непонятно, зачем мы пихаем в стек закрывающие скобки, встретившиеся перед открывающими. Поскольку operator[] создаёт запись в таблице при передаче отсутствующего ключа, подозреваю, что у меня получится подобрать к коду контрпример.
              Ответить
            • Контпример не подберётся, т.к. в стеке могут быть лишь скобки. Но размер статической карты можно запросто нарастить до 6 :) Уже после первого примера он становится равным 5, скобкам } и ] в качестве пары выставляется нулевой символ.
              Ответить
    • Согласно последнего социального опроса за 2013ый год вбросы на С++ в 8 раз популярнее вбросов на Хаскеле.
      Ответить
      • Согласно осмотру рекрутинговых сайтов специалисты по С++ 100500 раз востребование чем специалисты по хаскелю.
        Ответить
    • shit =: 3 : 0
      a=:>;:y NB.'(([{}{}[]]))'
      b=:|:(6 12) $,'(){}[]'=/a
      b=:(-1 3 5{"(1)b) (1 3 5)}"(1)b
      c1=:+/1 0{|:b
      c2=:+/3 2{|:b
      c3=:+/5 4{|:b
      c=:c1,.c2,.c3
      no =:_1
      n =:#c
      while. n~:no do.
      no=:n
      d=:~.(I.*./"(1)(1 _1)="(1)(2+\(0{|:c))),(I.*./"(1)(1 _1)="(1)(2+\(1{|:c))),(I.*./"(1)(1 _1)="(1)(2+\(2{|:c)))
      c=:((i.#c)-.(d,>:d)){c
      n=:#c
      end.
      n=0
      )
      Ответить
      • Улучшил
        shit =: 3 : 0
        a=:>;:y
        b=:|:(6,#y) $,'(){}[]'=/a
        b=:(-1 3 5{"(1)b) (1 3 5)}"(1) b
        c=:|:(3 2$i.6)([:+/[{[:|:])"(1 _) b
        no =:_1
        n =:#c
        p =: 13 : 'I.*./"(1)(1 _1)="(1)(2+\(x{y))'
        while. n~:no do.
        no=:n
        cc =: |:c
        d=:~.(0 p cc),(1 p cc),(2 p cc)
        c=:((i.#c)-.(d,>:d)){c
        n=:#c
        end.
        n=0
        )
        Ответить
        • Та ну, не может быть, чтоб так много писанины. Надо еще искать.
          Ответить
        • fbrackets =: monad : 'y -. (y -. ''{[()]}'')'
          fpairs =: monad : '=/"_1 (_1 }. y) ,"_1 (1 }. y)'

          Но дальше чет не придумывается. :)
          Ответить
        • fbrackets =: monad : '+/ y ="(1 _1) ''{[()]}'''
          fpairs =: monad : '=/"_1 (_1 }. y) ,"_1 (1 }. y)'

          Вернее, так.

          Теперь нужна только функция выбирающая из списка Х элементы там, где в списке У единицы, и задача решена.
          Ответить
          • proc =: 3 : 0
            d1 =: I. '()' E. y
            d2 =: I. '[]' E. y
            d3 =: I. '{}' E. y
            d =: ~.d1,d2,d3
            a =: (((d,>:d)-.~i.#y){y)
            )
            
            check_b =: 3 : 0
            0=#proc^:_ y
            )
            Ответить
          • $ jconsole
               1 2 3 4 #~ 0 1 0 1
            2 4


            Пилите, интересно увидеть
            Ответить
            • Про # я знаю, но я думал как-то через replace_step ` finish @. need_more_replacement сделать. Но это сверх моих познаний :)
              Ответить
          • Можно просто }. вместо 1 }. и }: вместо _1 }.
            Ответить
        • Шо то хуйня, шо это хуйня. Отэто обе хуйни такие, шо я бля ебал ее маму рот.
          Ответить
    • На БУУСТ.Спирт кратко бы получилось.
      Ответить

    Добавить комментарий