Модераторы: LSD

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Функциональные языки против традиционных, ML, OCaml, Haskell против С++, Java, C# 
:(
    Опции темы
 
Как, по-вашему, что в итоге будет более востребовано со временем?
Традиционные языки программирования [ 55 ]  [78.57%]
Функциональные языки программирования [ 15 ]  [21.43%]
Всего проголосовавших: 70
В этом опросе возможен один вариант ответа
Гости не могут голосовать 
GoldFinch
Дата 27.3.2009, 13:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата



****


Профиль
Группа: Завсегдатай
Сообщений: 2141
Регистрация: 30.11.2008

Репутация: нет
Всего: 26



Lazin, я тольк что предложил алгоритм, вот его и напиши на ФЯ
PM MAIL ICQ   Вверх
Lazin
Дата 27.3.2009, 15:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3820
Регистрация: 11.12.2006
Где: paranoid oil empi re

Репутация: 4
Всего: 154



Цитата(GoldFinch @  27.3.2009,  13:57 Найти цитируемый пост)
Lazin, я тольк что предложил алгоритм, вот его и напиши на ФЯ

если ты это имел ввиду
Цитата(GoldFinch @  27.3.2009,  12:34 Найти цитируемый пост)
1) получить указатель на структуру PEB из FS:[0x30]
2) пройтись по цепочке указателей в структурах до связанного списка структур описывающих загруженные модули
3) поиском по этому связанному списку найти структуру нужного модуля
4) взять в этой структуре искомый хендл

то он будет выглядеть так-же, да и не серьезно это как-то)
я имел ввиду что-то более серьезное, например реализовать какой-нибудь алгоритм на графе, поиск кратчайшего пути например
то, что на haskell/ocaml/erlang нет смысла писать системные приложения это всем и так понятно
PM MAIL Skype GTalk   Вверх
Void
Дата 27.3.2009, 20:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


λcat.lolcat
****


Профиль
Группа: Участник Клуба
Сообщений: 2206
Регистрация: 16.11.2004
Где: Zürich

Репутация: 11
Всего: 173



Цитата(Lazin @  27.3.2009,  17:06 Найти цитируемый пост)
я имел ввиду что-то более серьезное, например реализовать какой-нибудь алгоритм на графе, поиск кратчайшего пути например

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

А почему, собственно, нет. Haskell — неплохой императивный язык smile
GoldFinch, у меня нет GHC на Windows, так что код я не проверял и вполне мог не всё понять правильно из MSDN, но для иллюстрации пойдёт (здесь с подсветкой):
Код

import Foreign
import Data.List
import qualified Data.Text as T
import Data.Text.Foreign
import Data.Word

data Entry = Offset Int | DeRef

peekAt :: Storable a => [Entry] -> Ptr b -> IO a
peekAt [] p = peek $ castPtr p
peekAt (Offset n : path) p = peekAt path (p `plusPtr` n)
peekAt (DeRef : path) p = peek (castPtr p) >>= peekAt path

sizeT = sizeOf (undefined :: IntPtr)

{- typedef struct _LSA_UNICODE_STRING {
   USHORT Length;
   USHORT MaximumLength;
   PWSTR  Buffer;
} UNICODE_STRING; -}
newtype UnicodeString = UnicodeString String deriving (Eq, Ord, Show)

instance Storable UnicodeString where
    sizeOf _ = 4 + sizeT
    alignment _ = 4 -- ??
    peek p = do
        length <- (peek $ castPtr p) :: IO Word16
        str <- peekAt [Offset 4] p
        text <- fromPtr str (fromEnum $ length `div` 2)
        return $ UnicodeString $ T.unpack text
    poke _ _ = error "Not implemented"

{- typedef struct _LIST_ENTRY {
   struct _LIST_ENTRY *Flink;
   struct _LIST_ENTRY *Blink;
} LIST_ENTRY; -}
data ListEntry a = ListEntry {
      backLink :: Ptr a
    , forwardLink :: Ptr a
    }

