LINUX.ORG.RU

В завершение фразы о Лиспе


0

0

Хотел этим сообщением поставить жирную точку в дискуссии, но по
непонятным мне причинам ветка оказалась закрытой. Так что, чтобы
завершить дискуссию, пришлось открыть новую. Вот такой вот печальный
каламбур :-(.

Итак, до финиша дошло три программы:

Lisp (eugine_kosenko)
http://aroks.kiev.ua/pub/wiki/ProgrammaLabirinta

Python (redvasily)
http://rapidshare.com/files/1245074/advworld2.rar.html

Ocaml (satanic-mechanic)
http://sigma.by.sigma.neolocation.net/satmech/LOR-contest-2006.10.31-00.05.tar

На самом деле авторство несущественно (я, например, пользовался
подсказками), просто для определенности. Сводная статистика следующая:

Параметр                        | Лисп | Питон | Окамл
---------------------------------------------------------
Общая длина                     | 1278 |  1439 |  1283
Смысловая длина                 |  371 |   574 |   403
Общий тезаурус                  |  191 |   190 |   150
Смысловой тезаурус              |  106 |   147 |    93
Общая насыщенность (в %)        |   29 |    40 |    31
Насыщенность тезауруса (в %)    |   55 |    77 |    62
Общая выразительность (в %)     |   15 |    13 |    12
Смысловая выразительность (в %) |   29 |    26 |    23

Читать это можно как угодно, все зависит от того, считать ли стакан
"наполовину полным" или "наполовину пустым". В целом можно сказать,
что на задачах общего плана Лисп, как минимум, чуть-чуть лучше
аналогичных языков. Лисп стал победителем по общей длине (хотя и с
небольшим отрывом), по смысловой длине (примерно в 1.5-2 раза), у него
оказалась самая высокая выразительность (как общая, так и смысловая).
Проиграл Лисп по размеру тезауруса и, как следствие, насыщенности. И
то, проигрыш не абсолютный.

По прогнозам, дальнейшее увеличение сложности мира сохранило бы
пропорции, а вот усложнение языка управления вывело бы Лисп в
абсолютные лидеры. Ибо Лиспу достаточно было бы вывести в язык обычный
REPL (что, кстати, оказалось проще сделать и в этой версии), а вот
Питону, например, пришлось бы использовать для этого внешние костыли
типа TCL.

Наконец, в программе на Ocaml есть занятная багофича: если предмет
бросить на выходе, то он исчезает :-).

> Хотел этим сообщением поставить жирную точку в дискуссии, но по непонятным мне причинам ветка оказалась закрытой.

Ветку никто не закрывал нарочно. Просто с момента её возникновения прошло слишком много времени и она стала старой, а все старые ветки закрыты.

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

А как определяется, что ветка "стала старой"? Сколько времени должно пройти и начиная с какого момента (первого или последнего сообщения)?

eugine_kosenko ★★★
() автор топика

мне как модератору очень стыдно.... но я не нашёл задания :) можете в кратце суть задания рассказать? :)

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

> Сколько времени должно пройти и начиная с какого момента (первого или последнего сообщения)?

С момента возникновения ветки должно пройти, что-то около 40 дней, точное число признаться не помню. Кроме того за историю LOR этот период кажется изменялся.

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

> А где про методику расчета процентов можно почитать ?

Все там же, в ветке "Фраза о Лиспе":

http://www.linux.org.ru/jump-message.jsp?msgid=1587106#1619364 http://www.linux.org.ru/jump-message.jsp?msgid=1587106#1623405

Ну и вообще, сообщения в районе 37-38 страниц:

http://www.linux.org.ru/profile/eugine_kosenko/view-message.jsp?msgid=1587106... http://www.linux.org.ru/profile/eugine_kosenko/view-message.jsp?msgid=1587106...

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

> Слушай, а можешь в двух словах рассказать о методике. А то я че-то в такую дисскусию с нуля не в еду.

Общая длина -- число всех лексем в программе. По идее, определяет основной параметр -- интуитивный размер программы.

