Ir para o conteúdo principal

Arranjos Simples: Ordenar sem Usar Tudo

·2327 palavras·11 minutos·
Autor
Francisco Bustamante
Um químico trabalhando com Ciência de Dados e Programação em Python.
Tabela de conteúdos
A Arte de Contar - Este artigo faz parte de uma série de artigos.
Parte 4: Esse Artigo

Em uma corrida com 10 participantes, de quantas formas o pódio (1º, 2º, 3º lugar) pode ser preenchido? Aqui usamos apenas 3 dos 10 atletas — e a ordem importa (1º ≠ 2º). Isso é um arranjo simples.

Por que arranjos simples?
#

Selecionar e ordenar um subconjunto de elementos — sem necessariamente usar todos — é uma operação central em computação e matemática:

  • Segurança: senhas de comprimento \(r\) sem repetição, tiradas de um alfabeto de \(n\) símbolos, totalizam \(A(n, r)\) possibilidades — o arranjo dimensiona o espaço que um atacante de força bruta precisa percorrer.
  • Placas e identificadores únicos: sistemas alfanuméricos sem repetição de caracteres usam o arranjo para calcular quantos identificadores distintos podem ser emitidos — exatamente o exemplo resolvido a seguir.
  • Escalonamento: a ordenação de \(r\) processos entre \(n\) disponíveis numa fila de prioridade corresponde a \(A(n, r)\) sequências possíveis.
  • Rotas e grafos: o número de caminhos simples de comprimento \(r\) num grafo completo de \(n\) vértices é \(A(n, r)\) — base de algoritmos de busca em espaço de estados.
  • Rankings: pódios, listas de recomendação ordenada e resultados de torneios são arranjos — importa quem foi escolhido e em qual posição.

Da permutação ao arranjo
#

A permutação simples, abordada no artigo anterior, ordena todos os \(n\) elementos. O arranjo simples relaxa essa exigência: ordenamos apenas \(r < n\) deles. O diagrama abaixo situa o arranjo na família dos agrupamentos:

flowchart TD
    A["n elementos distintos"] --> B{"Usar todos?"}
    B -->|"Sim"| C["Permutação Simples
P_n = n!"] B -->|"Não — escolher r < n"| D{"Ordem importa?"} D -->|"Sim"| E["Arranjo Simples
A(n,r) = n!/(n-r)!"] D -->|"Não"| F["Combinação Simples
(próximo artigo)"]

Arranjo Simples
#

Definição

Um arranjo simples de \(n\) elementos distintos tomados \(r\) a \(r\) é uma seleção ordenada de \(r\) elementos distintos escolhidos dentre \(n\) (\(r \leq n\)):

$$A(n, r) = \frac{n!}{(n-r)!} = n \cdot (n-1) \cdots (n-r+1)$$

Casos notáveis:

  • \(A(n, n) = n!\) — o mesmo que a permutação simples \(P_n\)
  • \(A(n, 1) = n\)

Voltando ao exemplo da abertura: o pódio de uma corrida com 10 atletas tem \(A(10, 3) = 10 \times 9 \times 8 = 720\) configurações distintas.

Exemplos Resolvidos
#

Prédio com 8 andares — par (entrada, saída) distinto
#

Enunciado: Um prédio tem 8 andares. Uma pessoa entra no elevador em um andar e sai em outro diferente. De quantas maneiras distintas pode ocorrer esse par ordenado (entrada, saída)?

Solução: Queremos escolher 2 andares distintos entre 8, onde a ordem importa: entrar no 3º e sair no 7º é diferente de entrar no 7º e sair no 3º. Trata-se de um arranjo simples de 8 elementos tomados 2 a 2.

Preenchemos as duas posições sequencialmente:

Posição Opções disponíveis Justificativa
Andar de entrada 8 qualquer dos 8 andares
Andar de saída 7 qualquer exceto o de entrada
$$A(8, 2) = \frac{8!}{(8-2)!} = \frac{8!}{6!} = 8 \times 7 = \mathbf{56}$$
SQL: CROSS JOIN com filtro gera pares ordenados distintos

No artigo sobre Princípios Aditivo e Multiplicativo, vimos que CROSS JOIN — operação de SQL (Structured Query Language) que gera o produto cartesiano entre tabelas — produz \(n^2\) pares. Adicionar WHERE a.andar <> b.andar elimina as \(n\) diagonais onde entrada = saída e produz exatamente os \(A(n, 2)\) pares ordenados:

CREATE TABLE andares (andar INT);
INSERT INTO andares VALUES (1),(2),(3),(4),(5),(6),(7),(8);

SELECT a.andar AS entrada, b.andar AS saida
FROM   andares a
CROSS JOIN andares b
WHERE  a.andar <> b.andar
ORDER BY entrada, saida;
-- 56 linhas = A(8, 2)

SELECT COUNT(*)
FROM   andares a
CROSS JOIN andares b
WHERE  a.andar <> b.andar;
-- 56

A condição WHERE a.andar <> b.andar é exatamente o que distingue o arranjo \(A(n, 2) = n(n-1)\) do produto cartesiano \(n^2\): remove as \(n\) linhas onde a pessoa subiria e desceria no mesmo andar.

Programa de 3 atividades entre 4
#

Enunciado: Um estudante tem 4 atividades disponíveis: leitura (L), exercício (E), desenho (D) e culinária (C). Ele quer montar um programa diário com 3 dessas atividades em sequência definida — a ordem importa, pois determina o que fará pela manhã, tarde e noite. De quantas formas distintas pode montar esse programa?

Solução: Queremos selecionar e ordenar 3 atividades distintas entre 4. Preenchemos as três posições sequencialmente, sem repetição:

Período Opções disponíveis Justificativa
Manhã 4 qualquer das 4 atividades
Tarde 3 qualquer exceto a da manhã
Noite 2 qualquer exceto as duas já escolhidas
$$A(4, 3) = \frac{4!}{(4-3)!} = \frac{4!}{1!} = 4 \times 3 \times 2 = \mathbf{24}$$

Rotas entre 5 cidades — rota ordenada de 3 cidades
#

Enunciado: Um viajante precisa traçar uma rota que passe por exatamente 3 cidades entre São Paulo, Rio de Janeiro, Belo Horizonte, Porto Alegre e Curitiba. A ordem das cidades visitadas determina a rota — SP → RJ → BH é diferente de RJ → SP → BH. Quantas rotas distintas ele pode planejar?

Solução: Queremos uma sequência ordenada de 3 cidades distintas escolhidas entre 5. Preenchemos as três etapas da rota sequencialmente:

Etapa da rota Opções disponíveis Justificativa
1ª cidade 5 qualquer das 5 cidades
2ª cidade 4 qualquer exceto a 1ª
3ª cidade 3 qualquer exceto as duas anteriores
$$A(5, 3) = 5 \times 4 \times 3 = \mathbf{60}$$
Python: itertools.permutations e a fórmula do arranjo

itertools.permutations(iterable, r) gera exatamente os \(A(n, r)\) arranjos de \(r\) elementos distintos tirados de uma sequência de \(n\):

import itertools, math

# A(5, 3) — rotas de 3 cidades entre 5
cidades = ["SP", "RJ", "BH", "POA", "CWB"]
rotas = list(itertools.permutations(cidades, 3))
print(len(rotas))                          # 60

# Confirma com a fórmula
def arranjo(n, r):
    return math.factorial(n) // math.factorial(n - r)

print(arranjo(5, 3))                       # 60

Para \(n\) e \(r\) grandes, nunca materialize o iterador em lista — prefira contar pela fórmula. \(A(26, 3) \times A(10, 4) = 78{.}624{.}000\) objetos demandariam memória proibitiva.

SQL: triplo CROSS JOIN para rotas de 3 cidades

Estendendo o padrão do artigo sobre Princípios Aditivo e Multiplicativo: três CROSS JOIN encadeados com filtros de distinção geram \(A(n, 3)\) rotas ordenadas sem revisitar cidades.

CREATE TABLE cidades (cidade TEXT);
INSERT INTO cidades VALUES ('SP'),('RJ'),('BH'),('POA'),('CWB');

SELECT a.cidade AS origem,
       b.cidade AS escala,
       c.cidade AS destino
FROM   cidades a
CROSS JOIN cidades b
CROSS JOIN cidades c
WHERE  a.cidade <> b.cidade
  AND  b.cidade <> c.cidade
  AND  a.cidade <> c.cidade
ORDER BY origem, escala, destino;

SELECT COUNT(*)
FROM   cidades a
CROSS JOIN cidades b
CROSS JOIN cidades c
WHERE  a.cidade <> b.cidade
  AND  b.cidade <> c.cidade
  AND  a.cidade <> c.cidade;
-- 60 = A(5, 3)

O padrão generaliza para qualquer \(r\): encadeamos \(r\) cópias da tabela com CROSS JOIN e filtramos todos os pares de aliases com <>. Para \(r\) grande, essa abordagem se torna impraticável em SQL — use a fórmula.

Placas de veículos — 3 letras e 4 dígitos distintos
#

Enunciado: Um sistema de placas usa o formato AAA-NNNN: 3 letras do alfabeto (26 letras) seguidas de 4 dígitos (0–9). Nenhuma letra pode se repetir nas 3 posições de letras, e nenhum dígito pode se repetir nas 4 posições de dígitos. Quantas placas distintas podem ser emitidas?

Solução: A escolha das letras e a escolha dos dígitos são etapas independentes entre si, portanto aplicamos o Princípio Multiplicativo entre os dois blocos.

Bloco de letras — \(A(26, 3)\): selecionamos e ordenamos 3 letras distintas entre 26.

Posição Opções disponíveis Justificativa
1ª letra 26 qualquer das 26 letras
2ª letra 25 qualquer exceto a 1ª
3ª letra 24 qualquer exceto as duas anteriores
$$A(26, 3) = 26 \times 25 \times 24 = 15{.}600$$

Bloco de dígitos — \(A(10, 4)\): selecionamos e ordenamos 4 dígitos distintos entre 10.

Posição Opções disponíveis Justificativa
1º dígito 10 qualquer dos dígitos 0–9
2º dígito 9 qualquer exceto o 1º
3º dígito 8 qualquer exceto os dois anteriores
4º dígito 7 qualquer exceto os três anteriores
$$A(10, 4) = 10 \times 9 \times 8 \times 7 = 5{.}040$$

Total — Princípio Multiplicativo entre os dois blocos:

$$A(26, 3) \times A(10, 4) = 15{.}600 \times 5{.}040 = \mathbf{78{.}624{.}000}$$

Números de 3 algarismos distintos com \(\{0, 1, \ldots, 9\}\)
#

Enunciado: Quantos números de 3 algarismos (entre 100 e 999), com todos os algarismos distintos, podem ser formados com os dígitos \(\{0, 1, \ldots, 9\}\)?

Solução: A dificuldade é a restrição: o 1º algarismo não pode ser 0, caso contrário o número teria apenas 2 algarismos na prática (ex.: 053 = 53). Apresentamos duas abordagens.

Abordagem direta — preencher a posição restrita primeiro:

A estratégia é sempre começar pela posição com restrição, depois preencher as demais.

Posição Opções disponíveis Justificativa
Centenas (1º) 9 dígitos 1–9 (0 excluído)
Dezenas (2º) 9 dígitos 0–9 exceto o das centenas (0 volta a ser opção)
Unidades (3º) 8 dígitos 0–9 exceto os dois já usados
$$9 \times 9 \times 8 = \mathbf{648}$$

Verificação por complemento:

Contamos todos os arranjos de 3 dígitos distintos — inclusive os que começam com 0 — e subtraímos os inválidos:

  • Total sem restrição: \(A(10, 3) = 10 \times 9 \times 8 = 720\)
  • Começam com 0: 0 fixado na 1ª posição, 2 dígitos escolhidos entre os 9 restantes → \(A(9, 2) = 9 \times 8 = 72\)
$$A(10,3) - A(9,2) = 720 - 72 = \mathbf{648} \checkmark$$
Python: gerando e verificando PINs sem dígitos repetidos

Este exemplo é o problema clássico de dimensionar o espaço de PINs (Personal Identification Numbers, códigos de identificação pessoal) sem repetição — contexto introduzido na seção Por que arranjos simples?. O código abaixo enumera os PINs, aplica o filtro de validade e confirma o método do complemento:

from itertools import permutations

digitos = range(10)  # {0, 1, ..., 9}

# Todos os arranjos de 3 dígitos distintos (inclusive os que começam com 0)
todos = list(permutations(digitos, 3))
print(len(todos))     # 720 = A(10, 3)

# Apenas os válidos como número de 3 algarismos (sem 0 na 1ª posição)
validos = [p for p in todos if p[0] != 0]
print(len(validos))   # 648

# Casos inválidos: começam com 0 → A(9, 2) arranjos dos 9 dígitos restantes
invalidos = [p for p in todos if p[0] == 0]
print(len(invalidos)) # 72 = A(9, 2)

# Confirma o complemento
assert len(validos) + len(invalidos) == len(todos)  # 648 + 72 = 720 ✓

A última linha confirma em código o que fizemos no papel: \(A(10, 3) - A(9, 2) = 720 - 72 = 648\).

Números pares de 4 algarismos distintos com \(\{0,1,\ldots,9\}\)
#

Enunciado: Quantos números de 4 algarismos (entre 1000 e 9999), com todos os algarismos distintos, são pares, usando os dígitos \(\{0, 1, \ldots, 9\}\)?

Solução: Um número é par quando seu último algarismo (unidades) pertence a \(\{0, 2, 4, 6, 8\}\). Separamos em dois casos conforme o dígito final, pois a restrição do 1º algarismo (≠ 0) muda dependendo de qual dígito par ocupa a última posição.

Caso I — último algarismo = 0:

Com 0 fixado na última posição, ele não pode mais aparecer na 1ª posição — o que é automático, pois 0 já foi utilizado nessa posição.

Posição Opções disponíveis Justificativa
Unidades (4º) 1 fixado em 0
Milhares (1º) 9 dígitos 1–9 (0 já usado)
Centenas (2º) 8 dígitos restantes exceto os dois já usados
Dezenas (3º) 7 dígitos restantes
$$M_1 = 9 \times 8 \times 7 = \mathbf{504}$$

Caso II — último algarismo \(\in \{2, 4, 6, 8\}\):

Agora 0 não foi usado na última posição, portanto continua proibido na 1ª posição.

Posição Opções disponíveis Justificativa
Unidades (4º) 4 escolha entre \(\{2, 4, 6, 8\}\)
Milhares (1º) 8 dígitos 1–9 exceto o já usado nas unidades
Centenas (2º) 8 dígitos 0–9 exceto os dois já usados (0 volta a ser opção)
Dezenas (3º) 7 dígitos restantes
$$M_2 = 4 \times 8 \times 8 \times 7 = \mathbf{1{.}792}$$

Total — Princípio Aditivo entre os dois casos:

$$M_1 + M_2 = 504 + 1{.}792 = \mathbf{2{.}296}$$

Tabela-Resumo: Permutação vs. Arranjo
#

Conceito Usa todos? Ordem importa? Fórmula
Permutação simples Sim Sim \(n!\)
Arranjo simples Não (\(r < n\)) Sim \(\dfrac{n!}{(n-r)!}\)
note

Em geral, é conveniente começar a análise pelas posições que têm restrições especiais (ex.: não pode ser 0 na primeira posição).

Exercícios
#

Exercício 1 — Coordenador e subcoordenador

Em uma comissão de 10 professores, de quantas maneiras podem ser escolhidos um coordenador e um subcoordenador?

Resposta: A ordem importa (coordenador ≠ subcoordenador):

$$A(10,2) = 10 \times 9 = \mathbf{90}$$
Exercício 2 — Determinação de \(n\)

(a) Se \(A(n,2) = 72\), determine \(n\).   (b) Se \(4A(n,2) = A(2n,3)\), existe solução?

(a) \(n(n-1) = 72 \Rightarrow n^2 - n - 72 = 0 \Rightarrow \mathbf{n = 9}\)

(b) \(4n(n-1) = 2n(2n-1)(2n-2) = 4n(n-1)(2n-1)\). Dividindo ambos os lados por \(4n(n-1)\) (válido para \(n \geq 2\)): \(1 = 2n-1 \Rightarrow n = 1\). Mas isso contradiz \(n \geq 2\). Não tem solução.

Exercício 3 — Foto de 4 amigos entre 10

De quantas maneiras 4 amigos entre 10 podem se posicionar para uma foto?

Resposta: A ordem (posição na foto) importa:

$$A(10,4) = 10 \times 9 \times 8 \times 7 = \mathbf{5{.}040}$$
Exercício 4 — Bilhetes de companhia aérea

Uma companhia aérea liga 7 cidades. Quantos tipos de bilhetes (origem → destino) existem?

Resposta: \(A(7,2) = 7 \times 6 = \mathbf{42}\)

Exercício 5 — Números de 3 algarismos de \(\{2,3,5,8,9\}\)

Com os dígitos \(\{2,3,5,8,9\}\), conte os números de 3 algarismos distintos que são: (a) múltiplos de 5   (b) pares   (c) ímpares   (d) menores que 800

(a) Unidade = 5: \(A(4,2) = \mathbf{12}\)

(b) Unidade \(\in \{2,8\}\): \(2 \times A(4,2) = \mathbf{24}\)

(c) Unidade \(\in \{3,5,9\}\): \(3 \times A(4,2) = \mathbf{36}\)

(d) Centena \(\in \{2,3,5\}\): \(3 \times A(4,2) = \mathbf{36}\)


Próximos passos
#

O arranjo simples resolve o caso em que a ordem importa e usamos apenas \(r < n\) elementos. Sua limitação é exatamente essa exigência de ordem: em muitas situações práticas — montar uma comissão, escolher ingredientes de uma receita, selecionar filmes para assistir — só interessa quais elementos foram escolhidos, não em que sequência.

Quando a ordem não importa, chegamos às combinações simples, o próximo tema da série. Com permutações, arranjos e combinações teremos a tríade fundamental da combinatória, suficiente para resolver a grande maioria dos problemas de contagem.

A Arte de Contar - Este artigo faz parte de uma série de artigos.
Parte 4: Esse Artigo

Relacionados