instance Storable (ListEntry a) where
    sizeOf _ = 2 * sizeT
    alignment _ = 4 -- ??
    peek p = do
        back <- peek $ castPtr p
        forward <- peek $ castPtr (p `plusPtr` sizeT)
        return $ ListEntry back forward
    poke _ _ = error "Not implemented"

readNext :: (Storable a) => ListEntry a -> IO (Maybe a)
readNext entry =
    let p = forwardLink entry in
    if p == nullPtr then return Nothing
    else peek p >>= return . Just

readDList :: (Storable a) => ListEntry a -> (a -> ListEntry a) -> IO [a]
readDList head extract = do
    entry <- readNext head
    case entry of
        Just x -> readDList (extract x) extract >>= return . (x:)
        Nothing -> return []

{- typedef struct _LDR_DATA_TABLE_ENTRY {
    BYTE Reserved1[2];
    LIST_ENTRY InMemoryOrderLinks;
    PVOID Reserved2[2];
    PVOID DllBase;
    PVOID EntryPoint;
    PVOID Reserved3;
    UNICODE_STRING FullDllName;
    BYTE Reserved4[8];
    PVOID Reserved5[3];
    union {
        ULONG CheckSum;
        PVOID Reserved6;
    };
    ULONG TimeDateStamp;
} LDR_DATA_TABLE_ENTRY; -}
data LdrTableEntry = LdrTableEntry {
      listEntry :: ListEntry LdrTableEntry
    , fullDllName :: UnicodeString
    , dllBase :: IntPtr
    }

instance Storable LdrTableEntry where
    sizeOf _ = 66 -- лень считать с sizeT было
    alignment _ = 4 -- ??
    peek p = do
        entry <- peekAt [Offset 2] p
        base <- peekAt [Offset 18] p
        name <- peekAt [Offset 30] p
        return $ LdrTableEntry entry name base

getModuleHandle :: String -> IO (Maybe IntPtr)
getModuleHandle modName = do
    pPEB <- getPEBPtrByForeignMagic -- дёргаем единственную внешнюю функцию на Си
    head <- peekAt [Offset $ 4 + 2 * sizeT, DeRef, Offset $ 8 + 3 * sizeT] pPEB
    list <- readDList head listEntry
    let x = find (\x -> fullDllName x == UnicodeString modName) list >>= return . dllBase
    return x

Если всерьёз понадобится много тягать внешние структуры из Haskell, можно соорудить библиотечку EDSL, сделать deriving Storable на Template Haskell и т.д.

Предлагаю реализовать на чём угодно вторую задачу из конкурса дельфистов, на многопоточное программирование. Визуализацию можно консольную, но с GUI будет идеально. С меня решение на Haskell. Холивар? smile

Это сообщение отредактировал(а) Void - 27.3.2009, 20:00


--------------------
“Coming back to where you started is not the same as never leaving.” — Terry Pratchett
PM MAIL WWW GTalk   Вверх
GoldFinch
Дата 27.3.2009, 20:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата



****


Профиль
Группа: Завсегдатай
Сообщений: 2141
Регистрация: 30.11.2008

Репутация: нет
Всего: 26



Цитата(Void @  27.3.2009,  20:00 Найти цитируемый пост)
Предлагаю реализовать на чём угодно вторую задачу из конкурса дельфистов, на многопоточное программирование. Визуализацию можно консольную, но с GUI будет идеально. С меня решение на Haskell. Холивар?

хорошая идея)
PM MAIL ICQ   Вверх
Lazin
Дата 27.3.2009, 22:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3820
Регистрация: 11.12.2006
Где: paranoid oil empi re

Репутация: 4
Всего: 154



smile

Добавлено через 11 минут и 53 секунды
Цитата(Void @  27.3.2009,  20:00 Найти цитируемый пост)
Предлагаю реализовать на чём угодно вторую задачу из конкурса дельфистов,

я не понял, в чем прикол задачи, придумать алгоритм поведения для хулигана и для дворника? или просто сделать это все через потоки?
PM MAIL Skype GTalk   Вверх
Void
Дата 27.3.2009, 22:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