Смысловая длина -- число всех значимых лексем (не ключевых слов и не спецсимволов, т.е., идентификаторов, строк, чисел и т.п.). Приблизительно определяет общее количество определений и использования новых сущностей в программе. Параметр может быть определен неточно, так как в "ключевые слова" попали также все идентификаторы, определенные стандартом, или, по другому, использовать которые оказалось возможно без подключения внешних библиотек или пакетов. Сами имена библиотек/пакетов не считаются ключевыми.

Общий тезаурус -- размер словаря программы, число неповторяющихся лексем. Дает грубую оценку общего числа понятий, используемых в программе.

Смысловой тезаурус -- размер смыслового словаря программы, число неповторяющихся значимых лексем (определение такое же, как и для смысловой длины). Дает оценку числа новых понятий, определенных в программе.

Общая насыщенность -- отношение числа смысловой длины к общей, определяет степень "синтаксической засахаренности" наоборот -- чем ниже насыщенность, тем больше в языке синтаксического сахара.

Насыщенность тезауруса -- отношение размера смыслового тезауруса к общему.

Общая выразительность -- отношение размера общего тезауруса к общей длине, характеризует повторяемость, "рутиность", "копипастность" языка. Согласно этому определению BrainF*ck и Whitespace имеют самую низкую выразительность.

Смысловая выразительность -- аналогично общей, отношение смыслового тезауруса к смысловой длине. Для BrainF*ck и Whitespace неопределяема (0/0), но в предельном варианте для них она просто принимается равной нулю.

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

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

> а жаль, хотя бы time пропишите, если на одной машине все скрипты запускаются.

На такой задаче time будет в пределах статистической погрешности. А на Питоне автор вообще замедление вставил, чтобы человек поспевал за машиной.

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

А финальную версию считалки где можно увидеть ? А то к опубликованной на 37-38 странице дискуссии у меня возникли претензии. Подсчет не до конца корректен на мой взгляд. Методика показательна только для тех языков в которых соблюдается правило "одна лексема - одно смысловое понятие". Это неверно например для ocaml-а, где let rec ... in и let ... in - суть единые смысловые конструкции. А in в отдельности никакого особого смысла не несет. Аналогично if, then, else. Аналогично for ... to ... do ... done. Аналогично while ... do ... done. Аналогично match ... with ...

Также непонятно, почему в список ключевых слов лиспа не включены разнообразные символы из loop-а.

Ну и разумеется для вменяемого исследования нужно учитывать природу сущностей и области их видимости. Например, конструкции pattern matching в ocaml-е провоцируют программиста на активное введение сущностей с новыми идентификаторами, с очень короткими "сроками жизни". Такая сущность по смысловой сложности неэквивалентна другим объектам программы. Аналогично макры в лиспе должны тоже считаться как-то по другому, не как функции. Ну и т.д. :) Без оценки природы различных сущностей твой метод сравнения очень приблизительный.

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

> А финальную версию считалки где можно увидеть ?

http://aroks.kiev.ua/pub/wiki/Schitalka

> Это неверно например для ocaml-а, где let rec ... in и let ... in - суть единые смысловые конструкции.

Это можно считать особенностью языка. У каждого языка есть свои особенности синтаксиса. Побеждает тот язык, у которого для единой смысловой конструкции в большинстве случаев нужно наименьшее количество слов.

> Также непонятно, почему в список ключевых слов лиспа не включены разнообразные символы из loop-а.

А как Вы, не видя кода считалки, сделали такой вывод? У Вас есть какие-то косвенные данные или собственная версия считалки? Как раз символы loop и являются типичным примером стандартных ключевых слов. Я мог по невнимательности что-то упустить, ну тогда поправьте меня, пересчитаем.

> Ну и разумеется для вменяемого исследования нужно учитывать природу сущностей и области их видимости.

Я уже в той дискуссии отметил, что методика не претендует на идеальность. В ней важнее соотношение цена/качество/простота.

> Например, конструкции pattern matching в ocaml-е провоцируют программиста на активное введение сущностей с новыми идентификаторами, с очень короткими "сроками жизни".

Ну, если язык "провоцирует" программиста на "нехорошие" вещи, не является ли это еще одним минусом языка? Речь ведь не идет о том, кто кого провоцирует. Условия задачи заданы заранее, и если программист, собрав всю свою волю и не поддаваясь на провокации все же не может ее решить, то считайте, что это косвенным образом говорит еще об одном параметре языка -- его гибкости.

