Форум программистов, компьютерный форум, киберфорум
Haskell
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.94/16: Рейтинг темы: голосов - 16, средняя оценка - 4.94
5 / 5 / 3
Регистрация: 06.06.2013
Сообщений: 22
1

Сортировка сдвигами

08.08.2014, 13:12. Показов 3315. Ответов 41
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
есть задача про сортировку сдвигами, собственно вот она: http://codeforces.ru/problemset/problem/454/B есть ли другие решения этой задачи, возможно более правильные?
Вот моё решение:
Haskell
1
2
3
4
5
6
7
8
9
10
11
movingSort :: [Int] -> Int
movingSort [] = 0
movingSort x 
    | isSorted x = 0
    | isSorted $ tail x = length x - 1
    | otherwise = -1
 
isSorted :: [Int] -> Bool
isSorted [] = True
isSorted (x:[]) = True
isSorted (x:xs) = x <= head xs && isSorted xs
P.S. проверял в ghci, поэтому функцию main с вводом-выводом не писал
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
08.08.2014, 13:12
Ответы с готовыми решениями:

Деление сдвигами
как делить сдвигами число на 96? четность проверять побитовыми командами. это нужно сделать в...

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

Найти наибольшее число, получаемое сдвигами
2) К цифрам натурального числа a&gt;9 применяется операция циклический сдвиг влево. Из числа 1730382...

Операции со сдвигами, выделение битовых полей
Помогите, пожалуйста подкорректировать задачу во встроенном в TURBO PASCAL ассемблере: В исходном...

41
650 / 260 / 16
Регистрация: 02.03.2014
Сообщений: 587
08.08.2014, 14:39 2
Не всегда работает... чуть по позже напишу своё решение.
Haskell
1
2
3
4
> movingSort [4,1,2,3]
3
> movingSort [4,5,1,2,3]
-1
Добавлено через 45 минут
мой вариант...
Haskell
1
2
3
4
5
6
7
8
import Control.Monad.Fix
 
