Реализации алгоритмов/Алгоритм Нарайаны: различия между версиями

Перейти к навигации Перейти к поиску
Добавлена реализация на Go; мелкие исправления в других разделах
м (Исправление мелкой ошибки)
(Добавлена реализация на Go; мелкие исправления в других разделах)
 
=Реализации=
В нижеприведённых реализациях <code>sequence</code> — последовательность из <code>count</code> элементов, в которой производятся перестановки (как правило — массив из count элементов), <code>compare(x, y)</code> — функция, которая должна возвращать значение «истина» если <code>x < y</code>, и «ложь» иначе (если исходный порядок элементов последовательности неубывающий; для невозрастающего исходного порядка условие меняется на <code>x > y</code>).
 
Если не оговорено другое, то функция поиска очередной перестановки возвращает значение «истина», если перестановка найдена, либо «ложь», если следующей перестановки не существует (перебор закончен).
 
==[[w:Бейсик|BASIC]]==
===[[w:Visual_Basic_.NET|VBVisual Basic .NET]]===
<source lang="vb">
' Narayana.vb
 
Public Module Narayana
''' <summary>
''' Функция, задающая отношение порядка для значений типа T: < либо >
''' </summary>
Public Delegate Function Predicate2 (Of T) (ByVal value_0 As T, ByVal value_1 As T) As Boolean
 
''' <summary>
''' Поиск очередной перестановки
''' </summary>
Public Function NextPermutation (Of T) (ByVal sequence As T(), ByVal compare As Predicate2(Of T)) As Boolean
' Этап № 1
Dim i As Integer = sequence.Length
Do
Do
If i < 2 Then Return False ' Перебор закончен
i -= 1
Loop Until compare(sequence(i - 1), sequence(i))
' Этап № 2
Dim j As Integer = sequence.Length
Do While i < j And Not compare(sequence(i - 1), sequence(j - 1))
j -= 1
Loop
_SwapItems(sequence, i - 1, j - 1)
' Этап № 3
j = sequence.Length
Do While i < j - 1
j -= 1
_SwapItems(sequence, i, j)
i += 1
Loop
Return True
End Function
 
''' <summary>
''' Обмен значениями двух элементов последовательности
''' </summary>
Private Sub _SwapItems (Of T) (ByVal sequence As T(), ByVal index_0 As Integer, ByVal index_1 As Integer)
Dim item As T = sequence(index_0)
sequence(index_0) = sequence(index_1)
sequence(index_1) = item
End Sub
End Module
</source>
<source lang="vb">
' NarayanaTest.vb
 
Module NarayanaTest
''' <summary>
''' Возвращает True, если value_0 меньше value_1, иначе — False
''' </summary>
Private Function Less (Of T As IComparable) (ByVal value_0 As T, ByVal value_1 As T) As Boolean
Return value_0.CompareTo(value_1) < 0
End Function
 
''' <summary>
''' Возвращает True, если value_0 больше value_1, иначе — False
''' </summary>
Private Function Greater (Of T As IComparable) (ByVal value_0 As T, ByVal value_1 As T) As Boolean
Return value_0.CompareTo(value_1) > 0
End Function
 
''' <summary>
''' Инициализация последовательности
''' </summary>
Private Sub InitSequence (ByVal sequence As Integer())
' Заполнение последовательности значениями 1, 2, 3…
For i As Integer = sequence.Length To 1 Step -1
sequence(i - 1) = i
Next
End Sub
 