> Аналогично макры в лиспе должны тоже считаться как-то по другому, не как функции.

А они и считаются по другому. Ибо слово defmacro не совпадает со словом defun :-).

> Без оценки природы различных сущностей твой метод сравнения очень приблизительный.

Лучшего (и одновременно реализуемого в рамках JFF), увы, пока не предложили. А если Вы считаете методику "дырявой", то у Вас все еще остается возможность "обмануть" ее :-). Попробуете сделать это на конкретном примере?

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

> Это можно считать особенностью языка. У каждого языка есть свои особенности синтаксиса. Побеждает тот язык, у которого для единой смысловой конструкции в большинстве случаев нужно наименьшее количество слов.

В таком случае непонятено в чем побеждает этот язык. Считаются не смысловые конструкции, которыми оперирует человек, а количество ключевых слов. Основной фишка всех этих in, do, done и т.п. - зрительная структурированность текста программы.

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

> http://aroks.kiev.ua/pub/wiki/Schitalka

Подсчет keywords и meanword неравноценен как минимум для python и lisp.

Ниже приводятся изменения считалки для python (остальная часть прежняя).

Замечания: lexer с :flex-compatible у меня не заработал, поэтому лексер без него, регекспы для слов обрамлены \< и \> чтобы не срабатывал два раза на идентификаторы типа countThings. Дополнен список ключевых слов аналогами (функциями и методами) тех, что есть в лисповом парсере. Добавлен self, как общепринятое обозначение экземпляра класса (доступное без использования доп. библиотек ;).

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

(defun regex-list (lst)
  (cond
    ((eq :word (cadr lst))
     (mapcar (lambda (re)
               `(,(concatenate 'string "\\<" re "\\>") (return (values ,(car lst) lexer:%0))))
             (cddr lst)))
    (t
     (mapcar (lambda (re)
               `(,re (return (values ,(car lst) lexer:%0))))
             (cdr lst)))))

(defmacro defclassifier2 (name class-lst skip-lst)
  `(lexer:deflexer ,name
    ,@(mapcan #'regex-list class-lst)
    ,@(mapcar (lambda (s) `(,s)) skip-lst)))

(defclassifier2 make-python-classifier
    (
     (:keyword 
      "\\|" "\\&" "\\\\" "\\+=" "==" "\\-" "\\{" "\\}" "!=" "%" "," ":" "<" "=" ">" ">=" "\\(" "\\)" "\\*" "\\+" "\\." 
      "\\[" "\\]")
     (:keyword :word
      "import" "from" 
      "for" "if" "while" "in" "else" "pass" "print" "break" "continue"
      "and" "not" "or"
      "True" "False" "None"
      "__class__" "__init__" "__name__" "__unicode__" "__getattr__" "__str__" 
      "class" "cond" "def" "lambda" "return" "yield" 
      "setattr" "getattr"
      "try" "except" "finally" "raise" 
      "dict" "list" "file"
      "append" "keys" "items" "iteritems" "count" "update"
      "join" "startswith" "strip"
      "stdin" "stdout" 
      "readline" "write" "flush"
      "enumerate" "reduce" "xrange" 
      "len" "unicode" "str"
      "self" "sys" "max" "min" "del" 
      "AttributeError")
     (:meanword
      "`[^']+`" "\"[^\"]*\"" "(-)?[0-9]+" "[A-Za-z_][A-Za-z0-9_]*" "u?'[^']*'")
     )
  
  ;;skipword	
  ("^#.*?$" "[:space:]+"))

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

#advworld.py

from pickle import load
from socket import socket, AF_INET, SOCK_STREAM
from sys import stdin, stdout, argv

def clientLoop( cmdRead, echo ) :
    sock = socket( AF_INET, SOCK_STREAM )
    sock.connect( ( argv[1], int(argv[2]) ) )
    sock = sock.makefile()
    sock.write( "world\n" )
    sock.flush()

    world = load( sock )
    stdout.write( str(world) )
    stdout.flush()
    while not world.won() :
        for cmd in cmdRead( world ) :
            if echo :
                stdout.write( cmd )
            sock.write( cmd )
            sock.flush()
            world = load( sock )
            stdout.write( str(world) )
            stdout.flush()

