LINUX.ORG.RU

Выход mocl

 , ,


7

8

mocl — набор инструментов для разработки на Common Lisp под мобильные платформы iOS и Android. По заверениям разработчиков получаемый код (используется LLVM) по производительности значительно превосходит аналогичный на Java/Dalvik.

В основе mocl лежит идея, заключающаяся в том, что логика приложения должна быть полностью описана на Лиспе, а пользовательский интерфейс — быть «родным» для платформы. Авторы проводят аналогию с Вэбом, когда логика серверного приложения описана на одном языке (например, на Лиспе), а представление — на другом (HTML + JavaScript).

Цена лицензии варьируется от $1299 для серьёзных компаний до $199 для индивидуальных разработчиков. Также предусмотрена «Source code license» для особых энтузиастов, доступ к которой, по-видимому, дают после обращения в службу поддержки.

Пример приложения на Github.

>>> Подробности

★★★★★

Проверено: mono ()
Последнее исправление: Dendy (всего исправлений: 4)

Ответ на: комментарий от BooBoo

Тебе выше напоминали что Clojure и Scala используют _готовую_ вылизанную до блеска и полностью документированную низшими морлоками инфраструктуру JVM/Java. Упоминать достижения Clojure не упоминая Java даже как-то неловко - это как креативная личность въезжает в готовый удобный дом со всеми коммуникациями, красит стены в кислотный цвет и после этого приписывает все достоинства дома себе а недостатки вешает на строителей (чо с них взять то с макак примитивных, торопились заработать).

Как бы не привлекательна была выразительность Scala по сравнению с Java (также страдает от lisp-like аргументов - пишем в 5 раз быстрее и короче с меньшим кол-вом ошибок), ее создатели (вроде как элита от программирования) который год ну никак не могут выдать стабильно работающей плагин для эклипса, зато баги языка кочуют из версии в версию, API постоянно деприкейтится, фичи множатся, совместимость ломается.

Как после таких real-worl демонстраций можно серьезно относится к разговорам о невероятной производительности (по сравнений с Java) в умелых руках?

А тем временем Мартин решил в следующей версии поменять (местами)... синтаксис :о. Как после такого можно серьезно говорить о том что манагеры не должны ограничивать полет фантазии и желаний разработчиков?

anonymous
()
Ответ на: комментарий от wota
#include <cstdio>
#include <map>

int main() {
    std::map<int,int> stack;
    int homos=0, n, i;
    char buf[20];
    
    scanf("%d",&n);
    while(n--) {
        scanf("%s %d", &buf, &i);
        if(*buf == 'i')
            if(stack[i]++) ++homos;
        else if(stack.count(i))
            --stack[i] ? --homos : stack.erase(i);

        puts(stack.size() > 1 ? homos ? "both" : "hetero" : homos ? "homo" : "neither");
    }
}

не до конца прилизал код quasimoto, вот более простая версия

wota ★★
()
Последнее исправление: wota (всего исправлений: 2)
Ответ на: комментарий от wota

У тебя там скобочки после первого if потерялись.

Вот реализация на лиспе один в один, мне было лениво придумывать свой алгоритм, к тому же этот уже вылизан под задачу.