''' <summary>
''' Вывод содержимого последовательности
''' </summary>
Private Sub OutputSequence (Of T) (ByVal sequence As T())
Console.Write("["C)
If sequence IsNot Nothing And sequence.Length > 0 Then
Console.Write(sequence(0))
For i As Integer = 1 To sequence.GetUpperBound(0)
Console.Write(", ")
Console.Write(sequence(i))
Next
End If
Console.WriteLine("]"C)
End Sub
 
''' <summary>
''' Основная программа
''' </summary>
Public Sub Main (ByVal args As String())
Dim count As Integer = Integer.Parse(Console.ReadLine())
Dim sequence(count - 1) As Integer
InitSequence(sequence) ' Формирование исходной последовательности
Console.WriteLine("Неубывающая последовательность и её перестановки:")
Do
Do
OutputSequence(sequence)
Loop While Narayana.NextPermutation(sequence, AddressOf Less) ' x < y — критерий сравнения для неубывающей последовательности
' x < y — критерий сравнения для неубывающей последовательности
Console.WriteLine("Невозрастающая последовательность и её перестановки:")
Console.WriteLine("Невозрастающая последовательность и её перестановки:")
Do
Do
OutputSequence(sequence)
OutputSequence(sequence)
Loop While Narayana.NextPermutation(sequence, AddressOf Greater) ' x > y — критерий сравнения для невозрастающей последовательности
Loop While Narayana.NextPermutation(sequence, AddressOf Greater)
End Sub
' x > y — критерий сравнения для невозрастающей последовательности
End Sub
End Module
</source>
<source lang="cpp">
/* narayana.h */
 
#ifndef _NARAYANA_H_
#define _NARAYANA_H_
 
typedef int T; /* Вместо int можно подставить любой тип */
 
/* Обмен значениями двух элементов последовательности */
static void _swapItems (T *sequence, unsigned index_1index_0, unsigned index_2index_1);
 
/* Поиск очередной перестановки */
unsigned nextPermutation (T *sequence, unsigned const count, int (*compare)(T const, T const));
 
#endif
 
 
/* narayana.c */
 
#include "narayana.h"
 
 
/* Обмен значениями двух элементов последовательности */
static void _swapItems (T *sequence, unsigned index_1index_0, unsigned index_2index_1) {
T item = sequence[index_1index_0];
sequence[index_1index_0] = sequence[index_2index_1];
sequence[index_2index_1] = item;
}
 
/* Поиск очередной перестановки */
unsigned nextPermutation (T *sequence, unsigned count, int (*compare)(T const, T const)) {
unsigned i = count, j;
/* Этап № 1 */
do {
if (i < 2)
return 0; /* Перебор закончен */
--i;
} while (!(*compare)(sequence[i - 1], sequence[i]));
/* Этап № 2 */
for (j = count; j > i && !(*compare)(sequence[i - 1], sequence[--j]); );
_swapItems(sequence, i - 1, j);
/* Этап № 3 */
for (j = count; i < --j; )
_swapItems(sequence, i++, j);
return 1;
}
</source>
<source lang="cpp">
/* narayana_test.c */
 
#include <malloc.h>
#include <stdio.h>
 
#include "narayana.h"
 
 
/* Возвращает 1, если value_0 меньше value_1, иначе — 0 */
int less (T const value_0, T const value_1) {
return value_0 < value_1;
}
 
/* Возвращает 1, если value_0 больше value_1, иначе — 0 */
int greater (T const value_0, T const value_1) {
return value_0 > value_1;
}
 
/* Инициализация последовательности */
void initSequence (T *sequence, unsigned count) {
/* Заполнение последовательности значениями 1, 2, 3… */
unsigned i;
for (i = count; i; --i)
sequence[i - 1] = i;
}
 
/* Вывод содержимого последовательности */
void outputSequence (T const *sequence, unsigned count) {
putchar('[');
if (count) { /* Если последовательность не пуста */
unsigned i;
printf("%d", sequence[0]);
for (i = 1; i < count; ++i)
printf(", %d", sequence[i]);
}
}
putchar(']');
putchar('\n');
}
 