def makeDir( dx, dy ) :
    def move( self, writer ) :
        y, x = self.pos
        p = y+dy, x+dx
        if p not in self.walls :
            self.pos = p
    return move

class World :
    def __init__( self, worldFile ) :
        world = dict([ ((i,j),s) for i,line in enumerate(worldFile) for j,s in enumerate(line) if s in "#$." ])
        self.exit = dict([ (v,p) for p,v in world.iteritems() ])["."]
        self.walls = [ p for p,v in world.iteritems() if v=="#" ]
        self.things = [ p for p,v in world.iteritems() if v=="$" ]
        self.pos = self.exit
        self.inventory = 0

    north = makeDir( 0, -1 )
    south = makeDir( 0, 1 )
    east = makeDir( 1, 0 )
    west = makeDir( -1, 0 )
    nop = makeDir( 0, 0 )

    def pickup( self, writer ) :
        if self.pos in self.things and not self.inventory :
            self.things.remove( self.pos )
            self.inventory = 1

    def drop( self, writer ) :
        if self.inventory :
            self.things.append( self.pos )
            self.inventory = 0

    def gathered( self ) :
        return self.things.count( self.exit )

    def freeThings( self ) :
        return [ x for x in self.things if x!=self.exit ]

    def won( self ) :
        return not self.freeThings() and not self.inventory

    def __getattr__( self, name ) :
        if name.startswith( "__" ) :
            raise AttributeError
        return self.nop

    def __str__( self ) :
        maxy, maxx = reduce( lambda a,x: (max(a[0],x[0]),max(a[1],x[1])), self.walls )
        world = dict.fromkeys( self.things, "$" )
        world.update( dict.fromkeys( self.walls, "#" ) )
        world.update({ self.exit:".", self.pos:"@" })
        return "\n".join([ "".join([ (world[(y,x)] if (y,x) in world else " ")  for x in xrange(maxx+1) ]) for y in xrange(maxy+1) ] + [ ("You won!" if self.won() else "Game in progress"), ("You carry an item" if self.inventory else "Your hands are empty"), "Here lies %d item(s)" % self.things.count( self.pos ), "> " ])

#advserve.py
#!/usr/bin/env python2.5

from advworld import World
from pickle import dump
from socket import socket, AF_INET, SOCK_STREAM
from sys import argv

sock = socket( AF_INET, SOCK_STREAM )
sock.bind( ( "", int(argv[2]) ) )
sock.listen(5)
while True :
    fd = sock.accept()[0].makefile()
    world = World( file( argv[1], "r" ) )
    for cmd in fd :
        getattr( world, cmd.strip() )( fd )
        dump( world, fd )
        fd.flush()

#hclient.py
#!/usr/bin/env python2.5

from advworld import clientLoop
from sys import stdin

def cmdRead( world ) :
    yield stdin.readline()

clientLoop( cmdRead, False )

#roboclient.py
#!/usr/bin/env python2.5

from advworld import clientLoop

dirs = { (-1,0): "north\n", (1,0): "south\n", (0,-1): "west\n", (0,1): "east\n" }
def genPath( world ) :
    yield world.pos, None
    paths = { world.pos: None }
    lastpaths = { world.pos: None }
    while True :
        for p,v in lastpaths.items() :
            for dx,dy in dirs.keys() :
                np = p[0]+dy,p[1]+dx
                if np not in paths and np not in world.walls :
                    paths[np], lastpaths[np] = p, p
                    yield np,p
            del lastpaths[p]

def buildPath( world ) :
    result = ["pickup\n"]
    paths = {}
    for p,v in genPath( world ) :
        paths[p] = v
        if p in world.freeThings() :
            while paths[p] :
                dy, dx, p = p[0]-paths[p][0], p[1]-paths[p][1], paths[p]
                result = [dirs[(dy,dx)]] + result + [dirs[(-dy,-dx)]]
            return result+["drop\n"]

clientLoop( buildPath, True )

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