(defun homo ()
  (let ((stack (make-hash-table))
        (homos 0))
    (dotimes (j (read))
      (let* ((op (read)) (i (read)))
        (symbol-macrolet ((s (gethash i stack 0)))
          (cond
            ((eq op 'insert)
             (when (> (incf s) 1) (incf homos)))
            (s
             (if (plusp (decf s))
               (decf homos)
               (remhash i stack))))))
      (format t "~:[~:[both~;hetero~]~;~:[homo~;neither~]~]~%"
              (<= (hash-table-count stack) 1)
              (zerop homos)))))

Задача слишком мелкая чтобы тут было что улучшать. Ну вон я воткнул symbol-macrolet, но C++ всё равно выигрывает за счёт неявных приведений типов int -> bool и синтаксического сахара. Я тоже мог понадобавлять сахара, но это, во-первых, по-настоящему никому не надо, во-вторых, описание сахара будет занимать много больше, чем уже приведённое решение задачи --- народ тут же развопится про многословность, --- и, в-третьих, задача слишком маленькая, чтобы это дало какой-то профит. И вообще, это нечестно --- рассуждать про удобство работы со списками не работая с этими самыми списками. Конечно, это баг в бенчмарке, что получить требуемый вывод можно таким образом, ну так и не надо было его вообще приводить...

anonymous
()
Ответ на: комментарий от BooBoo

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

Можем локально проверить в относительном эквиваленте. У меня с твоей версией, с моей на C++ и на Scala, с которой я мало дружу, получается так:

running C++ tests...

0:02.81 4240
0:03.10 4448
0:04.45 136960
0:06.00 784608

running SBCL tests...

0:11.02 346928
0:12.39 346816
0:17.05 583712
0:21.11 2472608

running Scala tests...

0:18.53 455888
0:19.57 518976
0:28.78 1117840

checking diffs...

Ok
Ok
Ok
# Makefile

CXX=g++
CXXFLAGS=-std=c++11 -O3 -Wall
LDFLAGS=-lstdc++

homo-tests: homo-cpp-tests homo-sbcl-tests homo-scala-tests
	@echo
	@echo checking diffs...
	@echo
	@./homo-gen-in 1000 10 > /tmp/test
	@cat /tmp/test | ./homo > /tmp/c++.result
	@cat /tmp/test | sbcl --noinform --noprint --disable-debugger --load homo.lisp > /tmp/sbcl.result
	@cat /tmp/test | scala -classpath . Main > /tmp/scala.result
	@diff /tmp/sbcl.result /tmp/c++.result > /dev/null && echo Ok || echo C++ result != SBCL result
	@diff /tmp/scala.result /tmp/c++.result > /dev/null && echo Ok || echo C++ result != Scala result
	@diff /tmp/scala.result /tmp/sbcl.result > /dev/null && echo Ok || echo SBCL result != Scala result

homo-cpp-tests: homo-gen-in homo
	@echo
	@echo running C++ tests...
	@echo
	@./homo-gen-in 10000000 10 | \time -f "%E %M" ./homo > /dev/null
	@./homo-gen-in 10000000 1000 | \time -f "%E %M" ./homo > /dev/null
	@./homo-gen-in 10000000 1000000 | \time -f "%E %M" ./homo > /dev/null
	@./homo-gen-in 10000000 1000000000 | \time -f "%E %M" ./homo > /dev/null

homo-sbcl-tests: homo-gen-in homo.lisp
	@echo
	@echo running SBCL tests...
	@echo
	@./homo-gen-in 10000000 10 | \time -f "%E %M" sbcl --noinform --noprint --disable-debugger --load homo.lisp > /dev/null
	@./homo-gen-in 10000000 1000 | \time -f "%E %M" sbcl --noinform --noprint --disable-debugger --load homo.lisp > /dev/null
	@./homo-gen-in 10000000 1000000 | \time -f "%E %M" sbcl --noinform --noprint --disable-debugger --load homo.lisp > /dev/null
	@./homo-gen-in 10000000 1000000000 | \time -f "%E %M" sbcl --noinform --noprint --disable-debugger --load homo.lisp > /dev/null

homo-scala-tests: homo-gen-in Homo.scala
	@echo
	@echo running Scala tests...
	@echo
	@scalac -optimize Homo.scala
	@./homo-gen-in 10000000 10 | \time -f "%E %M" scala -classpath . Main > /dev/null
	@./homo-gen-in 10000000 1000 | \time -f "%E %M" scala -classpath . Main > /dev/null
	@./homo-gen-in 10000000 1000000 | \time -f "%E %M" scala -classpath . Main > /dev/null

homo-gen-in: homo-gen-in.o

homo: homo.o

clean:
	rm -f homo-gen-in homo *.o *.class
// homo-gen-in.cc

#include <cstdio>
#include <cstdlib>
#include <ctime>

int main(int argc, char **argv)
{
    srand(time(0));
    char* ops[] = { "insert", "delete" };
    int n = atoi(argv[1]), m = atoi(argv[2]);
    printf("%d\n", n);
    do printf("%s %d\n", ops[rand() % 2], rand() % m);
    while (--n);
}
quasimoto ★★★★
()
Ответ на: комментарий от anonymous
running SBCL tests...

0:27.93 361344
0:31.21 361232
0:42.31 616544
0:55.06 2757072

Даже хуже чем скала!11 :)

