Отсортируйте массив по нескольким условиям
Вход: массив целых чисел(-2^31 <= n < 2^31)
Выход: массив чисел отсортированный в следующем порядке:
- неотрицательные четные
- отрицательные нечетные
- неотрицательные нечетные
- отрицательные четные
Если несколько чисел попадёт в одну группу, то отсортировать их по возрастанию
Это code golf, но ни один ответ не будет принят т.к. цель вопрос в том чтобы собрать короткое решение на каждом языке
пожалуйста используйте сайт https://tio.run/ чтобы можно было легко запускать ваш код
Вход:
[-5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5]
Выход:
[0, 2, 4, -5, -3, -1, 1, 3, 5, -4, -2]
Таблица лидеров:
execute("ru.stackoverflow.com", "1236112");
.cssload-container,.cssload-cube{width:97px;height:97px;transform-style:preserve-3d}.cssload-container,.cssload-cube,.cssload-half1,.cssload-half2{transform-style:preserve-3d}.cssload-container{position:relative;margin:23px 84px;perspective:292px}.cssload-cube{animation:cube 11.5s forwards infinite;transform-origin:center 49px}.cssload-half1,.cssload-s1{top:0;transform-origin:50% 100%}.cssload-half1{height:39px;position:absolute;animation:half-fold 11.5s forwards infinite}.cssload-side{width:19px;height:19px;background:#ddd;position:absolute}.cssload-s1{left:39px;animation:s1ani 11.5s forwards infinite}.cssload-s2,.cssload-s3,.cssload-s4{left:39px;transform-origin:50% 0}.cssload-s2{top:19px;animation:s2ani 11.5s forwards infinite}.cssload-s3{top:39px;animation:s3ani 11.5s forwards infinite}.cssload-s4{top:58px;animation:s4ani 11.5s forwards infinite}.cssload-s5{left:19px;top:19px;transform-origin:100% 50%;animation:s5ani 11.5s forwards infinite}.cssload-s6{left:58px;top:39px;transform-origin:0 50%;animation:s6ani 11.5s forwards infinite}@keyframes cube{0%,30%{transform:rotateX(0)}40%{transform:rotateX(45deg) rotateY(0) rotate(45deg)}60%{transform:rotateX(60deg) rotateY(0) rotate(45deg)}65%,70%{transform:rotateX(60deg) rotate(45deg) rotate(180deg)}75%,80%{transform:rotateX(60deg) rotate(45deg) rotate(1turn)}90%{transform:rotateX(0) rotate(0) rotate(0)}}@keyframes s1ani{0%{opacity:1;transform:translateY(0);background:#ddd}40%{transform:rotateX(0);background:#ddd}50%{transform:rotateX(-90deg);background:#ddd}90%{transform:rotateX(-90deg)}}@keyframes s2ani{0%{opacity:0;transform:rotateX(-179deg)}10%{opacity:1;transform:rotateX(0)}40%{background:#ddd}45%,80%{background:#b4b4b4}65%{opacity:1;background:#b4b4b4}90%{opacity:1}to{opacity:0}}@keyframes s3ani{0%,10%{opacity:0;transform:rotateX(-179deg)}20%,90%{opacity:1;transform:rotateX(0)}40%{background:#ddd}45%{background:#969696}to{opacity:0}}@keyframes s4ani{0%,20%{opacity:0;transform:rotateX(-179deg)}10%,to{opacity:0}30%{opacity:1;transform:rotateX(0)}40%{transform:rotateX(0);background:#ddd}50%{transform:rotateX(90deg);background:#b4b4b4}80%{background:#b4b4b4}90%{opacity:1;transform:rotateX(90deg)}}@keyframes s5ani{0%,10%{opacity:0;transform:rotateY(-179deg)}20%{opacity:1;background:#ddd;transform:rotateY(0)}40%{transform:rotateY(0)}50%{transform:rotateY(90deg)}55%{background:#ddd}60%{background:#c8c8c8}90%{transform:rotateY(90deg);opacity:1}to{opacity:0}}@keyframes s6ani{0%,20%{opacity:0;transform:rotateY(179deg)}30%{opacity:1;transform:rotateY(0)}40%{transform:rotateY(0)}50%{transform:rotateY(-90deg);background:#ddd}60%,80%{background:#c8c8c8}90%{opacity:1;transform:rotateY(-90deg)}to{opacity:0}}@keyframes half-fold{0%,50%{transform:rotateX(0)}60%,90%{transform:rotateX(-90deg)}}
<script src="https://mayorovp.github.io/codegolf/table-8c505e68f1349e4c69e7.js"></script>
<div class=cssload-container><div class=cssload-cube><div class=cssload-half1><div class="cssload-side cssload-s1"></div><div class="cssload-side cssload-s2"></div><div class="cssload-side cssload-s5"></div></div><div class=cssload-half2><div class="cssload-side cssload-s3"></div><div class="cssload-side cssload-s4"></div><div class="cssload-side cssload-s6"></div></div></div></div>
Ответы (9 шт):
Python 3, 55
lambda a:sorted(a,key=lambda x:('1342'[(x<0)*2+x%2],x))
Ну вот Python, хотя какое-то шаманство получилось, наверняка можно формулу пересчёта весов для сортировки критериев вывести, но у меня пока не получилось:
a = [-5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5]
print(sorted(a, key=lambda x: ([[1, 3], [4, 2]][x < 0][x % 2], x)))
Вывод:
[0, 2, 4, -5, -3, -1, 1, 3, 5, -4, -2]
Краткое (или не очень) разъяснение:
sorted- стандартная функция для сортировки коллекций вPython, в данном случае использован вариант с заданием нестандартного ключа сортировки с помощью именованного параметраkey=lambda x:- способ описания анонимных функций вPython- Сортировать в питоне можно по составному ключу, для этого в качестве ключа сортировки указывается кортеж, в данном случае использован кортеж
(хитрое условие по числу, само число) - Для выборки нужного веса сортировки используется индексация в двумерном списке (можно воспринимать как матрицу)
[[значения],[значения]][строка][столбец] - Кроме того, при выполнении индексации тут используется тот факт, что булевы значения могут использоваться как целые числа:
True- это1, аFalse- это0
perl, 56
Не люблю поддерживать миф, что perl самый непонятный язык, но ...
$,=", ";
@X = (-5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5);
print sort{($a<0^$a&1).($a<0)cmp($b<0^$b&1).($b<0)||$a<=>$b}@X;
Функция sort сортирует указанный в самом конце массив (@X) с помощью блока кода перед ним. В этом блоке доступны предопределенные переменные $a и $b содержащие сравниваемые значения. задача блока вычислить какое из них больше.
sort {
Выражение1 cmp Выражение2 # Лексикографическое сравнение двух выражений
|| # ИЛИ (если они равны)
$a <=> $b # Числовое сравнение самих переменных
} @X;
Теперь само выражение для оценки веса переменной:
( $a<0 ^ $a & 1 ) # XOR между значениями признака отрицательного числа и его четности (младшего бита)
# он равен 0 для неотрицательных четных и отрицательных нечетных, иначе 1
. # Конкатенация строк
( $a<0 ) # признак отрицательности
# в perl сравнение дает пустую строку если условие ложно или 1 если истинно
На выходе данное выражение дает строки: "0", "01", "1", "11". В лексикографическом порядке эти строки дают нужный нам порядок условий.
Пример на tio.run
PHP, 122 bytes
$x=[[],[],[],[]];
foreach($d as $v)$x[$v>=0?($v%2?2:0):($v%2?1:3)][]=$v;
foreach($x as $v)sort($v);
$r=array_merge(...$x);
нормальная версия кода:
$d = [-5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5];
$x = [[],[],[],[]];
foreach($d as $v){
$i = $v >= 0 ? ( $v%2 ? 2 : 0) : ( $v%2 ? 1 : 3 );
$x[$i][] = $v;
}
foreach($x as $v) sort($v);
$r = array_merge(...$x);
JavaScript (V8), 50
(Способ №3)
v=>v.sort((a,b,t=x=>x*2&2|x<0||4)=>t(b)-t(a)||a-b)
let v = [-5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5];
v.sort((a,b,t=x=>x*2&2|x<0||4)=>t(b)-t(a)||a-b);
console.log(v.join());
JavaScript (V8), 52 bytes (Способ №2)
v=>v.sort((a,b)=>(b*2&2|b<0||4)-(a*2&2|a<0||4)||a-b)
let v = [-5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5];
v.sort((a,b)=>(b*2&2|b<0||4)-(a*2&2|a<0||4)||a-b);
console.log(v.join());
JavaScript (V8), 62 bytes (Способ №1)
v=>v.sort((a,b)=>"0231"[(a<0)*2|a&1]-"0231"[(b<0)*2|b&1]||a-b)
let v = [-5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5];
v.sort((a,b)=>"0231"[(a<0)*2|a&1]-"0231"[(b<0)*2|b&1]||a-b);
console.log(v.join());
Pyth, 18
o(+*2x%N2J>ZNJ N)Q
Перевод:
o #1 Сортировка значения из стека(#9) по ключу (с lambda N:)
( #2 Ключ будет кортежем (из 2 элементов)
+ #3 Сложение 2 элементов из стека (#4 + #7)
*2 #4 стек(#5) * 2
x %N2 #5 стек(#6) XOR N % 2
J>ZN #6 кладем в стек (0 > N) и запоминаем его же в переменной J
J #7 Только что сохраненная (в стр#6) J идет в стек для сложения (стр#3)
N #8 Второй элемент кортежа, текущий элемент массива
)Q #9 Конец кортежа и помещение входного массива в стек
Алгоритм примерно тот же, что применен в perl варианте, считаем первый ключ сортировки по формуле:
J = (N < 0)
((N % 2) ^ J) * 2 + J
Haskell, 34 bytes
f=sortOn(\x->(odd x/=(x<0),x<0,x))
Сортировка по трем характеристикам
- Число исключительно отрицательное или нечетное? (сначала четные неотрицательные и нечетные отрицательные)
- Отрицательное ли число? (сначала неотрицательные)
- Значение числа
Требуется импорт Data.List
Можно использовать без имени функции, тогда -2 байта
main = print (sortOn(\x->(odd x/=(x<0),x<0,x)) [-5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5])
С/C++
За краткостью не гнался.
avp@avp-desktop:~/avp/hashcode$ wc srt.c
30 145 827 srt.c
avp@avp-desktop:~/avp/hashcode$
Код проверил на https://tio.run/# в gcc и clang как C и C++
#include <stdio.h>
#include <stdlib.h>
int cmpf (const void *p, const void *q) {
static int sort_key[4] = {
0, // неотрицательные четные 'b00
2, // неотрицательные нечетные 'b01
3, // отрицательные четные 'b10
1 // отрицательные нечетные 'b11
};
int v1 = *(int *)p, v2 = *(int *)q;
int type1 = ((v1 < 0) << 1) | (v1 & 1),
type2 = ((v2 < 0) << 1) | (v2 & 1);
return type1 != type2 ? sort_key[type1] - sort_key[type2] :
v1 < v2 ? -1 : v1 == v2 ? 0 : 1;
}
int main ()
{
int a[] = {-5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5};
size_t n = sizeof(a) / sizeof(a[0]);
qsort(a, n, sizeof(a[0]), cmpf);
for (int i = 0; i < n; i++)
printf("%d%s", a[i], i == n - 1? "\n" : ", ");
return 0;
}
Идея компаратора состоит в том, что мы формируем 2-х разрядное число, состоящее из знака и бита четности, которое используем как индекс в массиве ключа сортировки.
C#, 47 bytes
Минус 10 байт, если не требовать на выходе массив.
Хоть C# и не предназначен для гольфа, вот вам версия на C# (48 байт):
a=a.OrderBy(v=>((v<0?1:0)^v&1,v<0,v)).ToArray();
Проверка тут.
Идея та же, что и в ответе @Mike: сортировка по sign bit ^ parity bit, потом по sign bit, потом по значению.
Более изящное решение с заменой v<0,v на (uint)v, к сожалению, проигрывает по размеру.
Выиграл ещё байт, заменив приведение к интам на приведение к bool:
a=a.OrderBy(v=>(v<0^(v&1)==1,v<0,v)).ToArray();
Проверка тут.
Powershell 7.1
(@(-5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5) | Sort-Object -Property `
@{Expression={$_ -ge 0 -and $_ % 2 -eq 0}; Descending=$true}, `
@{Expression={$_ -lt 0 -and $_ % 2 -ne 0}; Descending=$true}, `
@{Expression={$_ -gt 0 -and $_ % 2 -ne 0}; Descending=$true}, `
@{Expression={$_ -le 0 -and $_ % 2 -eq 0}; Descending=$true}) -join ", "
подумал получше
(((-5..5).Where({$_ -lt 0}, 5)).foreach{$_.Where({$_ % 2}, 5)})[3,0,2,1]