Статистика:

Total length 1101
Meaning length 350
Total thesaurus 153
Meaning thesaurus 91
Total saturation (%) 32
Thesaurus saturation (%) 59
Total expressiveness (%) 14
Meaning expressiveness (%) 26

Смотрится не так плохо в сравнении с другими языками. Непустых строк и не комментариев: 109
На мой взгляд, слишком примитивная задачка, чтобы сравнивать те же lisp и python.

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

> В таком случае непонятно в чем побеждает этот язык.

Считайте, что вот в этом:

> Основной фишка всех этих in, do, done и т.п. - зрительная структурированность текста программы.

и побеждает.

> Считаются не смысловые конструкции, которыми оперирует человек, а количество ключевых слов.

Этот параметр слишком сложно формализовать, чтобы претендовать на объективность.

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

> Подсчет keywords и meanword неравноценен как минимум для python и lisp.

Можно пояснить словами, в чем неравноценен?

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

> На мой взгляд, слишком примитивная задачка, чтобы сравнивать те же lisp и python.

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

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

> Кстати в ocaml-е .mli тоже считаются ?

Нет. Как я понял, они генерируются во время сборки, то есть, дополнительной информации не несут.

> А где там блокиратор комментариев для ocaml-а что-то я не догнал ?

Нету :-(. У cl-lexer серьезные проблемы с переменными состояния, поэтому блочные комментарии пришлось выбрасывать вручную.

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

> Смотрится не так плохо в сравнении с другими языками.

Гы. Как по мне, подозрительно короткий код поиска путей. Сейчас нет под рукой настроенной машинки, дома посмотрю. Есть серьезное подозрение, что выигрыш за счет более удачного алгоритма, и его портирование в Лисп тоже сократит код (эта часть мне в Лисп версии самому не нравится). Кстати, как я понял, представление мира тоже приняли то, что я использовал в Лиспе. Но код тоже визуально короче.

В общем, когда будет время, попробую портировать этот код (если он таки рабочий) в Лисп -- он мне нравится :-).

LOR contest продолжается... :-).

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

> def makeDir( dx, dy ) : > def move( self, writer ) : > y, x = self.pos > p = y+dy, x+dx > if p not in self.walls : > self.pos = p > return move

Я так понял, это замыкание? :-)

А можно пояснить сакральный смысл параметра writer, который (на первый взгляд) нигде не используется?

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

$ python hclient.py "world.dat" 7766
Traceback (most recent call last):
  File "hclient.py", line 3, in ?
    from advworld import clientLoop
  File "/home/eugine/my/study/lisp/lab/python/2/advworld.py", line 77
    return "\n".join([ "".join([ (world[(y,x)] if (y,x) in world else " ")  for x in xrange(maxx+1) ]) for y in xrange(maxy+1) ] + [ ("You won!" if self.won() else "Game in progress"), ("You carry an item" if self.inventory else "Your hands are empty"), "Here lies %d item(s)" % self.things.count( self.pos ), "> " ])
                                                ^
SyntaxError: invalid syntax

Я так понял, это все прелести синтаксиса Python версии 2.5? То-то я
смотрю, что это какой-то не такой Питон. Ну, в смысле, не такой, каким
его проходят в школе :-).

Ладно, условно зачтем, потому как решение красивое и интуитивно
понятное. Посмотрим, что этому может противопоставить Лисп. Кстати,
совершенно не отметились поклонники Рубина, а ведь по слухам, их
синтаксис по краткости рвет все остальные языки...

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

> Можно пояснить словами, в чем неравноценен?

В лисповой версии в :keywords были внесены операции типа append, concatenate, with-open-file и т.п. Их python-аналогов в анализаторе для python я не нашел. Может, он писался для программы, где этого не использовалось.

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

> Я так понял, это замыкание? :-)

Да. Возвращаемая функция становится впоследствии методом.

> можно пояснить сакральный смысл параметра writer, который (на первый взгляд) нигде не используется?

Да, забыл выкинуть :) В каком-то из промежуточных вариантов методы-команды могли что-то выдавать обратно через file-like объект (коим является в данном случае сокет, если взглянуть на advserver.py). Потом надобность в выводе отпала, а параметр остался. Можно еще чуток улучшить "качество" программы, если его выкинуть.

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