movingSort :: [Int] -> Int
movingSort a = fix (\f a n k m -> let n' = if k == 0 then 0 else n+1 in case a of
  x:xs| x >= m    -> f xs n' k x
      | k == 0    -> f xs 0  1 x
      | otherwise -> -1
  _               -> n' ) a 0 0 (head a)
Добавлено через 11 минут
Извиняюсь, не учёл один момент...
Haskell
1
2
3
4
5
6
7
8
import Control.Monad.Fix
 
movingSort :: [Int] -> Int
movingSort a = fix (\f a n k m s -> let n' = if k then 0 else n+1 in case a of
  x:xs| x >= m    -> f xs n' k     x s
      | k         -> f xs 0  False x s
      | otherwise -> -1
  _               -> if m <= s || k then n' else -1 ) a 0 True (head a) (head a)
2
Модератор
Эксперт функциональных языков программированияЭксперт Python
36601 / 20330 / 4220
Регистрация: 12.02.2012
Сообщений: 33,640
Записей в блоге: 13
08.08.2014, 16:41 3
Без монад:

Haskell
1
2
3
4
5
6
7
8
9
10
11
12
13
14
isSorted :: [Int] -> Bool
isSorted [x] = True
isSorted (x:xs) = (x < head xs) && isSorted xs
 
mvSort :: [Int] -> Int -> Int
mvSort x n | (n > lx) = (-1)
           | isSorted x = n
           | otherwise = mvSort ((last x) : (take (lx-1) x)) (n+1)
            where lx=length x
 
Main> mvSort [4,1,2,3] 0
3
Main> mvSort [4,5,1,2,3] 0
3
0
Модератор
5047 / 3276 / 526
Регистрация: 01.06.2013
Сообщений: 6,806
Записей в блоге: 9
08.08.2014, 18:19 4
Осмелюсь заметить, что Araneo не использовал монады. Можно подключить
Haskell
1
import Data.Function
где fix, собственно и определена, вместо Control.Monad.Fix.
0
Модератор
Эксперт функциональных языков программированияЭксперт Python
36601 / 20330 / 4220
Регистрация: 12.02.2012
Сообщений: 33,640
Записей в блоге: 13
08.08.2014, 18:23 5
KolodeznyDiver, хотя монады не использовались, код, на мой взгляд, тяжелый... Зачем усложнять простую задачу?
0
650 / 260 / 16
Регистрация: 02.03.2014
Сообщений: 587
08.08.2014, 18:31 6
Catstail, а как его можно "облегчить"? Ну избавлюсь я скажем от fix, но ведь по сути она лишь замаскированная рекурсия. А дальше что?
0
Модератор
Эксперт функциональных языков программированияЭксперт Python
36601 / 20330 / 4220
Регистрация: 12.02.2012
Сообщений: 33,640
Записей в блоге: 13
08.08.2014, 18:42 7
Цитата Сообщение от Araneo Посмотреть сообщение
а как его можно "облегчить"?
- в данном случае "лобовая рекурсия" смотрится проще.

Добавлено через 8 минут
Рискну предположить, что нижеприведенный код (хотя он и более громоздкий), тем не менее понимается значительно проще:

Haskell
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
isSorted :: [Int] -> Bool
isSorted [x] = True
isSorted (x:xs) = (x < head xs) && isSorted xs
 
rotate :: [a] -> [a]
rotate [] = []
rotate x = (last x) : (take (l-1) x)
           where l=length x
           
mvSort' :: [Int] -> Int -> Int
mvSort' x n | (n>l) = (-1)
            | isSorted x = n
            | otherwise = mvSort' (rotate x) (n+1)
             where l=length x           
 
mvSort :: [Int] -> Int
mvSort x = mvSort' x 0
0
Модератор
5047 / 3276 / 526
Регистрация: 01.06.2013
Сообщений: 6,806
Записей в блоге: 9
08.08.2014, 19:33 8
Решение с одним проходом и "лобовой рекурсией"
Haskell
1
2
3
4
5
6
7
8
9
10
11
shiftSort:: [Int] -> Int
shiftSort [] = 0
shiftSort [_] = 0
shiftSort (frst':xs) = let (_,_,res)= loop (frst':xs) 0 (negate 1) in res  
  where loop [last'] ix pos = ([], ix, if pos < 0 then 0 
                                       else if pos>0 && frst' < last' 
                                            then -1 else pos)
        loop (l:r:xs') ix pos = if l > r then 
                                    if pos >=0 then ([],0,-1) 
                                    else loop (r:xs') (ix+1) (1 + length xs') 
                                else loop (r:xs') (ix+1) pos
0
Модератор
Эксперт функциональных языков программированияЭксперт Python
36601 / 20330 / 4220
Регистрация: 12.02.2012
Сообщений: 33,640
Записей в блоге: 13
08.08.2014, 20:00 9
KolodeznyDiver, да, это возможно, но код столь же тяжёл и вязок. Мой на три строки длиннее, а для понимания значительно проще.

Вот мой код с комментариями, понятными всем. Ведь правда просто?

Haskell
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
isSorted :: [Int] -> Bool  -- проверка, отсортирован ли список
isSorted [x] = True  --   список из одного элемента всегда отсортирован
isSorted (x:xs) = (x < head xs) && isSorted xs -- а иначе список отсортирован, если его первый эл-т меньше 
                                                              -- второго и отсортирован хвост 
 
rotate :: [a] -> [a] -- вращение
rotate [] = []  -- вращение пустого дает пустой
rotate x = (last x) : (take (l-1) x) -- иначе берем последний эл-т и присоединяем его первым к списку без последнего
           where l=length x -- l - длина списка
           
mvSort' :: [Int] -> Int -> Int  -- рекурсивная программа с накопительным параметром
mvSort' x n | (n>l) = (-1) -- если число вращений превысило длину - отсортировать не удастся
            | isSorted x = n -- если отсортировали - вернем количество
            | otherwise = mvSort' (rotate x) (n+1) -- иначе рекурсивный вызов с увеличением накоп. параметра
             where l=length x           
 
mvSort :: [Int] -> Int -- парадная функция (только для того, чтобы не задавать 0 при вызове
mvSort x = mvSort' x 0
А Ваш код, без 0.5, пардон, и не поймешь
0
Модератор
5047 / 3276 / 526
Регистрация: 01.06.2013
Сообщений: 6,806
Записей в блоге: 9
08.08.2014, 20:50 10
По мне, так мой код лёгок как цветок сакуры и прекрасен как женщина, охотящаяся за леопардом!
Haskell
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
shiftSort:: [Int] -> Int -- ф-ия находит, сколько раз нужно выполнить циклический сдвиг
shiftSort [] = 0         -- для упорядочивания списка
shiftSort [_] = 0        -- для этого проходим по списку сравнивая соседнии элементы
                         -- там где неубывание нарушится, там и место проворота
shiftSort (frst':xs) = -- первый элемент нам понадобится для сравнения с последним 
    snd $ loop -- рекурсивная ф-ия с двумя аргументами, возвращает кортеж из них же 
                              (frst':xs) -- не просмотренная ещё часть списка 
                              (negate 1) -- позиция проворота или -1, если ещё не нашли  
  where loop [last'] pos = -- Добрались до последнего элемента 
         ([], if pos < 0 then 0 -- если прокручивать список не нужно, то и нет смысла 
                                -- сравнивать первый элемент с последним - они не будут рядом 
              else if pos>0 && frst' < last'  then -1 -- одна позиция для проворота уже была. две быть не может 
              else pos) -- успех
        loop (l:r:xs') pos = if l > r then -- неубывание нарушено  
                                    if pos >=0 then ([],-1) -- это уже не первое. Отсортировать не получится.
                                    else loop (r:xs') (1 + length xs') -- помечаем место откуда крутить список
                             else loop (r:xs') pos -- список пока неубыват, переходим к следующему
Заодно оказалось, что индекс я совершенно напрасно протаскивал по рекурсии
Заметно сократилось.
0
Модератор
Эксперт функциональных языков программированияЭксперт Python
36601 / 20330 / 4220
Регистрация: 12.02.2012
Сообщений: 33,640
Записей в блоге: 13
08.08.2014, 22:07 11
Цитата Сообщение от KolodeznyDiver Посмотреть сообщение
Заметно сократилось.
- не сказал бы... И 4 зацепленных if не сильно его красят. Даже комментированный код тяжёл.
0
650 / 260 / 16
Регистрация: 02.03.2014
Сообщений: 587
08.08.2014, 22:13 12
Взял я код KolodeznyDiver'a и решил его проэволюционировать...
Haskell
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
{-# Language MultiWayIf,LambdaCase#-}
import Data.Function
 
shiftSort:: [Int] -> Int 
shiftSort [] = 0         
shiftSort [_] = 0
shiftSort (frst':xs) = snd $ loop (frst':xs) (negate 1) 
  where loop [last'] pos = ([], if pos < 0 then 0 
              else if pos>0 && frst' < last'  then -1
              else pos)
        loop (l:r:xs') pos = if l > r then 
                                    if pos >=0 then ([],-1)
                                    else loop (r:xs') (1 + length xs')
                             else loop (r:xs') pos
 
shiftSort:: [Int] -> Int
shiftSort [] = 0         
shiftSort [_] = 0        
shiftSort (frst':xs) = snd $ loop (frst':xs) (-1)  
  where 
    loop [last'] pos = ([],
      if  | pos < 0                  -> 0
          | pos > 0 && frst' < last' -> -1
          | otherwise                -> pos)
    loop (l:r:xs') pos 
      | l <= r    = loop (r:xs') pos
      | pos >=0   = ([],-1) 
      | otherwise = loop (r:xs') (1 + length xs')
 
shiftSort:: [Int] -> Int
shiftSort x = case x of
  f:xs -> let loop x pos = case x of
                l:r:xs'| l <= r           -> loop (r:xs') pos
                       | pos >= 0         -> ([],-1) 
                       | otherwise        -> loop (r:xs') (1 + length xs')
                [l]    | pos < 0          -> ([],0  )
                       | pos > 0 && f < l -> ([],-1 )
                       | otherwise        -> ([],pos) 
          in  snd $ loop (f:xs) (-1)
  _    -> 0 
 
shiftSort:: [Int] -> Int
shiftSort = \case
  f:xs -> snd $ fix (\loop x pos -> case x of
      l:r:xs'| l <= r           -> loop (r:xs') pos
             | pos >= 0         -> ([],-1) 
             | otherwise        -> loop (r:xs') (1 + length xs')
      [l]    | pos < 0          -> ([],0  )
             | pos > 0 && f < l -> ([],-1 )
             | otherwise        -> ([],pos) 
    ) (f:xs) (-1)
  _    -> 0
2
Модератор
Эксперт функциональных языков программированияЭксперт Python
36601 / 20330 / 4220
Регистрация: 12.02.2012
Сообщений: 33,640
Записей в блоге: 13
08.08.2014, 22:14 13
Araneo, "Верной дорогой идете, товарищи!"
0
Модератор
5047 / 3276 / 526
Регистрация: 01.06.2013
Сообщений: 6,806
Записей в блоге: 9
09.08.2014, 00:28 14
Haskell
1
{-# Language MultiWayIf,LambdaCase#-}
Да, до этого я ещё не добрался. Компактно выглядит.

Добавлено через 2 часа 1 минуту
Ладно, осваиваем тайные практики Araneo
Haskell
1
2
3
4
5
6
7
8
9
10
11
{-# Language MultiWayIf,LambdaCase, ParallelListComp  #-}
 
sSort:: [Int] -> Int
sSort = \case
  f:xs -> case [z|(x,y,z)<-[(x,y,(length xs)-z)|x<-(init $ f:xs) |y<-xs|z<-[0,1..]],x>y] of
            []  -> 0
            [0] -> 0
            [i] -> if | f < (last xs) -> -1
                      | True -> i
            _   -> -1     
  _    -> 0
0
650 / 260 / 16
Регистрация: 02.03.2014
Сообщений: 587
09.08.2014, 01:37 15
Эээ, а зачем мульти иф если там вполне срабатывает и обычный?
в любом случае вы дали мне идею...
Haskell
1
2
3
4
5
6
sSort:: [Int] -> Int
sSort x = case [ n | (n,a) <- zip [1..] $ zipWith (-) x (last x:init x) , a < 0] of
  []  -> 0
  [1] -> 0
  [n] -> length x - n + 1
  _   -> -1
1
Модератор
5047 / 3276 / 526
Регистрация: 01.06.2013
Сообщений: 6,806
Записей в блоге: 9
09.08.2014, 02:20 16
Я же написал, для освоения тайных практик - нестандартных расширений GHC.
Haskell
1
2
3
4
5
6
7
8
{-# Language ParallelListComp  #-}
 
sSort:: [Int] -> Int
sSort x   = case [ n | (n,a) <- [(n,a<b)|n<-[1..]|a<-x|b<-(last x:init x)], a] of
  []  -> 0
  [1] -> 0
  [n] -> length x - n + 1
  _   -> -1
Добавлено через 13 минут
вроде бы, можно ещё одно действие убрать
Haskell
1
2
3
4
5
6
7
8
{-# Language ParallelListComp  #-}
 
sSort:: [Int] -> Int
sSort x   = case [ n | (n,a) <- [(n,a<b)|n<-[0..]|a<-x|b<-(last x:init x)], a] of
  []  -> 0
  [0] -> 0
  [n] -> length x - n 
  _   -> -1
1
Модератор
Эксперт функциональных языков программированияЭксперт Python
36601 / 20330 / 4220
Регистрация: 12.02.2012
Сообщений: 33,640
Записей в блоге: 13
09.08.2014, 10:25 17
Последние коды по крайней мере компактны...
0
Модератор
5047 / 3276 / 526
Регистрация: 01.06.2013
Сообщений: 6,806
Записей в блоге: 9
09.08.2014, 10:41 18
А в чём цель соревнования (верная дорога)? Я использовал один проход по списку из соображений скорости. Последние варианты (с list comprehension) в этом плане как раз не оптимальны.
0
Модератор
Эксперт функциональных языков программированияЭксперт Python
36601 / 20330 / 4220
Регистрация: 12.02.2012
Сообщений: 33,640
Записей в блоге: 13
09.08.2014, 11:01 19
Цель двояка: производительность vs наглядность. Лично для меня второе всегда более важно.
0
Модератор
5047 / 3276 / 526
Регистрация: 01.06.2013
Сообщений: 6,806
Записей в блоге: 9
09.08.2014, 11:15 20
А какую роль для Вас играет соответствие стандарту (Language MultiWayIf,LambdaCase, ParallelListComp)?
И ещё, я заметил, вы "не любите" монады. В такой простой задаче их не так, вот, и придумаешь как применить. Но бывают случаи что с ними и код короче получится.
0
09.08.2014, 11:15
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
09.08.2014, 11:15
Помогаю со студенческими работами здесь

Зашифруйте строку текста случайными сдвигами символов
Здравствуйте! Помогите,вот такое задание: Зашифруйте строку текста случайными сдвигами символов с...

Перевод отрицательных float в двоичную систему с побитовыми сдвигами
Добрый день! Мой код выдает ошибку при вводе отрицательных малых вещественных чисел -0,1; -0,01;...

Найти наибольшее число, получаемое левыми сдвигами цифр натурального числа
Задача из форума Turbo Pascal: https://www.cyberforum.ru/turbo-pascal/thread974839.html Найти...

Выведите количество подстрок строки a, являющихся циклическими сдвигами строки b
Строки (Время: 1 сек. Память: 16 Мб Сложность: 34%) Циклическим сдвигом строки s называется...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru