CJam é uma linguagem de golfe baseada em pilha, inspirada no GolfScript, criada pelo usuário do PPCG aditsu .
Assim, na linha de outras perguntas de dicas específicas de idiomas:
Que dicas gerais você tem para jogar golfe no CJam? Poste uma dica por resposta.
Respostas:
Módulo correto para números negativos
Muitas vezes é irritante que o resultado da operação do módulo dê o mesmo sinal que o primeiro operando. Por exemplo,
-5 3%
dá em-2
vez de1
. Na maioria das vezes você quer o último. A solução ingênua é aplicar o módulo, adicionar o divisor uma vez e aplicar o módulo novamente:Mas isso é longo e feio. Em vez disso, podemos usar o fato de que a indexação de matriz é sempre modular e faz trabalho corretamente com índices negativos. Então, transformamos o divisor em um intervalo e acessamos:
Aplicado a
-5
, isso dá1
como esperado. E é apenas um byte a mais que o embutido%
!Se o módulo for uma potência de 2, você poderá salvar outro byte usando a aritmética bit a bit (que também é muito mais rápida). Comparar:
Para o caso especial de
65536 == 2^16
outro byte, pode ser salvo usando o comportamento de quebra automática do tipo de caractere:fonte
Empurrando intervalos de caracteres concatenados
A cadeia que contém todos os dígitos
"0123456789"
pode ser escrita comoAs letras ASCII maiúsculas (
A-Z
) podem ser pressionadas comoque gera a sequência de todos os caracteres até Z e descarta os primeiros 65 (até @ ).
Todas as letras ASCII (
A-Za-z
) podem ser pressionadas comoque funciona como acima, cria uma cópia, converte para minúsculas e acrescenta.
Mas há uma maneira mais curta de fazer isso!
O
^
operador geralmente esquecido (diferenças simétricas para listas) permite criar os mesmos intervalos enquanto economiza três bytes:'[,
cria o intervalo de todos os caracteres ASCII até Z ,_el
cria uma cópia em minúscula e^
mantém apenas os caracteres das duas seqüências que aparecem em uma, mas não nas duas.Como todas as letras da primeira string estão em maiúsculas, todas na segunda estão em minúsculas e todos os caracteres que não são da letra estão nas duas strings, o resultado na string de letras.
O alfabeto RFC 1642 Base64 (
A-Za-z0-9+/
) pode ser pressionado usando a técnica acima e acrescentando as não letras:Uma maneira igualmente curta de empurrar essa string utiliza apenas diferenças simétricas:
Como podemos encontrar a corda no começo?
Todos os intervalos de caracteres usados (
A-Z
,a-z
,0-9
,+
,/
) pode ser empurrado como a diferença simétrica de gama para que começam no byte nulo, ou seja'A,'[,^
,'a,'{,^
,'0,':,^
,'+,',,^
e'/,'0,^
.Portanto, a execução
:,:^
em"A[a{):+,/0"
vão empurrar os caracteres desejados, mas não na ordem certa.Como encontramos a ordem certa? Força bruta para o resgate! O programa
itera sobre todas as permutações possíveis da string, aplica
:,:^
e compara o resultado à saída desejada ( link permanente ).O alfabeto radix-64 usado, por exemplo, por crypt (
.-9A-Za-z
) pode ser gerado usando o método acima:Este é o método mais curto que eu conheço.
Como todos os caracteres na saída desejada estão na ordem ASCII, a iteração sobre permutações não é necessária.
Nem todos os intervalos de caracteres concatenados podem ser enviados na ordem desejada usando
:,:^
.Por exemplo, o intervalo
0-9A-Za-z;-?
não pode ser pressionado executando:,:^
qualquer permutação de"0:A[a{;@"
.No entanto, podemos encontrar uma variação girada da string desejada que pode, usando o código
que imprimirá ( permalink ) o seguinte:
Isso significa que
tem o mesmo efeito que
que só pode ser usado com uma pilha vazia sem anexar a
[
.fonte
Evitar {…} {…}?
Suponha que você tenha um número inteiro na pilha. Se for ímpar, você deseja multiplicá-lo por 3 e adicionar 1; caso contrário, você deseja dividi-lo por 2.
Uma declaração if / else "normal" seria assim:
No entanto, o uso de blocos geralmente não é o caminho a seguir, pois
{}{}
já adiciona quatro bytes.?
também pode ser usado para selecionar um dos dois itens na pilha:Este é um byte mais curto.
Quadra-? com uma declaração if vazia é sempre um impedimento. Por exemplo,
tem dois bytes a mais que
Se você tiver
e o que você está verificando é um número inteiro não negativo, você pode fazer
O novo
{}&
e{}|
é útil, mas às vezes problemático se você não pode desordenar a pilha.Ainda assim, no caso de
você pode usar uma variável temporária:
fonte
!)/
eg)/
são mais curtos nos exemplos.Instruções de troca
CJam não possui instruções de opção. As instruções aninhadas if funcionam da mesma maneira, mas
{{}{}?}{}?
já têm 12 bytes de comprimento ...Se pudermos transformar a condição em um número inteiro pequeno e não negativo, podemos transformar todas as instruções de caso em uma sequência delimitada e avaliar o resultado correspondente.
Por exemplo, se queremos executar
code0
se o número inteiro da pilha for 0 ,code1
se for 1 ecode2
se for 2 , poderemos usarou
ou
S/
divide a string em["code0" "code1" "code2"]
,=
extrai o pedaço correspondente e~
avalia o código.Clique aqui para ver as instruções do switch em ação.
Por fim, conforme sugerido por @ jimmy23013 e @RetoKoradi, podemos reduzir ainda mais a opção em alguns casos. Digamos
code0
,code1
ecode2
tenham comprimentos L 0 , L 1 e L 2 , respectivamente.Se L 0 = L 1 ≥ L 2
Em vez disso, pode ser usado, onde
L
é L 0 . Em vez de dividir em um delimitador,/
divida a cadeia em pedaços de comprimento igual aqui.Se L 0 ≥ L 1 ≥ L 2 ≥ L 0 - 1 ,
pode ser usado em seu lugar.
>
remove 0, 1 ou 2 elementos do início da string e3%
extrai cada terceiro elemento (começando com o primeiro).fonte
"code0code1code2"5/=~
? Parece muito mais direto para mim, e tem o mesmo comprimento.Valores comuns de array e string de golfe
Existem certas matrizes ou strings curtas que surgem de vez em quando, por exemplo, para inicializar grades. Ingenuamente, estes podem custar 4 ou mais bytes, por isso vale a pena procurar operações com valores internos que fornecerão o mesmo resultado. Especialmente a conversão de base geralmente é útil.
[0 1]
pode ser escrito como2,
.[1 0]
pode ser escrito comoYYb
(ou seja, 2 em binário).[1 1]
pode ser escrito comoZYb
(ou seja, 3 em binário).[[0 1] [1 0]]
pode ser escrita como2e!
.[LL]
pode ser escrito comoSS/
(dividir um único espaço por espaços)."\"\""
pode ser escrito comoL`
."{}"
pode ser escrito como{}s
.O último pode ser estendido aos casos em que você deseja que todos os tipos de colchetes salvem outro byte:
"[{<()>}]"
pode ser escrito como{<()>}a`
."()<>[]{}"
pode ser escrito como{<()>}a`$
.Especialmente, o truque de conversão de base pode ser útil para alguns casos obscuros que aparecem de vez em quando. Por exemplo,
[3 2]
seriaE4b
(14 na base 4).Em casos ainda mais raros, você pode até achar o operador de fatoração
mf
útil. Por exemplo,[2 7]
éEmf
.Fique à vontade para estender esta lista se você encontrar outros exemplos.
fonte
Limpando a pilha
Se você quiser limpar toda a pilha, envolva-a em uma matriz e solte-a:
O que é um pouco mais complicado é que, se você fez muitos cálculos, mas apenas deseja manter o elemento da pilha superior e descartar tudo o que está embaixo. A abordagem ingênua seria armazenar o elemento superior em uma variável, limpar a pilha, pressionar a variável. Mas há uma alternativa muito mais curta: agrupar a pilha em uma matriz e extrair o último elemento:
(Obrigado ao Optimizer, que me mostrou isso outro dia.)
Obviamente, se houver apenas dois elementos na pilha,
\;
é mais curto.fonte
\;
exibirá apenas o elemento abaixo dos Termos de Serviço. Você quis dizer;;
?e
e poderes de dezComo em muitas outras línguas, você pode escrever em
1e3
vez de1000
em CJam.Isso funciona para bases não inteiras e também para expoentes não inteiros. Por exemplo,
1.23e2
empurra 123,0 e1e.5
empurra 3,1622776601683795 (raiz quadrada de 10 ).O que não é imediatamente óbvio é que
1e3
na verdade existem dois tokens:1
empurra o número inteiro 1 na pilha.e3
multiplica por 1000 .Por que isso é importante?
Você pode chamar
e<numeric literal>
algo que já está na pilha.Você pode mapear
e<numeric literal>
sobre uma matriz.fonte
Normas euclidianas
A maneira direta de calcular a norma euclidiana de um vetor, isto é, a raiz quadrada da soma dos quadrados dos seus elementos, é
No entanto, há uma maneira muito mais curta.
mh
, O operador hipotenusa, aparece dois inteiros um e b a partir da pilha e empurra sqrt (a 2 + b 2 ) .Se tivermos um vetor x: = [x 1 … x n ], n> 1 na pilha,
:mh
(reduzir por hipotenusa) obterá o seguinte:Primeiro x 1 e x 2 são pressionados e
mh
são executados, deixando sqrt (x 1 2 + x 2 2 ) na pilha.Em seguida, x 3 é pressionado e
mh
é executado novamente, deixandosqrt (sqrt (x 1 2 + x 2 2 ) 2 + x 3 2 ) = sqrt (x 1 2 + x 2 2 + x 3 2 ) na pilha.
Após o processamento de x n , ficamos com sqrt (x 1 2 +… x n 2 ) , a norma euclidiana de x .
Se n = 1 e x 1 <0 , o código acima produzirá um resultado incorreto.
:mhz
funciona incondicionalmente. (Obrigado a @ MartinBüttner por apontar isso.)Eu usei esse truque pela primeira vez nesta resposta .
fonte
Converta da base n com uma lista de números maior que n
CJam converte uma lista em um número com esta fórmula: A 0 * n l + A 1 * n l-1 + A 2 * n l-2 + A l * n 0 (com não negativo
n
).n
é a base el
é o comprimento da lista. Isso significa que A i pode ser qualquer número inteiro, que não precisa estar no intervalo de[0,n)
.Alguns exemplos:
0b
extrai o último item e o converte em número inteiro. Funciona comoW=i
e salva um byte se não fosse um número inteiro. Mas todo o resto da lista também deve ser capaz de converter em número inteiro.1b
retorna a soma. Funciona como:i:+
e salva dois bytes se não fossem números inteiros. Também funciona com listas vazias, enquanto:+
não.[i{_1&9 32?_@\m2/}16*;]W%:c
converte um caractere em uma sequência de linhas e tabulações, que podem ser convertidas novamente2bc
. A função de codificação não é fácil de jogar em um programa de código-golfe. Mas você geralmente não precisa disso.Você pode usar o código a seguir para converter uma seqüência de caracteres em caracteres Unicode não em 16 bits, que podem ser convertidos novamente
2A#b128b:c
. (As explicações serão adicionadas mais tarde. Ou talvez eu escreva uma nova versão mais tarde.)O método semelhante funciona com qualquer conjunto de
n
números inteiros com valores diferentes modn
, se você puder encontrar uma maneira de se livrar do dígito mais significativo.fonte
Usando
$
como ternário seQuando você não se importa de vazar memória, ou seja, deixando elementos não utilizados na pilha com os quais você limpará mais tarde
];
, o operador de cópia$
pode ser um substituto útil para o operador ternário?
.?
funciona bem se você conseguir calcular a condição antes de pressionar os dois itens para escolher, mas, na maioria das vezes, a condição realmente depende desses itens, e tê-la em cima deles resulta muito mais natural.Se você tiver
A B C
na pilha, poderá executarao invés de
para copiar
B
seC
é verdade ouA
não.Se
C
for um booleano (0
ou1
) real , você pode executarao invés de
para copiar
A
seC
é verdade ouB
não.fonte
Mapa para listas aninhadas
Digamos que você tenha uma lista aninhada, como uma matriz:
Ou uma matriz de strings:
E você deseja mapear um bloco no nível aninhado (ou seja, aplicá-lo a cada número ou cada caractere). A solução ingênua é aninhada
%
:No entanto, você pode realmente empurrar o bloco interno para a pilha e usá-lo
f%
.f
é "map com parâmetro adicional", portanto, ele será mapeado%
para a lista externa, usando o bloco como o segundo parâmetro:Salva dois bytes.
Outro truque interessante para fazer algo como
for (i=0; i<5; ++i) for (j=0; j<5; ++j) {...}
éO externo
f
será mapeado para o primeiro intervalo, fornecendo o segundo intervalo como um parâmetro adicional. Mas agora, se você usarf
novamente, apenas o elemento superior da pilha é uma matriz, então vocêf
mapeia o bloco interno para isso, fornecendo a "variável de iteração" externa como um parâmetro adicional. Isso significa que o bloco interno é executado comi
ej
na pilha.Isso tem o mesmo número de caracteres do que apenas mapear um bloco em um produto cartesiano (embora o último fique mais curto se você precisar dos pares como matrizes):
A diferença é que esta versão gera uma única matriz de resultados para todos os pares, enquanto a dupla
f
produz uma lista aninhada, que pode ser útil se você deseja armazenar os resultados em uma grade, com as variáveis do iterador sendo as coordenadas.Agradeço ao Dennis por me mostrar esse truque.
0.6.4 Atualizar
f
e:
agora foram imensamente aprimorados com a utilização de qualquer outro operador, inclusive eles próprios. Isso significa que você pode salvar ainda mais bytes agora. O mapeamento de um operador em uma lista aninhada ficou ainda mais curto agora:Isso realmente não ajuda no mapeamento de blocos para listas aninhadas.
Quanto à aplicação de blocos ou operadores ao produto cartesiano, isso também ficou mais curto agora, tanto para blocos quanto para operadores:
O legal é que agora você pode aninhar isso. Assim, você pode aplicar um operador com a mesma facilidade ao terceiro nível de uma lista:
Ou um bloco com alguns truques:
fonte
f~
...f
espera que um operador binário~
seja unário; você talvez quisesse:~
? Além disso, podemos discutir isso no chatUnhandled char after ':': :
( ligação )Operadores vetorizados para arte ASCII
Para muitos desafios de arte ASCII, é útil gerar dois padrões diferentes para superpor mais tarde. Operadores vetorizados podem ser muito úteis para obter diferentes tipos de superposições.
Uma propriedade útil da vetorização do operador é que o operador é executado apenas uma vez para cada elemento da string / matriz mais curta, enquanto os elementos da maior que não possuem contrapartes permanecem intocados.
.e<
O operador mínimo
e<
trabalha para pares de cadeias, caracteres, matrizes e números inteiros; ele solta dois itens da pilha e empurra a parte de baixo para trás.Como um espaço tem um ponto de código mais baixo do que todos os outros caracteres ASCII imprimíveis,
.e<
pode ser usado para "apagar" partes de um padrão gerado:Para um exemplo completo, consulte minha resposta para Me Want Honeycomb .
.e>
O operador máximo
e>
funciona como o operador mínimo, com o resultado oposto.Novamente, devido ao baixo ponto de código do espaço,
.e>
pode ser usado para inserir um padrão de caracteres imprimíveis em um bloco de espaços:Para um exemplo completo, consulte minha resposta para o Seven Slash Display .
.e&
O operador AND lógico
e&
pressiona seu argumento esquerdo, se for falso e, caso contrário, seu argumento correto.Se nenhum dos padrões contiver elementos falsos, isso poderá ser usado para impor incondicionalmente um padrão sobre outro:
Para um exemplo completo, veja minha resposta para Imprimir a bandeira americana! .
.e|
O operador OR lógico
e|
pode ser usado como acima, com ordem de argumento invertida:fonte
Use
&
para verificar se um item está em uma listaPara
Você pode usar
em vez disso, que retorna 0/1 e truthy / falsey, respectivamente.
fonte
z
e matrizes não retangularesO operador postal
z
transpõe as linhas e colunas de um bidimensional uma matriz A , cujos elementos também pode ser iterables.Para matrizes não retangulares - diferentemente das
zip
funçõesnil
internas em, por exemplo, Python (trunca as linhas com o mesmo comprimento) ou Ruby ( preenche as linhas ) - o CJam simplesmente converte as colunas da matriz em linhas, ignorando seus comprimentos e lacunas.Por exemplo, compactando a matriz
é equivalente a fechar o array
ou a matriz
como todas as três ações pressionam
na pilha.
Embora isso signifique que
z
não é uma involução (o que seria útil em algumas ocasiões), ele tem alguns aplicativos.Por exemplo:
Podemos alinhar as colunas de uma matriz ao topo (ou seja, transformar a primeira matriz na segunda) fechando duas vezes:
Modificações menores do método acima podem ser usadas para problemas semelhantes.
Por exemplo, para alinhar as colunas de uma matriz com a parte inferior (ou seja, para transformar a segunda matriz na primeira), podemos compactar duas vezes com a ordem inversa das linhas:
Dada uma matriz de cadeias, podemos calcular o comprimento da cadeia mais longa assim:
No entanto, compactando e calculando o número de linhas do resultado, podemos salvar três bytes:
1 Se qualquer uma das "linhas" de A não for iterável,
z
tratá-las como singletons, portanto, compactar funciona para matrizes arbitrárias.fonte
z
conversão de colunas em linhas, enquanto os valores vazios são ignorados. No exemplo, a primeira coluna na entrada é 1, 2, 3, a segunda coluna é 4, 5 (a posição vazia é ignorada) e a terceira coluna é 6. Essas são as linhas do resultado.Exceções
Todas as exceções são fatais no CJam. Como a saída para STDERR é ignorada por padrão , podemos usar isso para nossa vantagem.
Todos os operadores no CJam trabalham inserindo zero ou mais elementos da pilha, realizando alguma tarefa e pressionando zero ou mais elementos na pilha. Exceções ocorrem enquanto a tarefa é executada, portanto, ainda aparece os elementos, mas nada é enviado em retorno.
Aqui estão alguns casos de uso:
Limpando uma pequena pilha
Para limpar uma pilha que contém dois elementos,
@
pode ser usado.@
tenta exibir três elementos da pilha, mas falha depois de exibir o segundo.Qualquer outro operador que exibir três elementos serviria ao mesmo propósito.
Veja em ação aqui .
Removendo dois ou três elementos da pilha
Qualquer operador que não esteja implementado para esses elementos em particular pode ser usado para exibir dois ou três elementos da pilha antes de sair.
Para exibir dois elementos,
b
funciona se um deles é um caractere ou nenhum deles é um número inteiro.Para exibir três elementos,
t
funciona se nenhum dos dois inferiores for iterável, o iterável inferior estiver vazio ou nenhum deles for um número inteiro.Saindo de um loop
Em algumas ocasiões, precisamos sair de um loop quando um número inteiro se torna zero ou uma string se torna muito curta. Em vez de testar essas condições, se as operações envolvidas falharem com zero, a sequência vazia ou os singletons, podemos simplesmente deixar o programa seguir seu curso natural.
Para um exemplo envolvendo aritmética, veja aqui .
Para um exemplo envolvendo seqüências de caracteres, veja aqui .
Execução condicional
Se o código-fonte não deve ser executado para certos tipos de entrada, às vezes podemos usar um operador que falha nesse tipo de entrada.
Por exemplo,
i
falhará para cadeias que não são avaliadas como um número inteiro eew
falhará para cadeias de comprimento 0 ou 1.Veja em ação aqui .
fonte
Max / Min de uma matriz
Aqui está um para iniciantes!
Quando você precisa encontrar o número máximo ou mínimo de uma matriz, a maneira mais fácil e menor é classificar a matriz e remover o primeiro ou o último elemento.
Portanto, se a matriz estiver na variável
A
é o máximo e
é o mínimo.
Obter os dois ao mesmo tempo também é possível
Isso pode parecer óbvio após a leitura, mas a primeira tentativa de qualquer pessoa tende a ir para o uso
e<
ou ae>
iteração da matriz, que ocorre comoque é 2 bytes mais longo e ainda mais se você deseja max e min.
fonte
(
e, em)
vez de0=
eW=
.:e<
e:e>
Use um carimbo de data / hora para grandes números
Se você precisa de um número muito grande, mas arbitrário, geralmente usa notação científica como
9e9
ou eleva uma das grandes variáveis incorporadas a um poder semelhante, comoKK#
. No entanto, se você não se importa qual é o número real e não precisa ser consistentemente o mesmo (por exemplo, o limite superior de um número aleatório), é possível fazê-lo em dois bytes usandoem vez de. Isso fornece o registro de data e hora atual em milissegundos e está na ordem de 10 12
fonte
e9
.Verificando se duas strings / matrizes não são iguais
Às vezes, você deseja um valor verdadeiro quando duas cadeias ou matrizes não são iguais e um valor falso, se forem. A solução óbvia é dois bytes:
Verifique a igualdade e inverta o resultado. No entanto, sob algumas condições, você pode usar
Quando
#
aplicado a duas matrizes, na verdade, procura a segunda matriz como uma sub-matriz da primeira (e fornece o índice onde a sub-matriz inicia). Portanto, se as duas matrizes forem iguais, o sub-arranjo será encontrado logo no início e0
doado, o que é falso. Mas se a segunda matriz não puder ser encontrada, ela dará o-1
que é verdadeiro.A razão pela qual precisamos de alguma condição adicional nas duas matrizes é que isso também gera um valor falso se a segunda matriz for um prefixo não trivial da primeira, por exemplo:
dá
0
embora as cordas não sejam as mesmas. A condição mais simples que exclui esse caso é se você souber que as duas matrizes terão o mesmo comprimento - nesse caso, se uma for um prefixo da outra, você saberá que elas são iguais. Mas, em circunstâncias específicas, pode haver condições mais fracas que também sejam suficientes. Por exemplo, se você souber que as strings são classificadas, um prefixo sempre será a primeira, não a segunda.fonte
c
e inteiros de 16 bitsPara adicionar (ou subtrair) números inteiros de 16 bits não assinados com quebra automática, você pode usar
+65536%
ou+2G#%
.Contudo,
é muito mais curto. Os caracteres são agrupados em 65536 , portanto, a conversão para Character (
c
) e Long (i
) tem um efeito semelhante a65536%
, com o benefício adicional de que o resultado não será negativo.O mesmo truque pode ser usado para enviar 65535 :
fonte
Conjuntos de potência
Digamos que você tenha uma matriz e deseje uma matriz com todos os subconjuntos possíveis dessa matriz. O truque é começar com uma matriz vazia e, em seguida, para cada elemento, duplicar os subconjuntos que você já possui e adicionar o novo elemento a eles (mantendo o resultado anterior onde o elemento não foi adicionado ). Observe que você precisa inicializar a pilha com o caso base, ou seja, uma matriz que contenha apenas uma matriz vazia: Isso pode ser assim:
O bom disso é que você pode executar imediatamente alguns cálculos no subconjunto, potencialmente sem caracteres adicionados. Digamos que você queira os produtos de todos os subconjuntos. Nesse caso, o caso base é uma matriz que contém
1
, e a cada etapa, você pega a lista anterior de produtos possíveis, a duplica e multiplica tudo na duplicata pelo novo elemento:fonte
Verifique se os itens de uma lista são iguais
Eu acho que isso também vale a pena mencionar. Usar:
Retorna verdade se não for a mesma coisa ou lista vazia se for a mesma coisa. Erros se a lista estiver vazia.
Caso o item extraído possa ser uma matriz (ou sequência):
Use
!
ou!!
para obter valores booleanos. Caso o item extraído possa ser uma matriz e haja no máximo dois tipos de itens diferentes, e você deseja que seja 1 se não for o mesmo, isso é mais curto:fonte
0=
para cordasPara recuperar o primeiro elemento de uma matriz, você precisa usar
0=
(ou(
, se não se importa em deixar o resto da matriz na pilha).No entanto, se essa matriz for uma sequência, a conversão para caractere é suficiente.
Exemplo
fonte
c
extrair o primeiro elemento de qualquer matriz, o que seria mais útil e consistente.Girando uma matriz (ou a pilha) uma unidade para a esquerda
O CJam possui o operador girar para a esquerda
m<
, que normalmente é o que você deve usar para girar uma matriz com um número arbitrário de unidades para a esquerda.Em alguns casos, você também pode usar
(+
para mudar e acrescentar:O segundo exemplo não funcionou porque o primeiro elemento das matrizes também é iterável, portanto
+
concatenado em vez de anexar.Além disso, se você quiser despejar a matriz rotacionada na pilha, poderá usar
:\
(reduzir ao trocar) incondicionalmente:Contanto que você não tenha uma abertura
[
, esse truque também pode ser usado para girar a pilha inteira, ou seja, para trazer o item da pilha mais inferior para o topo:fonte
Imprimindo uma lista e limpando a pilha
Digamos que sua pilha tenha uma lista de strings / números / etc. na parte superior e alguns outros itens extras abaixo dela. ie
Agora você está interessado em imprimir apenas a última lista, para
quais saídas
O que parece realmente inteligente, pois usamos o truque de limpar a pilha e imprimimos apenas a lista unida com espaços (que pode não ser a maneira desejada de imprimir uma lista às vezes).
Isso pode ser jogado ainda mais!
Isso é 2 bytes mais curto !
e se você tiver apenas 1 item na pilha que não seja a lista, é ainda mais curto!
A
p
vantagem é que ele remove o item mais importante da pilha, o especifica (também adiciona uma nova linha no final) e imprime no STDOUT instantaneamente, sem aguardar a conclusão do código.Portanto, o código acima irá gerar
qual é a representação exata de uma lista quando estava na pilha!
fonte
Produtos cartesianos ou todas as combinações possíveis de dois ou mais conjuntos
O CJam possui uma calculadora cartesiana embutida do produto,
m*
que pega as duas listas / cadeias de caracteres da pilha e cria todos os pares possíveis. Por exemplosai
como a pilha
Mas e se você quiser todas as combinações possíveis de mais de 2 listas / strings. Você usa
m*
isso muitas vezes? Por exemplodeixará o seguinte na pilha
Observe que os produtos ainda são pares, onde um dos itens é o próprio par. Isso não é esperado e queremos combinações achatadas.
Existe uma maneira fácil de fazer isso. Basta agrupar todas as listas que você deseja para o seu produto cartesiano em uma matriz, criar aos pares produtos cartesianos e achatá-lo sempre:
Isso deixa
na pilha.
Deseja que o pedido seja mantido? , basta trocar o antes de adicionar o item pop-up novamente à matriz. ie
Deseja apenas permutações?
Deseja apenas elementos exclusivos nas combinações?
Isso é tudo, pessoal. por agora .
fonte
]:m*:e_
, com qualquer número de matrizesOperando em strings
Às vezes, se você estiver trabalhando com uma estrutura de dados complexa, enquanto os itens nela forem simples, a conversão em seqüências de caracteres pode ajudar.
Por exemplo, se você deseja obter o primeiro ou o último item em uma matriz 2D de bits e não se importa com o tipo retornado,
sA<
salva um byte de0=A<
ou:+A<
.Ou, se você quiser modificar alguns bits na entrada, poderá modificar a sequência antes de avaliá-la.
Ou se você conseguiu essa estrutura e deseja convertê-la em uma lista simples:
Você pode fazer isso com muitos caracteres de outras maneiras:
Mas pode ser muito mais curto com seqüências de caracteres:
É mais curto, mesmo que possa ter números com mais de um dígito:
Ou:
Se você não precisar de outra matriz contendo muitas dessas matrizes.
fonte
e_
agoras
ainda funciona melhor.Usando em
N
vez deLa
Em muitos casos, você precisa de algo inicializado em uma matriz que contenha uma matriz vazia como seu único elemento, que é
La
aparentemente desnecessariamente 1 byte a mais.Em muitos casos, você também precisa adicionar uma nova linha após cada elemento antes da impressão, o que seria algo como
No
ouN*
.Mas se os dois forem verdadeiros, às vezes você pode descobrir que pode apenas inicializar a matriz com
N
, que tem o caractere de nova linha como seu único elemento. Certifique-se de anexar apenas itens aos elementos no restante do código, e a primeira coisa a acrescentar sempre é um caractere ou uma matriz. Ou apenas acrescente, se uma nova linha principal for aceitável e a diminuir.Às vezes,
S
também funciona se você precisar separar a saída com espaços.Em casos mais raros, o elemento inicial deve ser uma string. Mas você ainda pode usar o
Na
que pode ser menor do que acrescentar a nova linha posteriormente.fonte
Divisão em uma ou mais ocorrências
Digamos que você tenha uma string
"abbcdbbfghbdbb"
e queira dividi-lab
Isso deixa na pilha:
Observe as cadeias vazias? Aqueles estão lá porque dois
b
estavam juntas e não havia nada entre elas. Às vezes, você deseja evitar isso. Você pode fazer issoou filtrando cadeias vazias
mas são 3 bytes extras.
Um operador pouco menos conhecido para esse caso de uso específico é
%
. Além de fazer mod e mapear e dividir com base no número ("abcd"2%
="ac"
),%
também pode dividir em strings / matrizes. Portanto, para o caso de uso acima:vai deixar
na pilha.
Obrigado por @ user23013 por apontar isso em uma das minhas respostas hoje.
fonte
Use fold / reduza como infix foreach
Temos
:x
como abreviação de{x}%
e ou{x}*
(dependendo sex
é unário ou binário). Infelizmente, não há um operador de infixo equivalente para encurtar{x}/
. No entanto, muitas vezes quando o fazemos{x}/
,x
é realmente um operador binário que modifica repetidamente o item que está embaixo da pilha. Se for esse o caso, e o referido item não for uma matriz, podemos salvar um byte abusando da dobra / redução como foreach:Isso funciona porque a dobra sempre deixa o primeiro elemento intocado. Infelizmente, ele não salva um byte, quando o elemento modificado é uma matriz, porque adicioná-lo o desembrulharia. No entanto, às vezes você tem sorte o suficiente para que sua matriz já contenha esse elemento na frente; nesse caso, a redução deve ser lembrada (em vez de remover manualmente o elemento antes de usá-lo
{}/
no restante).fonte
print e println
CJam tem
print
operador:o
. Funciona, mas a pilha está sendo impressa imediatamente após a execução de todo o código. Você pode pará-lo se limpar a pilha no final do programa. Basta colocar isso no final:Para imprimir, você pode usar
oNo
oup
(funciona como`oNo
)fonte
o
ep
.p
começa convertendo o item a ser impresso em uma representação de seqüência inequívoca.p
é equivalente à execução`oNo
.