quasimoto ★★★★
()
Ответ на: комментарий от anonymous

Спасибо за пример, symbol-macrolet действительно помог сделать код читабельнее, хотя конечно это уже скорее рефакторинг, чем ес-ный элемент при накидывании кода.

C++ всё равно выигрывает за счёт неявных приведений типов int -> bool и синтаксического сахара

На самом деле лисп сам по себе многословный, и в задачах вроде:

http://www.spoj.com/problems/NPRIME/

ему никогда не быть первым, даже С позволяет писать гораздо меньше кода, про ЯП вроде Ruby и говорить не надо.

Ну и если взять эту многословность, да добавить однообразный синтаксис, да динамическую типизацию, да макросы - то поддержка и развитие большого объема кода на лиспе - не самое приятное занятие. Ведь на самом деле плевать на «особой стиль накидывания кода», в больших проектах читать код приходится гораздо чаще чем писать, и там нужна прежде всего читабельность, а если код в узких местах еще и в десятки раз быстрее - то выбор просто очевиден. Как минимум против определенных ЯП, у которых таки есть своя ниша, но весьма узкая.

wota ★★
()
Последнее исправление: wota (всего исправлений: 1)
Ответ на: комментарий от wota

На самом деле лисп сам по себе многословный, и в задачах вроде: http://www.spoj.com/problems/NPRIME/

С чего бы это? :)

ему никогда не быть первым

Lisp всегда был первым по МП и, соответственно, по борьбе с boilerplate'ом. Не вводите общественность в заблуждение.

даже С позволяет писать гораздо меньше кода

Нет. Только в редких случаях, когда нужно долбить байтики, да и то не факт.

про ЯП вроде Ruby и говорить не надо.

Говорить надо, ибо Ruby никогда не мог и не может догнать Lisp относительно МП. Я знаю о чём говорю. Я знаю и Ruby и Lisp.

BooBoo
()
Ответ на: комментарий от wota
char buf[20];
...
scanf("%s %d", &buf, &i);

Потенциальный buffer overflow.

--stack[i] ? --homos : stack.erase(i);

Тернарное выражение в качестве if — bad practice.

stack.size() > 1 ? homos ? "both" : "hetero" : homos ? "homo" : "neither"

Вложенные тернарные выражения без скобочек не читаются — bad practice.

if(stack[i]++) ++homos;

Вам повезло, что при первом обращении значение инициализируется нулём. Кстати, всегда ли это так? Что нам говорит стандарт?

Также if/else без определения блоков {} — bad practice.

Также от C++ тут только std::map.

Резюмирую: вы сделали всё, чтобы символов в коде было как можно меньше, при этом нарушив «правила приличия» и местами сделали код не читаемым. Да и ещё потенциальный buffer overflow. Круто, чё. «Secure Robust Enterprise» решение.

BooBoo
()
Ответ на: комментарий от quasimoto

А почему у вас на каждый тест генерируется новый входной файл? Это не правильно. Нужно тестировать на одном наборе для всех языков.

BooBoo
()
Ответ на: комментарий от BooBoo

С чего бы это? :)

у тебя не выйдет обогнать даже вариант на С

Lisp всегда был первым по МП и, соответственно, по борьбе с boilerplate'ом. Не вводите общественность в заблуждение.

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

Нет. Только в редких случаях, когда нужно долбить байтики, да и то не факт.

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

Говорить надо, ибо Ruby никогда не мог и не может догнать Lisp относительно МП. Я знаю о чём говорю. Я знаю и Ruby и Lisp.

ну если ты и Ruby обгонишь - я обещаю никогда не критиковать лисп

wota ★★
()
Ответ на: комментарий от BooBoo

Потенциальный buffer overflow.

мопед не мой (с) взято с кода quasimoto

Тернарное выражение в качестве if — bad practice.

обоснуй

Вложенные тернарные выражения без скобочек не читаются — bad practice.

мопед не мой (с) взято с кода quasimoto