/* Основная программа */
int main () {
unsigned count;
scanf("%d", &count);
T *sequence = (T*)malloc(count * sizeof(T));
initSequence(sequence, count); /* Формирование исходной последовательности */
printf("Неубывающая последовательность и её перестановки:\n");
do {
outputSequence(sequence, count);
} while (nextPermutation(sequence, count, &less)); /* x < y — критерий сравнения для неубывающей последовательности */
/* x < y — критерий сравнения для неубывающей последовательности */
printf("Невозрастающая последовательность и её перестановки:\n");
printf("Невозрастающая последовательность и её перестановки:\n");
do {
do {
outputSequence(sequence, count);
outputSequence(sequence, count);
} while (nextPermutation(sequence, count, &greater)); /* x > y — критерий сравнения для невозрастающей последовательности */
} while free(nextPermutation(sequence, count, &greater));
/* x > y — критерий сравнения для невозрастающей последовательности */
return 0;
free(sequence);
return 0;
}
</source>
<source lang="cpp">
// narayana.hpp
 
#ifndef _NARAYANA_HPP_
#define _NARAYANA_HPP_
 
namespace Narayana {
// Обмен значениями двух элементов последовательности
template < typename T >
static void _swap (T &variable_0, T &variable_1) {
T variable = variable_0;
variable_0 = variable_1;
variable_1 = variable;
}
}
 
// Поиск очередной перестановки
template < typename Iterator, typename T >
bool nextPermutation (Iterator const begin, Iterator const end, bool (*compare)(T const, T const)) {
if (begin == end) // Если последовательность не содержит элементов
return false; // Нечего перебирать
// Этап № 1
Iterator i = end - 1, j = end;
do {
if (i == begin)
return false; // Перебор закончен
} while (!(*compare)(*--i, *--j));
// Этап № 2
j = end;
while (j != i && !(*compare)(*i, *--j));
_swap(*i, *j);
// Этап № 3
++i;
j = end;
for ( ; (i != j) && (i != --j); ++i)
_swap(*i, *j);
return true;
}
}
}
</source>
 
#endif
</source>
Пример использования:
<source lang="cpp">
// narayana_test.cpp
 
#include <iostream>
 
#include "narayana.hpp"
 
 
// Возвращает true, если value_0 меньше value_1, иначе — false
template < typename T >
bool less (T value_0, T value_1) {
return value_0 < value_1;
}
 
// Возвращает true, если value_0 больше value_1, иначе — false
template < typename T >
bool greater (T value_0, T value_1) {
return value_0 > value_1;
}
 
// Инициализация последовательности
template < typename Iterator >
void initSequence (Iterator const begin, Iterator const end) {
// Заполнение последовательности значениями 1, 2, 3…
int i = 0;
for (Iterator current = begin; current != end; ++current)
*current = ++i;
}
 
// Вывод содержимого последовательности
template < typename Iterator >
void outputSequence (Iterator const begin, Iterator const end) {
std::cout << '[';
if (begin != end) {
std::cout << *begin;
for (Iterator current = begin; ++current != end; )
((std::cout << ',') << ' ') << *current;
}
}
(std::cout << ']') << '\n';
}
 
