Си диез / Говнокод #9995 Ссылка на оригинал

0

  1. 1
  2. 2
  3. 3
  4. 4
  5. 5
  6. 6
  7. 7
  8. 8
  9. 9
  10. 10
  11. 11
  12. 12
  13. 13
  14. 14
  15. 15
  16. 16
  17. 17
  18. 18
  19. 19
public int RomeToArab (string str)
{
	int[] arabian = new int[13] { 1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1 };
	strint[] rome = new string[13] { "M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I" };
	int n = 0;
	int i = 0;
	do
	{
		if (str.StartsWith(rome[i]))
		{
			n = n + arabian[i];
			str = str.Substring(rome[i].Length, str.Length - rome[i].Length);
		}
		if (!str.StartsWith(rome[i])
			i++;
	}
	while (i < 13);
	return n;
}

Запостил: aleksi aleksi, (Updated )

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

  • (defun roman-to-arabic (numeral)
      (labels
          ((parse (i x)
    	 (if (< i 0) x
    	     (let ((y
    		    (ccase (aref numeral i)
    		      ((#\i) 1)
    		      ((#\v) 5)
    		      ((#\x) 10)
    		      ((#\l) 50)
    		      ((#\c) 100)
    		      ((#\d) 500)
    		      ((#\m) 1000))))
    	       (parse
    		(decf i)
    		(funcall 
    		(if (< y x) '- '+) x y))))))
        (parse (1- (length numeral)) 0)))

    Вполне в духе времени (почти как Linq)? если синтаксических ошибок нет, то будет работать 🙂
    Ответить
    • ЗЫ. Это я к тому, что в коде оригинала скобочек не хватает немного.

      (defun roman-to-arabic (numeral)
        (labels
            ((parse (i x)
      	 (if (< i 0) x
      	     (let ((y
      		    (ccase (aref numeral i)
      		      ((#\i) 1)
      		      ((#\v) 5)
      		      ((#\x) 10)
      		      ((#\l) 50)
      		      ((#\c) 100)
      		      ((#\d) 500)
      		      ((#\m) 1000))))
      	       (parse
      		(decf i)
      		(funcall 
      		(if (< (* y 4) x) '- '+) x y))))))
          (parse (1- (length numeral)) 0)))

      Упс, факир был пьян, вот теперь нормально.
      Ответить
      • Немножко гк:

        (defun arabic (roman)
          (dotimes (num 4000)
            (when (and (not (zerop num))
        	       (string= (format nil "~@R" num) roman))
              (return num))))
        Ответить
        • А почему только до 4 тысяч? Из длины строки вполне можно расчитать максимальное число, которое можно из нее получить.
          Ответить
          • "При этом некоторые из цифр могут повторяться, но не желательно более трех раз, таким образом с их помощью можно записать любое целое число не более 3999 (MMMCMXCIX)" (wiki)
            об этом ещё упоминается в Dive Into Python

            Самый простой способ, на мой взгляд - воспользоваться format для составления таблицы соответствий и потом просто делать gethash
            Ответить
            • А, я не знал, что MMMM уже не катит. Ну тогда окей 🙂

              Тут фишка же в чем: интуитивно хочется составить LR(k) (в лучшем случае LR(1)) парсер. Но задача лучше решается через RL(k), особенно потому, что легко строится RL(1) парсер и с минимальными накладными расходами. Т.е. перефразируя, для того, чтобы работал LR парсер в lookahead нужно чтобы было 2 символа, а для RL достаточно одного.

              EDIT: А, хотя, мой вариант тоже бы не работал для MMMM, так что да.
              Ответить
              • Именно поэтому Мавроди ограничился только тремя М
                Ответить
        • function arabicToRoman(input){
              var result;
              input = input.toLowerCase();
              function zero() { return 0; }
              function makeOrder(high, value){
          	return function(a){
          	    var r = value, p = zero, q = [];
          	    if (a){
          		p = a[0];
          		if (high.indexOf(p) > -1) r = -value;
          		q = [a.substr(1)];
          		if (p) p = this[p];
          	    }
          	    return value + p.apply(this, q);
          	}
              };
              var scope = {
          	i : makeOrder("vx", 1),
          	v : makeOrder("", 5),
          	x : makeOrder("cl", 10),
          	l : makeOrder("", 50),
          	c : makeOrder("md", 100),
          	d : makeOrder("", 500),
          	m : makeOrder("", 1000)
              };
              if (input)
          	result = scope[input[0]].apply(scope, [input.substr(1)]);
              return result;
          }


          Ну раз уж такое дело... можно сделать немного более функционально.
          Ответить
          • Или еще более функционально:
            arabicToRoman s = fst $ foldr step (0, 0) $ map roman s
                where
                    roman 'M' = 1000
                    roman 'D' = 500
                    roman 'C' = 100
                    roman 'L' = 50
                    roman 'X' = 10
                    roman 'V' = 5
                    roman 'I' = 1
                    step x (sum, prev) | x >= prev = (sum+x, x)
                                       | otherwise = (sum-x, x)
            Ответить
            • Да не функциональней, чем sed, с другой стороны раз хаскель, то хотелось бы, например:

              *Main> romanToArabic "LC"
              Left (line 1, column 2):
              unexpected 'C'
              expecting "X", "IX", "IV", "V", "I" or end of input
              Ответить
  • echo "DCCCLXXXVIII" | sed 's/cm/900+/gi; s/m/1000+/gi;
    s/cd/400+/gi; s/d/500+/gi; s/xc/90+/gi; s/c/100+/gi;
    s/xl/40+/gi; s/l/50+/gi; s/ix/9+/gi; s/x/10+/gi;
    s/iv/4+/gi; s/v/5+/gi; s/i/1+/gi; s/$/0/;' | bc
    Ответить
    • Хотя, наверное, лучше так:

      echo "DCCCLXXXVIII" | sed `echo "cm900m1000cd400d500xc90c100xl40l50ix9x10iv4v5i1s/$/0/;" | sed -r 's/([a-z]+)([0-9]+)/s\/\1\/\2+\/gi;/g;'` | bc
      Ответить

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

Где здесь C++, guest?!

    А не использовать ли нам bbcode?


    8