> Я так понял, это все прелести синтаксиса Python версии 2.5?

Да. Используется тернарная операция if-else:

(world[(y,x)] if (y,x) in world else " ") можно записать даже короче: world.get( (y,x), " " )

Для подстановки сообщений дальше по списку придется городить полноценные if'ы или извращаться с dict'ами, что будет длиннее.

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

> В лисповой версии в :keywords были внесены операции типа append, concatenate, with-open-file и т.п. Их python-аналогов в анализаторе для python я не нашел. Может, он писался для программы, где этого не использовалось.

Эти слова определены в Лисп стандартом, а функции доступны без подключения дополнительных модулей. Как я понял, соединение и конкатенация в Питоне определяются с помощью перегрузки плюса, а фрейм with- просто отсутствует. То есть, это тоже косвенно отражает возможности языка.

eugine_kosenko ★★★
() автор топика
Ответ на: комментарий от ero-sennin

> Уже присутствует в Питоне-2.5. :)

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

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

Да блин, в Питоне это обычная практика добавления новых ключевых слов. :) Чтоб не поломать старый код, эта фича пока отключена по умолчанию. Чтобы её включить, надо сделать from __future__ import with_statement. В следующей версии она будет включена всегда.

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

> Да блин, в Питоне это обычная практика добавления новых ключевых слов. :)

То есть, таким образом можно заставить эту программу работать у меня под 2.4?

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

Нет. :) В 2.4 этого нет. В 2.5 надо включать вручную. В 2.6 будет "искаропки". :)

ero-sennin ★★
()
Ответ на: комментарий от eugine_kosenko

> Эти слова определены в Лисп стандартом, а функции доступны без подключения дополнительных модулей.

Ну вот я и добавил в python-версию имена методов стандартных типов, т.к. они, в некотором роде, тоже определены стандартом языка и доступны без подключения доп. модулей.

> Как я понял, соединение и конкатенация в Питоне определяются с помощью перегрузки плюса

Ну, для list'а есть еще .append() и .extend(), для dict'а есть .update() и т.п. Аналогом with-open-file я посчитал для своего случая конструктор file().

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

> Ну вот я и добавил в python-версию имена методов стандартных типов, т.к. они, в некотором роде, тоже определены стандартом языка и доступны без подключения доп. модулей.

Ну, по идее, такие вещи легко определяются методом запуска, но я увы, пока еще морально не готов ставить Python 2.5 на своем Gentoo, а ковыряться со сборкой в отдельном месте просто нет времени. Посему придется поверить Вам на слово.

Тут возникла несколько иная проблема. В процессе портирования волнового алгоритма возникло серьезное подозрение, что в опубликованном виде он неработоспособен. Дело в том, что при проверке валидности соседних клеток проверяется только их принадлежность к множеству стен (ну и разметки). То есть, выход за пределы лабиринта не проверяется. Это работает для замкнутого мира (который со всех сторон ограничен стенами), и в большинстве случаев это проходит. Хотя, если пользователь стоит на входе/выходе, то он может сделать шаг за пределы лабиринта, и система это никак не контролирует. Аналогично, если запустить волновой алгоритм, то он начнет генерировать пути за пределами лабиринта, и зациклится.

По крайней мере, у меня в Лисп-версии сейчас так, и я пока поставил затычку для конкретного случая, чтобы полностью написать алгоритм, а потом разобраться с этим отдельно. Могу ведь вообще опубликовать в "незащищенном" виде, хотя это и неспортивно. Покажете по быстрому, где именно стоит блокировка выхода? Я, в принципе, вижу вариант с установкой дополнительных стен при генерации мира, но это а) усложнит решение и б) я не вижу соответствующего кода при генерации мира.

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

> Ну вот я и добавил в python-версию имена методов стандартных типов, т.к. они, в некотором роде, тоже определены стандартом языка

В версии 2.5?

> Ну, для list'а есть еще .append() и .extend(), для dict'а есть .update() и т.п. Аналогом with-open-file я посчитал для своего случая конструктор file().

Согласен, это мог и пропустить.

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

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