// Основная программа
int main () {
int main() {
unsigned count;
std::cin >> unsigned count;
std::cin >> count;
int *sequence = new int[count], *sequence_end = sequence + count;
int *sequence = new int[count], *sequence_end = sequence + count;
initSequence(sequence, sequence_end); // Формирование исходной последовательности
initSequence(sequence, sequence_end); // Формирование исходной последовательности
std::cout << "Неубывающая последовательность и её перестановки:\n";
std::cout << "Неубывающая последовательность и её перестановки:\n";
do {
do {
outputSequence(sequence, sequence_end);
outputSequence(sequence, sequence_end);
} while (Narayana::nextPermutation(sequence, sequence_end, &less<int>)); // x < y — критерий сравнения для неубывающей последовательности
} while (Narayana::nextPermutation(sequence, sequence_end, &less<int>));
std::cout << "Невозрастающая последовательность и её перестановки:\n";
// x < y — критерий сравнения для неубывающей последовательности
do {
std::cout << "Невозрастающая последовательность и её перестановки:\n";
outputSequence(sequence, sequence_end);
do {
} while (Narayana::nextPermutation(sequence, sequence_end, &greater<int>)); // x > y — критерий сравнения для невозрастающей последовательности
outputSequence(sequence, sequence_end);
delete [] sequence;
} while (Narayana::nextPermutation(sequence, sequence_end, &greater<int>));
return 0;
// x > y — критерий сравнения для невозрастающей последовательности
delete [] sequence;
return 0;
}
</source>
<source lang="csharp">
// Narayana.cs
 
public static class Narayana {
/// <summary>
/// Функция, задающая отношение порядка для значений типа T: < либо >
/// </summary>
public delegate bool Predicate2 <T> (T value_0, T value_1);
/// <summary>
/// Поиск очередной перестановки
/// </summary>
public static bool NextPermutation <T> (T[] sequence, Predicate2<T> compare)
{
{
// Этап № 1
var i = sequence.Length;
do
do
{
{
if (i < 2)
return false; // Перебор закончен
--i;
} while (!compare(sequence[i - 1], sequence[i]));
// Этап № 2
var j = sequence.Length;
while (i < j && !compare(sequence[i - 1], sequence[--j]));
_SwapItems(sequence, i - 1, j);
// Этап № 3
j = sequence.Length;
while (i < --j)
_SwapItems(sequence, i++, j);
return true;
}
}
 
/// <summary>
/// Обмен значениями двух элементов последовательности
/// </summary>
private static void _SwapItems <T> (T[] sequence, int index_0, int index_1)
{
{
var item = sequence[index_0];
sequence[index_0] = sequence[index_1];
sequence[index_1] = item;
}
}
}
</source>
<source lang="csharp">
// NarayanaTest.cs
 
public static class NarayanaTest
{
/// <summary>
/// Возвращает true, если value_0 меньше value_1, иначе — false
/// </summary>
private static bool Less <T>(T value_0, T value_1) where T: System.IComparable
{
{
return value_0.CompareTo(value_1) < 0;
}
}
 
/// <summary>
/// Возвращает true, если value_0 больше value_1, иначе — false
/// </summary>
private static bool Greater <T>(T value_0, T value_1) where T: System.IComparable
{
{
return value_0.CompareTo(value_1) > 0;
}
}
 
/// <summary>
/// Инициализация последовательности
/// </summary>
private static void InitSequence (int[] sequence)
{
{
// Заполнение последовательности значениями 1, 2, 3…
for (var i = sequence.Length; i > 0; --i)
sequence[i - 1] = i;
}
}
 
/// <summary>
/// Вывод содержимого последовательности
/// </summary>
private static void OutputSequence <T>(T[] sequence)
{
{
System.Console.Write('[');
if (!(sequence == null) && (sequence.Length > 0))
{
{
System.Console.Write(sequence[0]);
for (var i = 1; i < sequence.Length; ++i)
{
{
System.Console.Write(", ");
System.Console.Write(sequence[i]);
}
}
}
}
System.Console.WriteLine(']');
}
}
 
/// <summary>
/// Основная программа
/// </summary>
public static void Main()
{
var count = int.Parse(System.Console.ReadLine());
var sequence = new int[count];
InitSequence(sequence); // Формирование исходной последовательности
System.Console.WriteLine("Неубывающая последовательность и её перестановки:");
do
{
OutputSequence(sequence);
} while (Narayana.NextPermutation(sequence, Less));
// x < y — критерий сравнения для неубывающей последовательности
System.Console.WriteLine("Невозрастающая последовательность и её перестановки:");
do
{
OutputSequence(sequence);
} while (Narayana.NextPermutation(sequence, Greater));
// x > y — критерий сравнения для невозрастающей последовательности
}
}
</source>
 
==[[w:Go|Go]]==
<source lang="go">
// narayana/narayana.go
 
package narayana
 
type T = int // Вместо int можно подставить любой тип
 
// Поиск очередной перестановки
func NextPermutation(sequence []T, compare func (T, T) bool) bool {
count := len(sequence)
i := count
// Этап № 1
for {
if i < 2 {
return false // Перебор закончен
}
i--
if compare(sequence[i - 1], sequence[i]) {
break
}
}
// Этап № 2
j := count
for j > i && !compare(sequence[i - 1], sequence[j - 1]) {
j--
}
sequence[i - 1], sequence[j - 1] = sequence[j - 1], sequence[i - 1]
// Этап № 3
j = count
for i < j - 1 {
j--
sequence[i], sequence[j] = sequence[j], sequence[i]
i++
}
return true
}
</source>
Пример использования:
<source lang="go">
// narayana_test.go
 
package main
 
import (
"fmt",
"narayana"
)
 
// Возвращает true, если value_0 меньше value_1, иначе — false
func less(value_0, value_1 narayana.T) bool {
return value_0 < value_1
}
 
// Возвращает true, если value_0 больше value_1, иначе — false
func greater(value_0, value_1 narayana.T) bool {
return value_0 > value_1
}
 
// Инициализация последовательности
func initSequence(sequence []narayana.T) {
// Заполнение последовательности значениями 1, 2, 3…
value := narayana.T(len(sequence))
for i := len(sequence); i > 0; {
i--
sequence[i] = value
value--
}
}
 
func main() {
/// <summary>
var count uint
/// Основная программа
fmt.Scan(&count)
/// </summary>
var sequence := make([]narayana.T, count)
public static void Main ()
initSequence(sequence) // Формирование исходной последовательности
{
fmt.Println("Неубывающая последовательность и её перестановки:")
var count = int.Parse(System.Console.ReadLine());
for {
var sequence = new int[count];
fmt.Println(sequence)
InitSequence(sequence); // Формирование исходной последовательности
if !narayana.NextPermutation(sequence, less) {
System.Console.WriteLine("Неубывающая последовательность и её перестановки:");
break
do
}
{
// x < y — критерий сравнения для неубывающей последовательности
OutputSequence(sequence);
}
} while (Narayana.NextPermutation(sequence, Less)); // x < y — критерий сравнения для неубывающей последовательности
System.Console fmt.WriteLinePrintln("Невозрастающая последовательность и её перестановки:");
for {
do
fmt.Println(sequence)
{
if OutputSequence!narayana.NextPermutation(sequence, greater); {
break
} while (Narayana.NextPermutation(sequence, Greater)); // x > y — критерий сравнения для невозрастающей последовательности
}
}
// x > y — критерий сравнения для невозрастающей последовательности
}
sequence = nil
}
</source>
<source lang="java">
// Narayana.java
 
abstract class Narayana {
// Функция, задающая отношение порядка для значений типа T: < либо >
@FunctionalInterface
interface Predicate2 <T extends Comparable> {
boolean compare (final T value_0, final T value_1);
}
}
 
// Поиск очередной перестановки
public static final <T extends Comparable> boolean nextPermutation (T[] sequence, Predicate2 comparator) {
// Этап № 1
int i = sequence.length;
do {
if (i < 2)
return false; // Перебор закончен
--i;
} while (!comparator.compare(sequence[i - 1], sequence[i]));
// Этап № 2
int j = sequence.length;
while (i < j && !comparator.compare(sequence[i - 1], sequence[--j]));
_swapItems(sequence, i - 1, j);
// Этап № 3
j = sequence.length;
while (i < --j)
_swapItems(sequence, i++, j);
return true;
}
}
 
// Обмен значениями двух элементов последовательности
private static final <T> void _swapItems (T[] sequence, int index_0, int index_1) {
T temp = sequence[index_0];
sequence[index_0] = sequence[index_1];
sequence[index_1] = temp;
}
}
}
</source>
<source lang="java">
// NarayanaTest.java
 