Вам повезло, что при первом обращении значение инициализируется нулём

мне не повезло - я знаю стандарт

Также if/else без определения блоков {} — bad practice.

полнейшая чушь

Также от C++ тут только std::map.

аналогично, ты еще джаверам расскажи, что они на урезанном С++ пишут

wota ★★
()
Ответ на: комментарий от wota

у тебя не выйдет обогнать даже вариант на С

Ещё раз. За счёт чего вариант на Си будет читабельнее и лаконичнее, чем вариант на CL?

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

Пример, пожалуйста. И что именно прикрывается макросами?

ну если ты и Ruby обгонишь

Обгоню, обгонял и буду обгонять. Код Ruby только на простейших частных вещах короче будет. Если разговор заведётся о МП и кодогенерации, конечный результат на Ruby превратится в труху и пепел.

я обещаю никогда не критиковать лисп

А ты и не критикуешь. Это просто butthurt. Ты же Lisp'а то не знаешь. Как ты можешь критиковать Lisp?

BooBoo
()
Ответ на: комментарий от BooBoo
(defun -insert (n)
  (let ((count (gethash n *ht*)))
    (if count
        (progn
          (incf (gethash n *ht*))
          (setf *is-homo* t)
          (incf *homo-counter*))
        (setf (gethash n *ht*) 1)))
  (when (> (hash-table-count *ht*) 1)
    (setf *is-hetero* t)))

кстати забавно, что человек написавший «это», придирается к строке:

if(stack[i]++) ++homos;

которая полностью заменяет его код выше, достаточно сравнить эти два куска кода и будет очевидно, что его высокопарные фразы про «boilerplate» и гроша ломаного не стоят

wota ★★
()
Ответ на: комментарий от BooBoo

Ещё раз. За счёт чего вариант на Си будет читабельнее и лаконичнее, чем вариант на CL?

а ты попробуй на лиспе - сразу увидишь

Пример, пожалуйста. И что именно прикрывается макросами?

мой предыдущий пост посмотри и свои «gethash n *ht*»

Обгоню, обгонял и буду обгонять. Код Ruby только на простейших частных вещах короче будет

а, ну ок, а свой большой проект покажешь? или он в разработке, заодно супер-секретный и все такое?

А ты и не критикуешь. Это просто butthurt. Ты же Lisp'а то не знаешь. Как ты можешь критиковать Lisp?

опять общие фразы - эффективность, butthurt, «Ты же Lisp'а то не знаешь.», а как доходит дело до конкретных примеров - шумный слив по всем фронтам

wota ★★
()
Последнее исправление: wota (всего исправлений: 1)
Ответ на: комментарий от x4DA

эти два куска кода не эквивалентны

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

wota ★★
()
Ответ на: комментарий от wota

Тернарное выражение в качестве if — bad practice.

обоснуй

Так как «тернарное выражение» является таки _выражением_, то предполагается, что результат этого выражения будет использован. А у тебя выражение в void контексте и нужно лишь ради side-effect'ов — фактически нужен if. Это подобно тому, как неграмотные кодерки используют ФВП map в качестве for-each. Т.е. использовать то конечно можно, но запашок не очень от такого кода.

мне не повезло - я знаю стандарт

А можешь привести цитату из стандарта? Хорошо конечно. Но как быть, если за дефолтное значение нужно определить не 0?

аналогично, ты еще джаверам расскажи, что они на урезанном С++ пишут

Ты не согласен с тем, что от C++ в решении только std::map?

BooBoo
()
Ответ на: комментарий от wota

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

Да ну ладно вам. Ничего страшного я в собственном коде не вижу. Да, немного многословно написал местами. Ну так я и не задумывался надо сокращением количества символов. Код читаем и в целом понятен. К тому же ваша критика, это больше «тяв-тяв-тяв» :) Вот если бы меня господа лисперы покритиковали, тут бы я внимательно послушал и переделал. А так просто «шшшшш» — белый шум :)

BooBoo
()
Ответ на: комментарий от BooBoo

Так как «тернарное выражение» является таки _выражением_

охуеть, а ++n по-твоему что такое? тебе явно не стоит придираться к тому, что ты не знаешь

А можешь привести цитату из стандарта?