λcat.lolcat
****


Профиль
Группа: Участник Клуба
Сообщений: 2206
Регистрация: 16.11.2004
Где: Zürich

Репутация: 11
Всего: 173



Цитата(Lazin @  28.3.2009,  00:35 Найти цитируемый пост)
я не понял, в чем прикол задачи, придумать алгоритм поведения для хулигана и для дворника? или просто сделать это все через потоки? 

Просто реализовать описанное асинхронное поведение.
Вот это условие:
Цитата(Alexeis @  10.10.2008,  11:53 Найти цитируемый пост)
  Условие поимки. Попытка одновременного доступа (2х потоков) к общей ячейке.

мы переформулируем, чтобы не заострять внимание на деталях реализации:
Цитата
Хулиган пойман, когда ячейка, в которой он находился, подверглась очистке со стороны дворника.



--------------------
“Coming back to where you started is not the same as never leaving.” — Terry Pratchett
PM MAIL WWW GTalk   Вверх
Lazin
Дата 27.3.2009, 23:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3820
Регистрация: 11.12.2006
Где: paranoid oil empi re

Репутация: 4
Всего: 154



то-есть они не должны как-то оптимизировать свое поведение, что-бы увеличить шанс успеха?
PM MAIL Skype GTalk   Вверх
Void
Дата 27.3.2009, 23:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


λcat.lolcat
****


Профиль
Группа: Участник Клуба
Сообщений: 2206
Регистрация: 16.11.2004
Где: Zürich

Репутация: 11
Всего: 173



Lazin, нет, задачка чисто техническая. В оригинале предлагалось минимизировать блокировки, ну а нам надо бы показать, что есть весёлого в ФЯ на тему параллелизма smile


--------------------
“Coming back to where you started is not the same as never leaving.” — Terry Pratchett
PM MAIL WWW GTalk   Вверх
Void
Дата 1.4.2009, 23:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


λcat.lolcat
****


Профиль
Группа: Участник Клуба
Сообщений: 2206
Регистрация: 16.11.2004
Где: Zürich

Репутация: 11
Всего: 173



Придётся первому, значит smile

Сразу решил делать что-то вроде актёров: два потока, хулиган и дворник, отсылают через асинхронную очередь сообщения третьему, который хранит состояние поля и обновляет его в соответствии с полученными данными. Очередь на основе STM уже в стандартной библиотеке. Актёр крутится в бесконечном цикле, при этом его состояние хранится в монаде State.
Визуализацию сделал на Gtk2Hs и Cairo. Скриншот в аттаче. Поскольку GTK не потокобезопасен, получилось четыре потока: добавился главный поток GUI, в контексте которого можно выполнить действие с помощью библиотечной функции postGUIAsync.

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

Тестировал на Linux с GHC 6.10.1 и Gtk2Hs 0.10.0. На 6.8.* не скомпилируется из-за изменений в системе исключений, а с 6.10 работает Gtk2Hs не ранее 0.10, так что свободы выбора особо нет. Собирать с -threaded, конечно же.
с подсветкой
Код