import java.util.Arrays;
import java.util.Scanner;
 
 
public class NarayanaTest {
// Возвращает true, если value_0 меньше value_1, иначе — false
static final <T extends Comparable> boolean less (final T value_0, final T value_1) {
return value_0.compareTo(value_1) < 0;
}
}
 
// Возвращает true, если value_0 больше value_1, иначе — false
static final <T extends Comparable> boolean greater (final T value_0, final T value_1) {
return value_0.compareTo(value_1) > 0;
}
}
 
// Инициализация последовательности
static final void initSequence (Integer[] sequence) {
// Заполнение последовательности значениями 1, 2, 3…
for (int value = sequence.length; value > 0; --value)
sequence[value - 1] = value;
}
}
 
// Основная программа
public static void main (String[] args) {
Scanner scanner = new Scanner(System.in);
int count = scanner.nextInt();
Integer[] sequence = new Integer[count];
initSequence(sequence); // Формирование исходной последовательности
System.out.println("Неубывающая последовательность и её перестановки:");
do {
System.out.println(Arrays.deepToString(sequence));
} while (Narayana.nextPermutation(sequence, NarayanaTest::less)); // x < y — критерий сравнения для неубывающей последовательности
// x < y — критерий сравнения для неубывающей последовательности
System.out.println("Невозрастающая последовательность и её перестановки:");
System.out.println("Невозрастающая последовательность и её перестановки:");
do {
do {
System.out.println(Arrays.deepToString(sequence));
System.out.println(Arrays.deepToString(sequence));
} while (Narayana.nextPermutation(sequence, NarayanaTest::greater)); // x > y — критерий сравнения для невозрастающей последовательности
} while (Narayana.nextPermutation(sequence, NarayanaTest::greater));
}
// x > y — критерий сравнения для невозрастающей последовательности
}
}
</source>
<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): Boolean;
 