" if T is a scalar type, the object is set to the value 0 (zero)"

Но как быть, если за дефолтное значение нужно определить не 0?

сделать свой тип со своим дефолтным значением, «снаружи» будет тот же int, после компиляции 0 оверхеда

Ты не согласен с тем, что от C++ в решении только std::map?

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

wota ★★
()
Ответ на: комментарий от BooBoo

Ну так я и не задумывался надо сокращением количества символов.

а там не символы, там логика проще

Код читаем и в целом понятен

ну да, просто его в 10 раз больше, но для лиспо-фанбоев - это все-равно лучше любого примера на другом ЯП

А так просто «шшшшш» — белый шум :)

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

wota ★★
()
Ответ на: комментарий от wota

охуеть, а ++n по-твоему что такое? тебе явно не стоит придираться к тому, что ты не знаешь

И что с того что ++ выражение? Это оправдывает как-то что ты, как быдло, использовал тернарный оператор в void контексте в качестве if, дабы зачем то сэкономить пару символов?

BooBoo
()
Ответ на: комментарий от BooBoo

И что с того что ++ выражение?

у тебя амнезия - «является таки _выражением_, то предполагается, что результат этого выражения будет использован», кстати и «a=1» тоже выражение, тут тебя не смущает игнорирование результата?

Это оправдывает как-то что ты, как быдло

что вы, не надо комплиментов, я просто быдло

использовал тернарный оператор в void контексте в качестве if, дабы зачем то сэкономить пару символов?

это ты еще в код gnuplot, zlib и пр. не смотрел ;) я много проектов пересмотрел, и помогал, кстати, серьезные люди не заморачиваются такой ерундой, у них понятие быдлокода расходится с правилами для обезьянок, которых держат на привязи

wota ★★
()
Ответ на: комментарий от wota

у тебя амнезия - «является таки _выражением_, то предполагается, что результат этого выражения будет использован», кстати и «a=1» тоже выражение, тут тебя не смущает игнорирование результата?

Нет, не смущает. Потому что нет иного способа присвоить значение связанной переменной, кроме как использовать одну из операций присваивания (которые являются выражениями). Посему использование таких операций в void контексте — обычная практика и никого не смущает. Тернарный же оператор не имеет смысл использовать в void-контексте, ибо есть if/else. Это только вводит в заблуждение читателя. К таким «трюкам» прибегают только кулхацкеры для экономии пары символов, для демонстрации того на сколько они «круты» :)

Кстати говоря, в CL (и в Ruby, и практически во всех ФЯП'ях) if является выражением у которого отсутствуют недостатки операционного if'а и ограничения тернарного оператора ;)

BooBoo
()
Ответ на: комментарий от wota

это ты еще в код gnuplot, zlib и пр. не смотрел ;) я много проектов пересмотрел, и помогал,

Ну это ни разу не новость. Плохо сопровождаемый код есть всегда и везде. И это совершенно не повод фигачить код как попало.

кстати, серьезные люди не заморачиваются такой ерундой

Согласен. Гороздо хуже потенциальный buffer overflow и отмазы, уровня: «это не я, это не я, это всё он (quasimoto)» :) Очень профессионально. Это вам ни какой-то там детский сад и напоминает о «серьёзных людях» :)

BooBoo
()
Ответ на: комментарий от BooBoo

потенциальный buffer overflow

Замеряй время, на которое %s отличается от %s19.

детский сад

«Детский сад» - это когда к решению задачи на скорость начинают предъявлять претензии «а здесь у тебя тернарный оператор вместо if».

tailgunner ★★★★★
()
Ответ на: комментарий от BooBoo

Согласен. Гороздо хуже потенциальный buffer overflow и отмазы, уровня: «это не я, это не я, это всё он (quasimoto)» :)

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

wota ★★
()
Ответ на: комментарий от BooBoo

Тернарный же оператор не имеет смысл использовать в void-контексте, ибо есть if/else. Это только вводит в заблуждение читателя.

только весьма глупого читателя, надо отметить, т.к. данная строка проста и очевидна, даже тебе

wota ★★
()
Ответ на: комментарий от wota