Он работоспособен для "правильного" лабиринта. Т.е. такого, в котором нет недостижимых items. То, что алгоритм генерит пути за пределами --- не страшно.

Блокировка выхода --- как только нашли путь до клетки, на которой есть thing (p in freeThings()). Сам алгоритм ищет только один путь до вещи, которую нашел первой. В clientLoop есть проверка на world.won(), которая прекращает выполнение после победы.

Просто, в найденном мной условии ничего не говорилось про защиту от невалидных данных, иначе придется еще учитывать лабиринты без входа и прочие радости.

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

> В версии 2.5?

В любой. Есть стандартная документация к Python, в которой описаны типы данных и их методы. Стандартные типы --- в модуле __builtins__.

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

> LOR contest продолжается... :-).

Еще один круг в состязании Питона и Лиспа:

http://aroks.kiev.ua/pub/wiki/ProgrammaLabirinta

Параметр                        | Лисп | Питон | Окамл
------------------------------------------------------
Общая длина                     |  883 |  1101 |  1283
Смысловая длина                 |  246 |   350 |   403
Общий тезаурус                  |  158 |   153 |   150
Смысловой тезаурус              |   81 |    91 |    93
Общая насыщенность (в %)        |   28 |    32 |    31
Насыщенность тезауруса (в %)    |   51 |    59 |    62
Общая выразительность (в %)     |   18 |    14 |    12
Смысловая выразительность (в %) |   33 |    26 |    23

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

Самое главное достижение -- преодоление символической планки в 1000
слов :-).

eugine_kosenko ★★★
() автор топика

[advserver.k]
map: 0: *_i; h:#map; w: #*map
l:#m:,/map
S:m?"."; T:&m="$"; ic:#T;  P:S;carry: 0
m:~m="#"
won:  {ic=+/T=S}
here: {+/T=P}
move: {if[m[x]; P::x]}
north:{if[P>w; move[P-w]]}
east: {if[(P+1)!w; move[P+1]]}
west: {if[P!w; move[P-1]]}
south:{if[l>P+w; move[P+w]]}
take: {p:T?P; if[(carry=0)&(p<#T); carry+:1; T::T _di p]}
drop: {if[carry>0; carry-:1; T::T,P]}
cmd:{(`north`east`west`south`take`drop`)["newstd"?x][];smap[]}
smap:{(h;w)#@["# "m;T,S,P;:;((#T)#"$"),".@"]}
swon:{:[won[];"You won!";"Game is in progress"]}
scarry:{:[carry;"You carry an item"; "Your hand are empty"]}
shere:{"Here lies ", ($here[]), " item(s)" }
.m.s:{cmd'x}


[hclient.k]
srv: (`;0) $ _i
show:{{`0:x;`0:"\n"}'srv 4:"(smap[];swon[];scarry[];shere[])";}
read:{`0:"newstd>";0:`}
show[];while[~srv 4:"won[]";srv 3:read[];show[]]

[rclient.k]
srv: (`;0) $ _i
.k[`m`h`w`S`T]:srv 4:"(m;h;w;S;T)"
l:#m
nb:{t:,/(:[x>w;,x-w;!0];:[x!w;,x-1;!0];:[(x+1)!w;,x+1;!0];:[l>x+w;,x+w;!0]
);t@&m[t]}
d:l#l;d[S]:0;{u:x@*<d[x];d[nb[u]]&:d[u]+1;x _dv u}/ &m;
path:{{d[x]>0}{t:nb[x];t@d[t]?d[x]-1}\x}
p2c:{{"news"@(-w;1;-1;w)?x}'-':x}
plan:{q:path[x]; p2c[|q],"t",p2c[q],"d"}
show:{{`0:x;`0:"\n"}'srv 4:"(smap[];swon[];scarry[];shere[])";}
step:{srv 3:x;show[]}
step',/plan'T;


Общая длина                     | 675
Смысловая длина                 | 240
Общий тезаурус                  | 111
Смысловой тезаурус              |  76
Общая насыщенность (в %)        |  35
Насыщенность тезауруса (в %)    |  68
Общая выразительность (в %)     |  16
Смысловая выразительность (в %) |  31

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