IMPLEMENTATION
 
{ Поиск очередной перестановки }
function NextPermutation (var sequence: array of T; Compare: TPredicate2): Boolean;
var count, i, j: Word;
{ Обмен значениями двух элементов последовательности }
procedure SwapItems (index_1, index_2: Word);
var item: T;
begin
item := sequence[index_1];
sequence[index_1] := sequence[index_2];
sequence[index_2] := item
end;
begin
count := Length(sequence);
{ Этап № 1 }
i := count;
repeat
if i < 2 then
begin
NextPermutation := false;
Exit
Exit
{ Перебор закончен }
end;
i := i - 1
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;
SwapItems(i - 1, j - 1);
{ Этап № 3 }
j := count;
while i < j - 1 do
begin
j := j - 1;
SwapItems(i, j);
i := i + 1
end;
NextPermutation := true
end;
 
END.
<source lang="pascal">
{ NarayanaTest.pas }
uses Narayana;
 
PROGRAM NarayanaTest;
 
USES Narayana;
var sequence: array of T;
 
count: Word;
VAR sequence: array of T;
count: Word;
 
{ Возвращает true, если value_0 меньше value_1, иначе — false }
function Less (const value_0, value_1: T): Boolean;
begin
Less := value_0 < value_1
end;
 
{ Возвращает true, если value_0 больше value_1, иначе — false }
function Greater (const value_0, value_1: T): Boolean;
begin
Greater := value_0 > value_1
end;
 
{ Инициализация последовательности }
procedure InitSequence (var sequence: array of T);
var i: Word;
begin
{ Заполнение последовательности значениями 1, 2, 3… }
for i := Length(sequence) downTo 1 do
sequence[i - 1] := i;
end;
 