только весьма глупого читателя, надо отметить, т.к. данная строка проста и очевидна, даже тебе

Только весьма глупый читатель скажет, что всё okay. Умный же читатель, напротив, возмутиться и воскликнет: «WTF? Нафиг тут вообще тернарный оператор?»

Для демонстрации лаконичности и чёткости C++ кода, письни-ка вот это «многословное», но простенькое преобразование на С++. Можешь использовать любые библиотеки. Как бонус, ещё и на Ruby реализуй -- http://www.linux.org.ru/news/commercial/9298028/page10#comment-9319818 (комментарий)

BooBoo
()
Ответ на: комментарий от wota

сделать свой тип со своим дефолтным значением, «снаружи» будет тот же int, после компиляции 0 оверхеда

Покажи, пожалуйста.

BooBoo
()
Ответ на: комментарий от tailgunner

«Детский сад» - это когда к решению задачи на скорость начинают предъявлять претензии «а здесь у тебя тернарный оператор вместо if».

На какую скорость? Тернарный оператор пишется быстрее чем if?

BooBoo
()
Ответ на: комментарий от BooBoo

«Детский сад» - это когда к решению задачи на скорость начинают предъявлять претензии «а здесь у тебя тернарный оператор вместо if».

На какую скорость?

На скорость работы результирующей программы.

Тернарный оператор пишется быстрее чем if?

Тернарный оператор ни на что не влияет.

tailgunner ★★★★★
()
Ответ на: комментарий от BooBoo

Только весьма глупый читатель скажет, что всё okay.

ты уж определись, что у тебя за глупый читатель и как он отреагирует

письни-ка вот это «многословное», но простенькое преобразование на С++

сформулируй точно задачу и предоставь полное решение с тестовым данными

wota ★★
()
Ответ на: комментарий от BooBoo

Покажи, пожалуйста.

~$ cat 1.cpp
#include <iostream>
#include <map>
using namespace std;

template<int def>
struct Integer {
	int v_;
	Integer() {v_ = def;}
	Integer( int v ) { v_ = b; }

	operator int() const { return v_; }
};

int main()
{
	map<int,Integer<100>> m;
	cout << m[0] << endl;
}

~$ g++ 1.cpp
~$ ./a.out 
100

на деле класс надо бы чуть расширить, но для примера опять же думаю сойдет

wota ★★
()
Ответ на: комментарий от wota

ты уж определись, что у тебя за глупый читатель и как он отреагирует

Я определился. Ты просто не внимательно читаешь.

сформулируй точно задачу и предоставь полное решение с тестовым данными

На входе список типа «list of string option»:

(list "11/11/2013" nil "22:00:00" "January 3")
На выходе «list of string list»:
("11" "11" "2013") ("22" "00" "00") ("January" "3"))
Разбор строк производится по рац. выражениям:
(defconstant +day+  "^(\\w+)\\s+(\\d{1,2})$")
(defconstant +date+ "^(\\d{2})/(\\d{2})/(\\d{4})$")
(defconstant +time+ "^(\\d{2}):(\\d{2}):(\\d{2})$")
В выходном списке None'ы (nil'ы) должны быть поскипаны. Если строка не разберается — exception.

BooBoo
()
Ответ на: комментарий от BooBoo

эта задача не имеет практического смысла, ну и для дат есть удобнейший strptime, ну да ладно, вариант на С++ будет где-то такой:

list<list<string>> res;
smatch m;

for( string s : { "11-11-2013","","22:00:00","January 3" } ) {
    for( regex r : { regex(...), regex(...), ... } ) {
        if( regex_search( s, m, r ) )
            res.push_back( { m.begin(), m.end() } );
    }
}

извиняюсь, что не полностью рабочий вариант - не дружу с регулярными выражениями, а в С++11 тем более еще и формат их другой, не хочу тратить врем на чтение того, чем не пользуюсь, но мы ведь и не их обсуждаем, а так - все остальное рабочее, т.е. конечный вариант будет таким же

wota ★★
()
Последнее исправление: wota (всего исправлений: 1)
Ответ на: комментарий от BooBoo

((ppcre +time+ h m s) (list (list h m s)))))

кстати, а варианта сразу получить список нет? только руками?