{-# LANGUAGE GADTs, FlexibleContexts, DeriveDataTypeable #-}
import Control.Concurrent
import Control.Concurrent.STM
import Control.Exception
import Control.Monad
import Control.Monad.State
import Data.Array.Diff
import Data.Maybe
import Data.Typeable
import Graphics.Rendering.Cairo hiding (scale)
import Graphics.Rendering.Cairo.Matrix
import Graphics.UI.Gtk hiding (get, fill)
import Graphics.UI.Gtk.Abstract.Widget
import System.IO
import System.Random

sendMsg :: TChan a -> a -> IO ()
sendMsg chan msg = atomically $ writeTChan chan msg

sendMsgs :: TChan a -> [a] -> IO ()
sendMsgs chan msgs = atomically $ forM_ msgs $ writeTChan chan

loBound = 1
hiBound = 60

data Message = ComeTo Int | DropBag | Disappear | Clean [Int] deriving (Eq, Show)

newtype HooliganS = HooliganS {
      bagCount :: Int
    }

hooligan :: TChan Message -> StateT HooliganS IO ()
hooligan chan = forever $ do
    bags <- gets bagCount
    let drop = bags > 0
    when drop $ put $ HooliganS (bags - 1)
    liftIO $ do
        pos <- randomRIO (loBound, hiBound)
        sendMsgs chan $ [ComeTo pos] ++ if drop then [DropBag] else []
        threadDelay 60000
        sendMsg chan Disappear
        threadDelay 300000

runHooligan :: TChan Message -> IO ()
runHooligan chan =
    evalStateT (hooligan chan) (HooliganS 22)

data JanitorS = JanitorS {
      position :: Int
    , direction :: Int
    }

janitor :: TChan Message -> StateT JanitorS IO ()
janitor chan = forever $ do
    (JanitorS pos dx) <- get
    let clean = [x | x <- [pos - 1 .. pos + 1], x >= loBound && x <= hiBound]
    liftIO $ sendMsg chan $ Clean clean
    let dx' = if pos == loBound && dx < 0 || pos == hiBound && dx > 0 then -dx else dx
    put $ JanitorS (pos + dx') dx'
    liftIO $ threadDelay 400000

runJanitor :: TChan Message -> IO ()
runJanitor chan =
    evalStateT (janitor chan) (JanitorS loBound 1)

data Cell = Empty | Bag

data Field where
    Field :: IArray a Cell => a Int Cell -> Field

data Playground = Playground {
      hooliganPos :: Maybe Int
    , janitorPos :: [Int]
    , field :: Field
    }

instance Show Playground where
    show (Playground hooligan janitor (Field field)) =
        map pchar (assocs field)
            where pchar (i, _)
                    | (Just i) == hooligan = 'H'
                    | i `elem` janitor = 'J'
                  pchar (_, Empty) = '.'
                  pchar (_, Bag) = 'X'

updateField p@(Playground _ _ (Field a)) d = p { field = Field $ a // d }

data HooliganCaught = HooliganCaught Int deriving (Show, Typeable)

instance Exception HooliganCaught

mainLoop :: TChan Message -> (Playground -> IO ()) -> IO ()
mainLoop chan draw = do
    let field = listArray (loBound, hiBound) (repeat Empty) :: DiffArray Int Cell
    catchJust (\e -> (fromException e) :: Maybe HooliganCaught)
        (evalStateT loop (Playground Nothing [] (Field field)))
        (const $ return ()) where
        loop = do
            state@(Playground hooligan janitor (Field field)) <- get
            liftIO $ draw state
            let caught = (hooligan >>= return . (`elem` janitor)) == Just True
            when caught $ liftIO $ throwIO $ HooliganCaught $ fromJust hooligan
            msg <- liftIO $ atomically $ readTChan chan
            liftIO $ print msg
            put $ case msg of
                    ComeTo x -> state { hooliganPos = Just x }
                    DropBag -> updateField state [(fromJust hooligan, Bag)]
                    Disappear -> state { hooliganPos = Nothing }
                    Clean xs -> (updateField state (zip xs $ repeat Empty)) { janitorPos = xs }
            loop

renderPlayground :: Playground -> Render ()
renderPlayground (Playground hooligan janitor (Field field)) = do
    setSourceRGB 255 255 255
    paint
    let cellRGB x r g b = do
            setSourceRGB r g b
            newPath
            rectangle (realToFrac $ x - 1) 0 1 1
            fill
    let drawElem (i, _)
            | (Just i) == hooligan =
                if fromJust hooligan `elem` janitor then do
                    setSourceRGB 255 0 0
                    newPath
                    arc (realToFrac i - 0.5) 0.5 0.4 0 (2 * pi)
                    fill
                else cellRGB i 255 255 0
            | i `elem` janitor = cellRGB i 255 0 0
        drawElem (i, Bag) = cellRGB i 0 0 255
        drawElem (_, Empty) = return ()
    forM_ (assocs field) drawElem

drawPlayground :: WidgetClass a => a -> Playground -> IO ()
drawPlayground widget playground = postGUIAsync $ do
    drawWindow <- widgetGetDrawWindow widget
    (w, h) <- drawableGetSize drawWindow
    drawWindowBeginPaintRect drawWindow (Rectangle 0 0 w h)
    renderWithDrawable drawWindow $ do
        setMatrix $ scale 15 15 identity
        renderPlayground playground
    drawWindowEndPaint drawWindow

main = do
    unsafeInitGUIForThreadedRTS
    window <- windowNew
    set window [ containerBorderWidth := 10, windowTitle := "Hooligan and Janitor",
                 windowWindowPosition := WinPosCenter ]
    window `onDestroy` mainQuit
    area <- drawingAreaNew
    area `onSizeRequest` return (Requisition 900 15)
    buttonQuit <- buttonNewWithLabel "Quit"
    buttonQuit `onClicked` (widgetDestroy window)
    vbox <- vBoxNew False 20
    window `containerAdd` vbox
    boxPackStartDefaults vbox area
    boxPackStartDefaults vbox buttonQuit
    
    chan <- newTChanIO
    t1 <- forkIO $ runHooligan chan
    t2 <- forkIO $ runJanitor chan
    forkIO $ do
        mainLoop chan (drawPlayground area)
        killThread t1
        killThread t2
    
    widgetShowAll window
    mainGUI



Это сообщение отредактировал(а) Void - 2.4.2009, 00:27

Присоединённый файл ( Кол-во скачиваний: 21 )
Присоединённый файл  hooligan.png 6,61 Kb


--------------------
“Coming back to where you started is not the same as never leaving.” — Terry Pratchett
PM MAIL WWW GTalk   Вверх
Unlocker
Дата 2.4.2009, 09:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 125
Регистрация: 2.11.2007
Где: Москва - Знаменск (Капустин Яр)

Репутация: нет
Всего: 2



Прошу не считать меня невеждой, но в обсуждении я так и не нашел хотя бы краткого перечня задач, для которого программирование на функциональных языках будет по каким-то причинам предпочтительнее, чем на традиционных.
Я ни разу не писал код на Haskell или Ocaml (использовал Python одно время для инженерных расчетов), но из обсуждения непонятно есть ли перспектива изучения подобных языков и в каких областях. Как коррелируется изучение этого класса ЯП с применением в различных практических областях?
Прошу внести ясность, если кто-то может.

Это сообщение отредактировал(а) Unlocker - 2.4.2009, 09:56
--------------------
"Если бы Шекспир был программистом, то фразу "To be or not to be" он написал бы так: 2b | ! 2b."
PM MAIL ICQ Skype GTalk Jabber   Вверх
Rickert
Дата 2.4.2009, 10:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Ситхи не пройдут!
****


Профиль
Группа: Комодератор
Сообщений: 3356
Регистрация: 11.7.2006
Где: Лакрима

Репутация: нет
Всего: 52



Будущее за классикой, ибо она - золотая середина вся.


--------------------
Ни что не внушает сна крепче, чем день приисполненный трудов!
PM MAIL WWW Skype GTalk   Вверх
Void
Дата 2.4.2009, 15:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


λcat.lolcat
****


Профиль
Группа: Участник Клуба
Сообщений: 2206
Регистрация: 16.11.2004
Где: Zürich

Репутация: 11
Всего: 173



Unlocker, во-первых, не обязательно противопоставлять ФП привычному структурному и ОО-подходу. Они вполне могут сочетаться, и тому есть хорошие примеры: F#, Scala.
Трудно сразу показать на практическом примере преимущества ФП. Обычно следуют такие возражения:
1. Это непонятно. Пусть при императивном подходе будет больше кода, но я его быстрее напишу и другие быстрее поймут.
2. Как следствие из предыдущего: где найти программистов, которые будут это поддерживать и кто мне позволит использовать ФЯ на работе?
3. Это неэффективно и будет тормозить.
4. Для ФЯ нет инфраструктуры: библиотек и сред разработки.
Всё это в какой-то мере справедливо. Глупо выдавать ФП за серебряную пулю, но перечисленного недостаточно, чтобы закрыть на него глаза.
ФП, как и любое новшество, требует времени на обучение. Нет никаких доказательств того, что ФП фундаментально сложнее. Напротив, оно ориентировано на работу от базовых принципов, а не перечисление неформальных особенностей поведения. ФП благосклонно к более формальному подходу, но отнюдь не требует зубодробительной математики. Неоднократно слышал, как программист, поставленный перед необходимостью использования ФЯ на работе (да, бывает и такое), в минимальные сроки разбирался и начинал писать код — не больше проблем, чем с очередным фреймворком (пруфлинк, первый попавшийся).
Гибридные языки вроде F# позволяют сохранить привычную компонентную структуру на высоком уровне и в то же время получить в распоряжение набор новых инструментов для создания программной логики уровнем ниже. Возьму на себя смелость утверждать, что подход, основанный на композиции чистых функций над неизменяемыми структурами данных, проще, легче поддерживается и менее подвержен ошибкам.
Тем, кто работает на платформе .NET, однозначно надо попробовать F#. Microsoft тянет его в мейнстрим и одновременно обогащает C# ФП-возможностями. Заодно отпадает вопрос об IDE и библиотеках.
Другое направление, в виде Haskell, стремится развить как можно более строгую систему типов со статическими проверками. Здесь сложнее обещать немедленный эффект, но на мой взгляд стоит хотя бы попробовать, что такое отделение чистых функций на уровне типов, классы типов, всеобщая ленивость и т.д.

Задачку никто больше решать не будет? Erlang бы взял кто-нибудь, хоть с консолью, хоть с gs.
А код на Haskell комментировать? Хотя бы в духе «это хуже чем Perl» :-)


--------------------
“Coming back to where you started is not the same as never leaving.” — Terry Pratchett
PM MAIL WWW GTalk   Вверх
Lazin
Дата 2.4.2009, 19:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3820
Регистрация: 11.12.2006
Где: paranoid oil empi re

Репутация: 4
Всего: 154



Цитата(Void @  2.4.2009,  15:44 Найти цитируемый пост)
А код на Haskell комментировать? Хотя бы в духе «это хуже чем Perl» smile 

дык оно-же не работает с моим ghc, нужно скачивать 6.10
Цитата(Void @  2.4.2009,  15:44 Найти цитируемый пост)
Задачку никто больше решать не будет? Erlang бы взял кто-нибудь, хоть с консолью, хоть с gs

будет smile 
PM MAIL Skype GTalk   Вверх
Lazin
Дата 3.4.2009, 14:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3820
Регистрация: 11.12.2006
Где: paranoid oil empi re

Репутация: 4
Всего: 154



написал то-же самое на с++, но без GUI, все выводится в консоль, всего есть 3 потока, один для хулигана, один для дворника и основной поток, первые два потока отправляют основному потоку свое состояние через очередь(порт завершения), основной поток выступает в роли брокера, и вычисляет общее состояние
Код

// forvingrad.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <windows.h>
#include <cassert>
#include <boost/thread.hpp>
#include <boost/bind.hpp>
#include <boost/function.hpp>
#include <boost/system/error_code.hpp>
#include <boost/system/system_error.hpp>
#include <set>
#include <string>
#include <conio.h>


class UserInterface
{
public:
    void Write(const std::set<int> packets, int hooligan, int sweep)
    {
        std::string field(60, ' ');
        for (std::set<int>::const_iterator i = packets.begin(); i != packets.end(); ++i)
        {
            assert(*i > -1);
            assert(*i < 60);
            field[*i] = 'P';
        }
        if (sweep != -1)
        {
            field[sweep] = 'O';
            field[sweep + 1] = 'O';
            field[sweep + 2] = 'O';
        }
        if (hooligan != -1)
            field[hooligan] = 'X';

        std::cout << field << std::endl;
    }
};

class Workfield
{
    enum 
    {
        position_status,
        drop_bag_status,
        sweep_status,
        hide_status
    };
    struct PositionEvent : OVERLAPPED
    {
        int index;
        PositionEvent(int ix) 
            : index(ix)
        {
            ZeroMemory(this, sizeof(OVERLAPPED));
            Offset = position_status; 
        }
    };
    struct DropBagEvent : OVERLAPPED
    {
        DropBagEvent()
        {
            ZeroMemory(this, sizeof(OVERLAPPED));
            Offset = drop_bag_status;
        }
    };
    struct SweepEvent : OVERLAPPED
    {
        int first;
        SweepEvent(int ix)
            : first(ix)
        {
            ZeroMemory(this, sizeof(OVERLAPPED));
            Offset = sweep_status;
        }
    };
    struct HideEvent : OVERLAPPED
    {
        HideEvent()
        {
            ZeroMemory(this, sizeof(OVERLAPPED));
            Offset = hide_status;
        }
    };
    HANDLE cport_;
    volatile LONG done_;
public:
    enum
    {
        hooligan_wins = 1,
        janitor_wins = 2
    };
    Workfield()
        : cport_(CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, NULL, 0))
        , done_(0)
    {
        if (!cport_)
        {
            DWORD last_error = ::GetLastError(); 
            boost::system::system_error e(boost::system::error_code(last_error, boost::system::get_system_category()), __FUNCTION__": CreateCompletionPort failed"); 
            boost::throw_exception(e); 
        }
    }
    int IsDone()
    {
        return InterlockedExchangeAdd(&done_, 0);
    }
    void Done(int who_wins)
    {
        InterlockedExchange(&done_, who_wins);
    }
    void StepTo(int ix)
    {
        PositionEvent* pos_evt = new PositionEvent(ix);
        if(!PostQueuedCompletionStatus(cport_, 0, 0, pos_evt))
        {
            DWORD last_error = ::GetLastError(); 
            boost::system::system_error e(boost::system::error_code(last_error, boost::system::get_system_category()), __FUNCTION__": PostQueuedCompletionStatus failed"); 
            boost::throw_exception(e); 
        }
    }
    void Hide()
    {
        HideEvent* hide_evt = new HideEvent();
        if(!PostQueuedCompletionStatus(cport_, 0, 0, hide_evt))
        {
            DWORD last_error = ::GetLastError(); 
            boost::system::system_error e(boost::system::error_code(last_error, boost::system::get_system_category()), __FUNCTION__": PostQueuedCompletionStatus failed"); 
            boost::throw_exception(e); 
        }
    }
    void Sweep(int first)
    {
        SweepEvent* sweep_evt = new SweepEvent(first);
        if(!PostQueuedCompletionStatus(cport_, 0, 0, sweep_evt))
        {
            DWORD last_error = ::GetLastError(); 
            boost::system::system_error e(boost::system::error_code(last_error, boost::system::get_system_category()), __FUNCTION__": PostQueuedCompletionStatus failed"); 
            boost::throw_exception(e); 
        }
    }
    void DropBag()
    {
        DropBagEvent* drop_evt = new DropBagEvent();
        if(!PostQueuedCompletionStatus(cport_, 0, 0, drop_evt))
        {
            DWORD last_error = ::GetLastError(); 
            boost::system::system_error e(boost::system::error_code(last_error, boost::system::get_system_category()), __FUNCTION__": PostQueuedCompletionStatus failed"); 
            boost::throw_exception(e); 
        }
    }

    void ProcessQueue(UserInterface& ui)
    {
        OVERLAPPED *event;
        ULONG_PTR ck;
        DWORD bytes_tr;
        std::set<int> packets;
        int hooligan_state = -1;
        int janitor_state = -1;
        while(!IsDone())
        {
            BOOL res = GetQueuedCompletionStatus(cport_, &bytes_tr, &ck, &event, INFINITE);
            if(!res)
            {
                DWORD last_error = ::GetLastError(); 
                boost::system::system_error e(boost::system::error_code(last_error, boost::system::get_system_category()), __FUNCTION__": GetQueuedCompletionStatus failed"); 
                boost::throw_exception(e); 
            }
            if(event)
            {
                int type = event->Offset;
                switch(type)
                {
                    case position_status:
                        {
                            PositionEvent* pos_evt = (PositionEvent*)event;
                            hooligan_state = pos_evt->index;
                            delete pos_evt;
                        }
                        break;
                    case drop_bag_status:
                        {
                            DropBagEvent* drop_evt = (DropBagEvent*)event;
                            packets.insert(hooligan_state);
                            delete drop_evt;
                        }
                        break;
                    case sweep_status:
                        {
                            SweepEvent* sweep_evt = (SweepEvent*)event;
                            janitor_state = sweep_evt->first;
                            delete sweep_evt;
                            for(int i = 0; i < 3; ++i)
                                packets.erase(i + janitor_state);
                            if(hooligan_state != -1)
                            {
                                int dp = hooligan_state - janitor_state;
                                if (dp < 3 && dp >= 0)
                                {
                                    //caught
                                    Done(janitor_wins);
                                }
                            }
                        }
                        break;
                    case hide_status:
                        {
                            HideEvent* hide_evt = (HideEvent*)event;
                            hooligan_state = -1;
                            delete hide_evt;
                        }
                        break;
                    default:
                        throw std::runtime_error(__FUNCTION__"Queue error");
                };
                ui.Write(packets, hooligan_state, janitor_state);
            }
        }
    }
};

class Hooligan
{
    Workfield& field_;

public:
    void ThreadProc()
    {
        for(int i = 0; i < 22; ++i)
        {
            int pos = rand() % 60;
            field_.StepTo(pos);
            field_.DropBag();
            Sleep(60);
            field_.Hide();
            Sleep(300);
            if(field_.IsDone()) return;
        }
        field_.Done(Workfield::hooligan_wins);
    }
    Hooligan(Workfield& f) 
        : field_(f)
    {
    }
};

class Janitor
{
    Workfield& field_;

public:
    void ThreadProc()
    {
        int i = 0;
        for (;"Ever";)
        {
            for(; i < 20; ++i)
            {
                Sleep(400);
                field_.Sweep(i*3);
                if (field_.IsDone()) return;
            }
            for(;i;--i)
            {
                Sleep(400);
                field_.Sweep(i*3 - 3);
                if (field_.IsDone()) return;
            }
        }
    }
    Janitor(Workfield& f)
        : field_(f)
    {
    }
};



int main(int argc, char* argv[])
{
    srand((unsigned int)time(NULL));
    UserInterface ui;
    Workfield field;
    Hooligan h(field);
    Janitor j(field);
    boost::thread hthread( boost::bind(&Hooligan::ThreadProc, &h) );
    boost::thread jthread( boost::bind(&Janitor::ThreadProc, &j) );
    field.ProcessQueue(ui);
    hthread.join();
    jthread.join();
    if(field.IsDone() == Workfield::hooligan_wins)
        std::cout << "Hooligan Wins" << std::endl;
    else
        std::cout << "Janitor Wins" << std::endl;
    system("pause");
    return 0;
}



300 строк, почти в 2 раза больше чем у Void

Добавлено через 3 минуты и 55 секунд
ps
winsows only
PM MAIL Skype GTalk   Вверх
GoldFinch
Дата 6.4.2009, 11:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата



****


Профиль
Группа: Завсегдатай
Сообщений: 2141
Регистрация: 30.11.2008

Репутация: нет
Всего: 26



не очень понятна фраза "Дворник бегает от края до края поля за раз сметая 3 бумажки (очищая 3 соседние ячейки) в течении 400мс."
PM MAIL ICQ   Вверх
Страницы: (5) Все 1 2 [3] 4 5 
Ответ в темуСоздание новой темы Создание опроса
Правила ведения Религиозных войн
Smartov
1. Уважайте собеседника
2. Собеседник != враг
3. Старайтесь воздерживаться от тем вида "Windows Rulez" или "Linux Rulez"

С уважением, Smartov.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Религиозные войны | Следующая тема »


 




[ Время генерации скрипта: 0.1411 ]   [ Использовано запросов: 24 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.