{ Вывод содержимого последовательности }
procedure OutputSequence (const sequence: array of T);
var i, count: Word;
begin
Write('[');
count := Length(sequence);
if count > 0 then { Если последовательность не пуста }
begin
Write(sequence[0]);
for i := 1 to count - 1 do
Write(', ', sequence[i])
end;
WriteLn(']')
end;
 
{ Основная программа }
BEGIN
ReadLn(count);
SetLength(sequence, count);
InitSequence(sequence); { Формирование исходной последовательности }
WriteLn('Неубывающая последовательность и её перестановки:');
repeat
OutputSequence(sequence)
until not NextPermutation(sequence, @Less); { x < y — критерий сравнения для неубывающей последовательности }
{ x < y — критерий сравнения для неубывающей последовательности }
WriteLn('Невозрастающая последовательность и её перестановки:');
WriteLn('Невозрастающая последовательность и её перестановки:');
repeat
repeat
OutputSequence(sequence)
OutputSequence(sequence)
until not NextPermutation(sequence, @Greater) { x > y — критерий сравнения для невозрастающей последовательности }
until not NextPermutation(sequence, @Greater)
{ x > y — критерий сравнения для невозрастающей последовательности }
END.
</source>
===Вариант № 1===
<source lang="PHP">
// narayana.php
function nextPermutation ($sequence, $count) {
$out = $sequence;
// Этап № 1
$k = $count - 2;
while ($k >= 0 && $out[$k] >= $out[$k + 1]) {
--$k;
}
if (-1 == $k) {
return false; // Перебор закончен
}
// Этап № 2
$t = $count - 1;
while ($t >= 0 && $t >= $k + 1 && $out[$k] >= $out[$t]) {
--$t;
}
$tmp = $out[$k];
$out[$k] = $out[$t];
$out[$t] = $tmp;
// Этап № 3
for ($i = $k + 1; $i < ceil(($count + $k) / 2); ++$i) {
$t = $count + $k - $i;
$tmp = $out[$i];
$out[$i] = $out[$t];
$out[$t] = $tmp;
}
 
function nextPermutation($sequence, $count) {
return $out;
$out = $sequence;
// Этап № 1
$k = $count - 2;
while ($k >= 0 && $out[$k] >= $out[$k + 1]) {
--$k;
}
if (-1 == $k) {
return false; // Перебор закончен
}
// Этап № 2
$t = $count - 1;
while ($t >= 0 && $t >= $k + 1 && $out[$k] >= $out[$t]) {
--$t;
}
$tmp = $out[$k];
$out[$k] = $out[$t];
$out[$t] = $tmp;
// Этап № 3
for ($i = $k + 1; $i < ceil(($count + $k) / 2); ++$i) {
$t = $count + $k - $i;
$tmp = $out[$i];
$out[$i] = $out[$t];
$out[$t] = $tmp;
}
 
return $out;
}
</source>
Вариант с выводом справа налево:
<source lang="PHP">
// narayana.php
 
$b = "123456789";
$a = strrev($b);
while ($a !=$b) {
$i = 0;
 
while($a[$i] > $a[$i - 1]) {
$i++;
}
}
$j = 0;
while($a[$j] < $a[$i]) {
++$j;
}
}
 
$c = $a[$j];
$a[$j] = $a[$i];
$a[$i] = $c;
 
$x = strrev(substr($a, 0, $i));
$y = substr($a, $i);
 
print $a = $x . $y;
print ‘<br/>’;
}
</source>
<source lang="python">
# narayana.py
 
"""Поиск очередной перестановки"""
def next_permutation (sequence, compare) -> bool:
count = len(sequence)
i = count
# Этап № 1
while True:
if i < 2:
return False # Перебор закончен
i -= 1;
if compare(sequence[i - 1], sequence[i]):
break
# Этап № 2
j = count
while j > i and not compare(sequence[i - 1], sequence[j - 1]):
j -= 1
sequence[i - 1], sequence[j - 1] = sequence[j - 1], sequence[i - 1]
# Этап № 3
j = count
while i < j - 1:
j -= 1
sequence[i], sequence[j] = sequence[j], sequence[i]
i += 1
return True
</source>
Пример использования на Python 3.x (в Python 2.x надо убрать скобки в операторах <code>print</code>):
<source lang="python">
# narayana_test.py
import narayana
 