wota ★★
()
Ответ на: комментарий от BooBoo

А почему у вас на каждый тест генерируется новый входной файл?

Потому что это не влияет на результат.

Нужно тестировать на одном наборе для всех языков.

Можно и так:

$ make
running C++ tests:  	0:10.98 5408
running SBCL tests: 	1:21.22 396752
checking diffs:     	Ok
# Makefile

CXX=g++
CXXFLAGS=-std=c++11 -O3 -Wall
LDFLAGS=-lstdc++

N=7500

tests: homo-gen-in homo homo.lisp

	@./homo-gen-in $(N) > /tmp/test

	@printf "running C++ tests:  \t"
	@cat /tmp/test | \time -f "%E %M" ./homo > /tmp/c++.result

	@printf "running SBCL tests: \t"
	@cat /tmp/test | \time -f "%E %M" sbcl --noinform --noprint --disable-debugger --load homo.lisp > /tmp/sbcl.result

	@printf "checking diffs:     \t"
	@diff /tmp/c++.result /tmp/sbcl.result > /dev/null && echo Ok || echo C++ result != SBCL result

homo-gen-in: homo-gen-in.o

homo: homo.o

clean:
	rm -f homo-gen-in homo *.o /tmp/{test,c++.result,sbcl.result}
// homo-gen-in.cc

#include <cstdio>
#include <cstdlib>

int main(int argc, char **argv)
{
    int n = atoi(argv[1]);
    printf("%d\n", n * (n - 1));
    for (int i = 0; i < n; ++i) {
        for (int j = 0; j < i; ++j)
            printf("insert %d\n", j);
        for (int j = 0; j < i; ++j)
            printf("delete %d\n", j);
    }
}
quasimoto ★★★★
()
Ответ на: комментарий от BooBoo

Повторения забыл:

// homo-gen-in.cc

#include <cstdio>
#include <cstdlib>

int main(int argc, char **argv)
{
    int n = atoi(argv[1]);

    // http://oeis.org/A064999
    printf("%d\n", ((n - 1) * (n - 1) * (n - 1) - n + 4) / 3 - 1);

    for (int i = 0; i < n; ++i) {
        for (int j = 0; j < i; ++j)
            for (int k = 0; k < j; ++k)
                printf("insert %d\n", j);
        for (int j = 0; j < i; ++j)
            for (int k = 0; k < j; ++k)
                printf("delete %d\n", j);
    }
}
$ make N=250
running C++ tests:  	0:00.72 4272
running SBCL tests: 	0:05.85 340688
$ make N=500
running C++ tests:  	0:06.47 4320
running SBCL tests: 	0:47.30 380208

примечательно, что при N=250 результат почти такой же как на SPOJ.

quasimoto ★★★★
()
Последнее исправление: quasimoto (всего исправлений: 1)
Ответ на: комментарий от BooBoo

По производительности труда, типичный Java кодер не успеет и глазом маргнут, как «соснёт» у типичного Lisp программиста.

Но ведь это миф, культивируемый лисперами. На практике этот миф не имеет подтверждения.

Если Вы не согласны — пожалуйста, приведите доказательства. Например, в следующей форме:

Программное обеспечение XXX было написано на Java N программистами за M часов (ссылка). Программное обеспечение YYY, аналогичное XXX по функциональности, масштабируемости, производительности, доступности, надежности, безопасности, управляемости и расширяемости было написано на Лиспе n программистами (n << N) за m часов (m << M) (ссылка).

Время пошло.

anonymous
()
Ответ на: комментарий от anonymous

Но ведь это миф, культивируемый лисперами.

Нет.

На практике этот миф не имеет подтверждения.

Нет. Подтверждается. Причём заметно не вооруженным глазом. И совершенно не удивительно.

Если Вы не согласны — пожалуйста, приведите доказательства.

Нет. Это бесполезно.

Время пошло.

Нет.

BooBoo
()
Ответ на: комментарий от wota
string s : { "11-11-2013","","22:00:00","January 3" }

Забавный у тебя None :)

На входе список типа «list of string option»

«» должна считаться за строку не подходящую под шаблоны. Соответственно:

Если строка не разберается — exception.

