Реализации алгоритмов/Алгоритм Нарайаны: различия между версиями
Содержимое удалено Содержимое добавлено
Переработана реализация на C; добавлен пример использования |
Добавлена реализация и пример использования на Rust; мелкие правки для остальных языков |
||
Строка 21:
</source>
'''C++:''' Все функции, кроме <code>main</code>, следует предварить строкой:
<source lang="cpp">
template < typename T >
Строка 28:
Собственно реализация:
<source lang="cpp">
/* narayana.h */
/* Обмен значениями двух элементов последовательности */
static void
/* Поиск очередной перестановки */
unsigned nextPermutation (T *sequence, unsigned const count, int (*compare)(T const, T const));
/* narayana.c или narayana.cpp */
/* Обмен значениями двух элементов последовательности */
static void _swapItems (T *sequence, unsigned index_1, unsigned index_2) {
T _ = sequence[index_1]; /* _ — временная переменная */
sequence[index_1] = sequence[index_2];
sequence[index_2] = _;
}
/* Поиск очередной перестановки */
unsigned i = count, j;
/* Этап № 1 */
Строка 47 ⟶ 54 :
for (j = count; j > i && !(*compare)(sequence[i - 1], sequence[j - 1]); --j);
--i;
/* Этап № 3 */
for (j = i + 1; j <= (count + i) >> 1; ++j) /* >> 1 — более быстрый вариант / 2 */
return j;
}
Строка 56 ⟶ 63 :
Пример использования:
<source lang="cpp">
/* narayana_test.c или narayana_test.cpp */
#include <malloc.h>
#include <stdio.h>
#include "narayana.h"
Строка 83 ⟶ 93 :
printf("%d", sequence[0]);
for (unsigned i = 1; i < count; ++i)
printf(", %d", sequence[i]);
}
putchar(']');
Строка 111 ⟶ 121 :
==[[w:Паскаль (язык программирования)|Pascal]]==
<source lang="pascal">
{ Narayana.pas }
UNIT Narayana;
INTERFACE
type T = Integer; { Вместо Integer можно использовать любой тип }
{ Функция, задающая отношение порядка для значений типа T: < либо > }
TPredicate2 = function (const value_0, value_1: T): Boolean;
{ Поиск очередной перестановки }
function NextPermutation (var sequence: array of T; Compare: TPredicate2): Word;
IMPLEMENTATION
{ Поиск очередной перестановки }
function NextPermutation (var sequence: array of T; Compare: TPredicate2): Word;
{ Обмен значениями двух элементов последовательности }
procedure SwapItems (index_1, index_2: Word);
var _: T; { _ — временная переменная }
begin
sequence[index_2] := _
end;
{ Этап №
repeat
NextPermutation := 0;
end;
until Compare(sequence[i - 1], sequence[i]);
{ Этап № 2 }
j := count;
while (j > i) and not Compare(sequence[i - 1], sequence[j - 1]) do
j := j - 1;
i := i - 1;
SwapItems(i, j - 1);
{ Этап № 3 }
for j := i + 1 to (count + i) shr 1 do { shr 1 — более быстрый вариант div 2 }
SwapItems(j, count + i - j);
NextPermutation := j
end;
END.
</source>
Пример использования:
<source lang="pascal">
{ NarayanaTest.pas }
uses Narayana;
var sequence: array [0..3] of T; { Последовательность. Границы индексов могут быть и другими }
Строка 186 ⟶ 212 :
Write(sequence[0]);
for i := 1 to count - 1 do
Write(', ', sequence[i])
end;
WriteLn(']')
Строка 267 ⟶ 293 :
</source>
==[[w:Rust|Rust]]==
<source lang="rust">
// narayana.rs
// Поиск очередной перестановки
fn next_permutation <T: Copy + PartialOrd> (sequence: &mut[T], compare: fn (T, T) -> bool) -> usize {
let count = sequence.len();
let mut i = count;
// Этап № 1
loop {
if i < 2 {
return 0;
}
i -= 1;
if compare(sequence[i - 1], sequence[i]) {
break;
}
}
// Этап № 2
let mut j = count;
while j > i && !compare(sequence[i - 1], sequence[j - 1]) {
j -= 1;
}
i -= 1;
sequence.swap(i, j - 1);
// Этап № 3
j = i + 1;
while j <= (count + i) >> 1 { // >> 1 — более быстрый вариант / 2
sequence.swap(j, count + i - j);
j += 1;
}
j
}
</source>
Пример использования:
<source lang="rust">
// narayana_test.rs
// Возвращает true, если value_0 меньше value_1, иначе — false
fn less <T: PartialOrd> (value_0: T, value_1: T) -> bool {
value_0 < value_1
}
// Возвращает true, если value_0 больше value_1, иначе — false
fn greater <T: PartialOrd> (value_0: T, value_1: T) -> bool {
value_0 > value_1
}
// Инициализация последовательности
fn init_sequence (sequence: &mut [usize]) {
// Заполнение последовательности значениями 1, 2, 3…
let mut i = sequence.len();
while i > 0 {
sequence[i - 1] = i;
i -= 1;
}
}
// Основная программа
fn main () {
let mut sequence = [0usize; 4]; // Длина последовательности - 4. Может быть и любой другой
init_sequence(&mut sequence); // Формирование исходной последовательности
println!("Неубывающая последовательность и её перестановки:");
while {
println!("{:?}", sequence);
narayana::next_permutation(&mut sequence, less::<usize>) > 0 // x < y — критерий сравнения для неубывающей последовательности
} { }
println!("");
println!("Невозрастающая последовательность и её перестановки:");
while {
println!("{:?}", sequence);
narayana::next_permutation(&mut sequence, greater::<usize>) > 0 // x > y — критерий сравнения для невозрастающей последовательности
} { }
}
</source>
{{BookCat}}
|