import narayana
 
"""Возвращает True, если value_0 меньше value_1, иначе — False"""
def less (value_0, value_1):
return value_0 < value_1
 
"""Возвращает True, если value_0 больше value_1, иначе — False"""
def greater (value_0, value_1):
return value_0 > value_1
 
# Основная программа
sequence = list(range(1, count + 1)) # Заполнение последовательности значениями 1, 2, 3…
print("Неубывающая последовательность и её перестановки:")
permutation_found = True
while True:
while permutation_found:
print(sequence)
print(sequence)
if not narayana.next_permutation(sequence, less): # x < y — критерий сравнения для неубывающей последовательности
permutation_found = narayana.next_permutation(sequence, less)
break
# x < y — критерий сравнения для неубывающей последовательности
print("Невозрастающая последовательность и её перестановки:")
permutation_found = True
while True:
while permutation_found:
print(sequence)
print(sequence)
if not narayana.next_permutation(sequence, greater): # x > y — критерий сравнения для невозрастающей последовательности
permutation_found = narayana.next_permutation(sequence, greater)
break
# x > y — критерий сравнения для невозрастающей последовательности
</source>
 
<source lang="rust">
// narayana.rs
 
// Поиск очередной перестановки
fn next_permutation <T: Copy + PartialOrd> (sequence: &mut[T], compare: fn (T, T) -> bool) -> bool {
let count = sequence.len();
let mut i = count;
// Этап № 1
while {
if i < 2 {
return false; // Перебор закончен
}
}
i -= 1;
!compare(sequence[i - 1], sequence[i])
} { } // Пустое тело цикла (имитация цикла с постусловием)
// Этап № 2
let mut j = count;
while j > i && !compare(sequence[i - 1], sequence[j - 1]) {
j -= 1;
}
}
sequence.swap(i - 1, j - 1);
// Этап № 3
j = count;
while i < j - 1 {
j -= 1;
sequence.swap(i, j);
i += 1;
}
}
true
}
</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 [i32]) {
// Заполнение последовательности значениями 1, 2, 3…
let mut i = sequence.len();
let mut value = i as i32;
while i > 0 {
i -= 1;
sequence[i] = value;
value -= 1;
}
}
}
 
// Функция для ввода данных
fn read_var <Type: std::str::FromStr> (var: &mut Type) -> bool {
let mut input_text = String::new();
std::io::stdin()
.read_line(&mut input_text)
.expect("Не удалось прочитать из стандартного ввода.");
match input_text.trim().parse::<Type>() {
Ok(value) => { *var = value; true },
Err(..) => { false }
}
}
}
 
// Основная программа
fn main () {
let mut count = 0usize;
read_var(&mut count);
let mut sequence = vec![0i32; count];
init_sequence(&mut sequence); // Формирование исходной последовательности
println!("Неубывающая последовательность и её перестановки:");
while {
println!("{:?}", sequence);
narayana::next_permutation(&mut sequence, less::<i32>) // x < y — критерий сравнения для неубывающей последовательности
// x < y — критерий сравнения для неубывающей последовательности
} { }
} { }
println!("Невозрастающая последовательность и её перестановки:");
println!("Невозрастающая последовательность и её перестановки:");
while {
while {
println!("{:?}", sequence);
println!("{:?}", sequence);
narayana::next_permutation(&mut sequence, greater::<i32>) // x > y — критерий сравнения для невозрастающей последовательности
narayana::next_permutation(&mut sequence, greater::<i32>)
} { }
// x > y — критерий сравнения для невозрастающей последовательности
} { }
}
</source>
74

правки

Навигация