А в целом так я и думал. loop на loop'е :) Невероятно читаемо и лаконично!

BooBoo
()
Ответ на: комментарий от BooBoo

Забавный у тебя None :)
Если строка не разберается — exception.

давай не будем обсуждать побочные эффекты, нормальная обработка ошибок и поведение с ними не связаны

А в целом так я и думал. loop на loop'е :) Невероятно читаемо и лаконично!

              ((ppcre +day+  m d  ) (list (list m d  )))
              ((ppcre +date+ d m y) (list (list d m y)))
              ((ppcre +time+ h m s) (list (list h m s)))))

и это говорит человек, у которого в очередной раз копипаста, а не код, неужели на лиспе по-другому нельзя, только тонны копипаста?

wota ★★
()
Последнее исправление: wota (всего исправлений: 1)
Ответ на: комментарий от wota

и это говорит человек, у которого в очередной раз копипаста, а не код, неужели на лиспе по-другому нельзя, только тонны копипаста?

Где копипаста?

BooBoo
()
Ответ на: комментарий от BooBoo

С++:

        if( regex_search( s, m, r ) )
            res.push_back( { m.begin(), m.end() } );

добавляем новую регулярку - ничего не меняется

Лисп:

              ((ppcre +day+  m d  ) (list (list m d  )))
              ((ppcre +date+ d m y) (list (list d m y)))
              ((ppcre +time+ h m s) (list (list h m s)))))

добавляем новую регулярку - добавляем:

((ppcre ####1 #####2) (list (list #####2)))))

собс-но ты сам это уже сделал

wota ★★
()
Последнее исправление: wota (всего исправлений: 1)
Ответ на: комментарий от wota

и это говорит человек, у которого в очередной раз копипаста, а не код, неужели на лиспе по-другому нельзя, только тонны копипаста?

Okay. (list (list... не шибко какая страшная копипасти, особенно для 3-х веток. И нужно для nconc, что бы отфильтровать nil'ы походу дела. Но можно и по другому сделать:

(remove nil (mapcar #'(lambda (a)
                        (match a
                          ((ppcre +day+  m d  ) (list m d  ))
                          ((ppcre +date+ d m y) (list d m y))
                          ((ppcre +time+ h m s) (list h m s))))
                    (list "11/11/2013" nil "22:00:00" "January 3")))

BooBoo
()
Ответ на: комментарий от wota

добавляем новую регулярку - ничего не меняется

Optima на каждую ветку генерирует свой scope со связываниями. Вместо простого выражения list может быть сколь угодно сложный код. И в каждоё ветке совершенно разный. Всё это записывается декларативно и интуитивно понятно. А для того, чтобы расширить твою версию нужно погрязнуть в if'ах и табличках. В этом простейшем случаем можно сделать конечно и так как ты сделал. Подобный низкоуровневый вариант и на lisp пишеться элементарно. Но конечно я хотел увидить pm на C++.

BooBoo
()
Ответ на: комментарий от BooBoo

Вместо простого выражения list может быть сколь угодно сложный код

тоже мне большое колдунство:

regex_search( s, m, day  ) ? [](){ cout << "day"; } :
regex_search( s, m, date ) ? [](){ cout << "date"; } :
regex_search( s, m, time ) ? [](){ cout << "time"; } :
throw "error!!!";

практически твой код, хотя я забыл - у тебя же фобия к данному оператору ;)

wota ★★
()
Ответ на: комментарий от wota

ну и да - это тоже легко выносится в массив во избежание копипасты

wota ★★
()
Ответ на: комментарий от wota
(macrolet ((matching (obj &body decls)
	     `(match ,obj
		,@(mapcar (lambda (decl)
			    (destructuring-bind (regexp
						 binds
						 &optional positions)
				decl
			      `((ppcre ,regexp
				       ,@binds)
				(list (list ,@(or positions
						  binds))))))))))
  (matching a
	    (+day+ (m d))
	    (+date+ (d m y))
	    (+time+ (h m s))))

Для нелюбителей копипастить

ados ★★★★★
()
Последнее исправление: ados (всего исправлений: 1)
Ответ на: комментарий от ados

спасибо, это просто замечательный пример

wota ★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.