Guerra é paz. Liberdade é escravidão. Ignorância é força


69

Como George Orwell escreveu em 1984 :

Guerra é paz
Liberdade é escravidão
Ignorância é força

Escreva um programa ou função que capte uma das seis palavras principais da citação de Orwell e emita sua contraparte.

Especificamente:

[input] -> [output]
war -> peace
peace -> war
freedom -> slavery
slavery -> freedom
ignorance -> strength
strength -> ignorance

Nenhum outro par de entrada / saída é necessário.

Você deve assumir que as palavras estão sempre em minúsculas, como acima. Alternativamente, você pode supor que as palavras são sempre totalmente maiúsculas: WAR -> PEACE, PEACE -> WAR, etc.

O código mais curto em bytes vence.



2
@Dennis Sim. Ou tudo é minúscula, ou tudo é maiúscula.
— Passatempos de Calvin

3
Não sei se alguém pode usar isso para compactar mais suas cordas (não melhorou minha pontuação no Pip), mas as letras iniciais dessas palavras ( w p f s i) não são encontradas em nenhum outro lugar em nenhuma das palavras. Uma propriedade intrigante.
— DLosc

13
Este é um desafio doubleplusgood
— Jojodmo

Respostas:


58

05AB1E , 30 bytes

05AB1E usa CP-1252 .

“ignorance¤í‡î—™šÔÃÒry“#DIk1^è

Experimente online! ou como um conjunto de testes

Explicação

A abordagem direta

  • Empurre a corda ignorance strength war peace freedom slavery
  • Dividir em espaços
  • Obter o índice da entrada na lista
  • XOR o índice com 1
  • Obter o elemento na lista nesse índice

42
14 bytes mais curto que o comprimento de todas as palavras. O que é essa linguagem?
— DJMcMayhem

65
> Aperte a cordaignorance strength war peace freedom slavery , sinto que estou perdendo cerca de uma dúzia de passos lá!
— Bob


10
Alguém pode explicar de onde vêm as outras palavras além de "ignorância"?
— precisa saber é o seguinte

36
O 05AB1E possui um dicionário interno de palavras que são representadas por 2 bytes cada: github.com/Adriandmen/05AB1E/blob/master/dictionary.py
— Robert Fraser

47

JavaScript (ES6), 80 bytes

s=>'freedom,,war,,strength,,slavery,peace,ignorance'.split`,`[s.charCodeAt(1)%9]

Como funciona

Utilizamos uma pequena tabela de pesquisa baseada no código ASCII do 2º caractere de cada palavra, retornando o índice de sua contraparte.

Word      | 2nd char. | ASCII code | MOD 9
----------+-----------+------------+------
war       | a         | 97         | 7
peace     | e         | 101        | 2
freedom   | r         | 114        | 6
slavery   | l         | 108        | 0
ignorance | g         | 103        | 4
strength  | t         | 116        | 8

Como observação lateral, se a combinação de maiúsculas e minúsculas fosse permitida, o uso war PEACE FREEDOM slavery IGNORANCE strengthcom o módulo 6 levaria a um hash perfeito.

Teste


2
Essa é uma abordagem legal. Nunca teria pensado nisso.
— Carcigenicate

Muito agradável. Os restos não são distintos para 6, 7, 8, então você precisa 9.
— ShreevatsaR

Usando um separador como ze, em seguida, compactando a string com atobeconomiza 8 bytes?
— Downgoat

@Downgoat Isso não exigiria muito escape para caracteres fora do intervalo 32-126?
— Arnauld

usando atobvocê obtém uma string que é na maior parte javascript válido - eventualmente você precisa escapar apenas do `\` e da citação de fechamento. Pode ser difícil publicá-lo neste site, mas isso não invalida a resposta. Veja a resposta perl de smis
— edc65

32

Gelatina , 24 bytes

“Ñ=ƘḊ¹ƥ¹Ƙ⁷ṅ8cøGị»Ḳµiɠ^1ị

Experimente online!

Como funciona

Primeiro, o token

“Ñ=ƘḊ¹ƥ¹Ƙ⁷ṅ8cøGị»

índices no dicionário de Jelly para criar a string

strength war peace freedom slavery ignorance

que Ḳdivide em espaços para gerar a matriz de strings

["strength", "war", "peace", "freedom", "slavery", "ignorance"]

µ inicia uma nova cadeia monádica, com essa matriz de string como argumento, que também é o valor de retorno atual.

ɠlê uma linha de entrada de STDIN e iencontra seu índice do valor de retorno anterior, ou seja, a matriz de strings gerada.

Agora, ^1pegue o XOR bit a bit desse índice e 1 . Para índices mesmo - lembre-se que os índices de geléia são um baseado e modular, assim que a força tem índice 1 e ignorância tem índice de 6 / 0 - isto incrementa o índice; para índices ímpares, diminui-os.

Por fim, ịrecupera a sequência nesse índice a partir do argumento da cadeia.


16

Mathematica, 84 bytes

(x="war""peace")(y="freedom""slavery")(z="ignorance""strength")/#/.x->1/.y->1/.z->1&

Explicação

Mais "aritmética" com cordas! Como na resposta vinculada, isso se baseia no fato de que você pode "multiplicar" cadeias no Mathematica, o que as deixará sem avaliação (semelhante à multiplicação de duas variáveis ​​não atribuídas x*y), mas o Mathematica aplicará simplificações básicas, como fatores de cancelamento em uma divisão.

Então, vamos começar por armazenar os três pares de produtos x, y, z, respectivamente, e multiplicá-los todos juntos:

(x="war""peace")(y="freedom""slavery")(z="ignorance""strength")

Isso avalia como

"freedom" "ignorance" "peace" "slavery" "strength" "war"

(O Mathematica classifica automaticamente os fatores, mas não nos importamos com o pedido.)

Dividimos isso pela entrada para remover a palavra com a qual não queremos .../#, pois o Mathematica cancela os fatores. Por exemplo, se a entrada fosse "peace", teríamos:

"freedom" "ignorance" "slavery" "strength" "war"

Finalmente, se livrar dos pares que não está interessado, substituindo cada um x, ye zcom 1. Novamente, a simplificação do Mathematica 1*aé sempre assim a. Esta parte é feita com:

/.x->1/.y->1/.z->1

O bom é que o Mathematica sabe que a multiplicação é Orderlessassim, e isso encontrará os dois fatores, independentemente de serem adjacentes ao produto ou não. Somente a palavra oposta à entrada não é mais emparelhada no produto, para que não seja removida e permaneça como a única saída.


Argh, tão bem feito! Eu perco por 7 bytes com WordList[][[<|"l"->14007,"t"->17083,"a"->25105,"r"->32106,"g"->33790,"e"->39048|>@#[[2]]]]&.
— Greg Martin

@GregMartin Oh, WordListé legal. Pegar uma lista de caracteres como entrada e retornar uma string parece um pouco complicado. ;) Dito isto, você pode fazer 4 bytes melhor com x[[7-Position[x={"war","slavery","ignorance","strength","freedom","peace"},#][[1,1]]]]&.
— Martin Ender

Eu estarei interessado na sua opinião, mas para mim, parece desonesto sancionado por PP e CG :) #
— 687 Greg Martin

também <|#->#2&~MapThread~{x={"war","slavery","ignorance","strength","fre‌edom","peace"},Reverse@x}|>para 94 bytes
— Greg Martin

13

Vim, 60 bytes

D3iwar freedom ignorance peace slavery strength <esc>2?<C-r>"
3wdwVp

Experimente online! no intérprete V compatível com versões anteriores.

Obviamente, se mudarmos para V, poderemos salvar um byte usando um método de entrada mais conveniente. Mas como essa é uma diferença tão pequena, prefiro usar a versão que não seja de golfe.

Explicação:

D                       " Delete this whole line
 3i...<esc>             " Insert the text three times
           2?           " Search backwards twice
             <C-r>"     " For the words we deleted
3w                      " Move three words forward
  dw                    " Delete a word
    V                   " Select this whole line
     p                  " And paste the word we deleted over it

10

C (gcc) , 120 107 bytes

f(long*s){long r[2]={0};strcpy(r,s);s=*r>>40?*r>>56?"\n":"":"CE";*r^=*s;r[1]^=69;puts(r);}

Máximo abuso de ponteiro! Requer uma máquina little-endian e comprimentos de 64 bits.

O código contém alguns não imprimíveis, mas a cópia e colagem ainda deve funcionar.

Experimente online!


8

Python, 81 bytes

l='war peace freedom slavery ignorance strength'.split()
lambda s:l[l.index(s)^1]

Ou mesmo comprimento:

l='war slavery ignorance strength freedom peace'.split()
dict(zip(l,l[::-1])).get

Definições de variáveis ​​fora do lamba são permitidas ao usar um lambda em vez de um programa completo?
— SMLS

11
@smls Sim, veja esta meta-discussão . Note que, de outro modo, alguém poderia entrar lcomo um argumento opcional.
— Xnor

8

Perl 6 , 61 bytes

Com caracteres não imprimíveis mostrados como (porque o StackExchange os retira do contrário):

{first {s/^\w+<(\0*$//},["���ce","�������","���
����e"X~^$_]}

Aqui está um xxddump hexadecimal:

00000000: 7b66 6972 7374 207b 732f 5e5c 772b 3c28  {first {s/^\w+<(
00000010: 5c30 2a24 2f2f 7d2c 5b22 0704 1363 6522  \0*$//},["...ce"
00000020: 2c22 151e 0413 011d 1422 2c22 1a13 1c0a  ,".......","....
00000030: 1c06 1a0b 6522 587e 5e24 5f5d 7d0a       ....e"X~^$_]}.

Versão expandida (caracteres não imprimíveis substituídos por seqüências de escape e espaço em branco e comentários adicionados):

{    # A Lambda.
    first {                   # Return first element which:
        s/ ^ \w+ <( \0* $ //  #   after stripping \0 has only word characters left.
    },
    [                                                  # The array to search:
        "\x[7]\x[4]\x[13]ce",                          #   "war" xor "peace"
        "\x[15]\x[1e]\x[4]\x[13]\x[1]\x[1d]\x[14]",    #   "freedom" xor "slavery"
        "\x[1a]\x[13]\x[1c]\n\x[1c]\x[6]\x[1a]\x[b]e"  #   "ignorance" xor "strength"
        X~^ $_                                         #   each xor'ed with the input.
    ]
}

8

Bash , 100 87 86 78 bytes

a=peace;e=war;r=slavery;l=freedom;g=strength;t=ignorance;x=${1:1:1};echo ${!x}

Experimente online!

A segunda letra de cada palavra identifica exclusivamente essa palavra, então eu uso esse caractere como um nome de variável; o valor dessa variável é a outra palavra correspondente.

Por exemplo, a segunda letra de peaceé ee a palavra correspondente a peaceé war, então eu defino e=war.

Dada uma string de entrada, o segundo caractere dessa string é usado como um nome de variável para exibir a palavra correspondente desejada, usando a expansão indireta dos parâmetros do bash.


8

TI-Basic, 103 84 77 bytes

Reduzir para uma linha economizou muitos bytes! Haha, como essa afirmação foi irônica ...

inString("EALRGT",sub(Ans,2,1
sub("WAR  PEACE FREEDOMSLAVERY STRENGTH IGNORANCE ",9Ans+1,4+Ans

7

Perl , 63 bytes

62 bytes + -psinalizador.

$_=(slavery,freedom,ignorance,strength,war,peace)[(ord)%6+/h/]

Experimente online!

ordretorna o código de caractere do primeiro caractere da palavra de entrada.
Após o %6, temos:

- liberdade => ord = 102 =>% 6 = 0  
- escravidão => ord = 115 =>% 6 = 1  
- ignorância => ord = 105 =>% 6 = 3  
- força => ord = 115 =>% 6 = 1  
- guerra => ord = 119 =>% 6 = 5  
- paz => ord = 112 =>% 6 = 4  

Portanto, temos slaverye strengthretornamos 1 (já que ambos começam com a mesma letra), e nenhum retornando 2. Portanto, adicionamos 1for strength(é a única palavra que corresponderá /h/) e cada uma delas será mapeada para um índice de 0 a 5)


6

R, 86 87 92 Bytes

Alterado para uma função sem nome e gsubpara subpor alguns bytes. Os grepdetermina qual das cordas 3 é usado e a entrada é removida da cadeia com sub.

function(v)sub(v,'',(l=c("warpeace","freedomslavery","ignorancestrength"))[grep(v,l)])

5

PHP, 70 bytes

<?=[ignorance,peace,slavery,strength,freedom,war][md5("^$argv[1]")%7];

5

Befunge, 89 88 bytes

<>_00g1v2+%7~%2~"slavery"0"war"0"freedom"0"ignorance"0"strength"0"peace"
 |p00:-<
@>:#,_

Experimente online!

Explicação

Código fonte com caminhos de execução destacados

*Começamos colocando todas as seqüências de saída possíveis na pilha, terminadas em nulo. Essa sequência é executada da direita para a esquerda, para que os valores sejam pressionados ao contrário, pois essa é a ordem em que os caracteres serão necessários quando forem exibidos.
*Em seguida, lemos os dois primeiros caracteres do stdin, o que é tudo o que precisamos para identificar a string de entrada. Se pegarmos o valor ASCII da primeira letra mod 2, mais a segunda letra mod 7, obteremos um número único no intervalo de 2 a 7.

Input         ASCII      %2 %7   Sum
[fr]eedom     102 114    0  2    2
[pe]ace       112 101    0  3    3
[sl]avery     115 108    1  3    4
[st]rength    115 116    1  4    5
[ig]norance   105 103    1  5    6
[wa]r         119 97     1  6    7

*Esse número pode ser usado como um tipo de índice na lista de cadeias na pilha. Nós decrementamos iterativamente o índice (a primeira vez em 2) e, para cada iteração, limpamos uma sequência da pilha com a sequência >_.
*Quando o índice chega a zero, ficamos com a string de saída correta no topo da pilha, então usamos uma sequência simples de saída de string para gravar o resultado em stdout.


2
Eu gosto do uso de :-<e @>:#"smileys" aqui :)
— Tobias KIENZLER

5

Pyke, 29 bytes

.d⻌૽ɦڷࠛ⯤dci@1.^iR@

Experimente aqui!

.d⻌૽ɦڷࠛ⯤           -     "war peace freedom slavery ignorance strength"
         dc         -     ^.split(" ")
           i        -    i=^
            @       -   ^.find(input)
             1.^    -  ^ xor 1
                iR@ - input[^]

5

C, 93

A resposta de @ Arnauld foi portada para C

#define F(w)(char*[]){"freedom",0,"war",0,"strength",0,"slavery","peace","ignorance"}[w[1]%9]

4

C (gcc) , 113 108 bytes

f(char*s){char*t="5WAR\0+PEACE\09FREEDOM\0'SLAVERY\0;IGNORANCE\0%STRENGTH";while(strcmp(s,++t));puts(t+*--t-47);}

Todas as instâncias de \0 podem ser substituídas por bytes NUL reais para fins de pontuação.

t+*--t-47é um comportamento indefinido; isso pode / não irá funcionar com outros compiladores.

Experimente online!


4

JavaScript (ES6), 71 78

Tão chato que a resposta de Arnauld, mas mais curto também.

Agora eu adicionei a codificação com btoa. Na string codificada, existem 4 bytes que não posso postar neste site, mesmo que sejam caracteres válidos em uma string javascript. Então eu usei um escape hexadecimal no formulário\xHH . Cada uma dessas escapes é contada como 1 byte.

A cadeia codificada é strength0ignorance0peace0war0slavery0freedom

x=>(w=btoa`²ÚÞ\x9e\x0baÒ('¢¶§qí)y§\x1eÓ\x06«ÒÉZ½êòÑúÞyÚ&`.split(0))[w.indexOf(x)^1]

Este é 82 e não diferencia maiúsculas de minúsculas

x=>',,strength,,slavery,war,,,ignorance,peace,freedom'.split`,`[parseInt(x,36)%15]

Teste

F=
x=>(w=btoa`²ÚÞ\x9e\x0baÒ('¢¶§qí)y§\x1eÓ\x06«ÒÉZ½êòÑúÞyÚ&`.split(0))[w.indexOf(x)^1]

;['freedom','slavery','war','peace','ignorance','strength']
.forEach(w=>console.log(w + ' -> ' + F(w)))


3

CJam, 52 (apenas ASCII)

"/.|Mv
DO'y    EK{ {:nBct'Pt}d4sE"144b26b'af+'j/_ra#1^=

Experimente online

Nota: as coisas que parecem espaço são caracteres de tabulação (um antes e outro depois de "EK {")

Explicação:

A parte até "+" está descompactando a sequência "slaveryjfreedomjwarjpeacejignorancejstrength", usando a conversão base:
string (tratada como matriz de códigos de caracteres) → (base 144) número → (base 26) número → (base 26) matriz de números → (adicionando 'a' a cada número) sequência

'j/    split around 'j' characters
_      duplicate the resulting word array
ra     read the input and wrap in array
#      find the index of the input in the word array
1^     XOR with 1
=      get the word at the new index

3

> <> (Peixe), 84 78 bytes

0i~ia%.
v'raw'
>ol?!;
^'htgnerts'
^'yrevals'

^'ecnarongi'
^'ecaep'
^'modeerf'

Experimente online!

Começamos a nadar a partir do canto superior esquerdo, indo para a direita. Primeiro, carregamos a pilha com um 0. Em seguida, lemos a primeira letra da entrada ( i), descartamos ( ~), lemos a segunda letra ( i) e reduzimos seu valor ASCII módulo 10 (a% ). Isso mapeia a, e, r, l, ge t para 7, 1, 4, 8, 3 e 6, respectivamente - vamos chamar esse número N.. exibe dois valores da pilha - N e 0 - e salta para linha N, caractere 0.

Após um salto, o peixe prossegue um tiquetaque antes de executar as instruções, por isso ignora o primeiro caractere e nada pela linha N, que carrega a palavra correspondente na pilha. Finalmente, vamos para a linha 2, que gera toda a pilha e sai.

  • Economizei seis bytes usando um salto, em vez da auto-modificação legal do código que eu usei antes. Ah bem.

3

JavaScript, 78 bytes

w=>(a="war slavery ignorance strength freedom peace".split` `)[5-a.indexOf(w)]

Este é um tipo de porta da minha resposta Python . Armazenamos as palavras em uma sequência em que cada uma está na posição oposta à sua contraparte. Encontramos o índice da palavra dadaw e obtemos esse índice no final, para retornar o resultado.

Snippet de teste:

f = w=>(a="war slavery ignorance strength freedom peace".split` `)[5-a.indexOf(w)]

console.log(f("peace"))
console.log(f("ignorance"))
console.log(f("war"))


2

Pari / GP, 86 Byte

Pari / GP é um intérprete interativo, não precisamos de um "print" -cmd para a saída; no entanto, o utilitário Try-It_Online precisa de um "print" -cmd, então separei isso para o "rodapé".
Definimos uma "função-objeto" (a letra O me lembra muito a função Orwell ... ;-)):

x.O=s=[war,freedom,ignorance,strength,slavery,peace];for(k=1,6,if(x==s[k],i=7-k));s[i]

Depois disso, ligue

print(war.O)   \\ input to Pari/GP with the O-rwell-member of "war"
       peace   \\ output by Pari/GP

Experimente online!

(Observe que, no Pari / GP, os tokens fornecidos aqui não são cadeias, mas nomes de variáveis ​​legais! Essas variáveis ​​nunca devem ter nenhum valor atribuído)


2

Empilhados, 70 bytes

@x'war
strength
freedom
slavery
ignorance
peace'LF split:x index\rev\#

Experimente aqui! Recebe entrada na pilha e deixa a saída na pilha. Por exemplo:

'war'

@x'war
strength
freedom
slavery
ignorance
peace'LF split:x index\rev\#

out

Este código é bastante auto-explicativo. Ligeiramente modificado para executar todos os casos de teste:

('war' 'slavery' 'ignorance')
{x:'war
strength
freedom
slavery
ignorance
peace'LF split:x index\rev\#x\,}"!
disp

11
o que 'LFfaz?
— Downgoat

11
@Downgoat Bem, @xdefine uma variável, '...'é uma string, e LFé a variável de avanço de linha
— Conor O'Brien

11
Ah entendo, então o argumento da função vem antes do nome da função?
— Downgoat

11
@Downgoat Precisamente. Empilhado é, assim, baseado em pilha.
— Conor O'Brien

11
agora eu me sinto idiota por não perceber tal fato óbvio: |
— Downgoat

2

Jolf, 35 bytes

.γG"ΞΠΞ¦ΞpΞsΞΈΞ3I"-5 iγ

Existem muitos imprimíveis. Aqui está um hexdump, embora não faça muito bem:

00000000: 2ece b347 22ce 9e07 cea0 c28e ce9e 07c2  ...G"...........
00000010: 8ac2 a6ce 9e06 c28e 70ce 9e07 73c2 8fce  ........p...s...
00000020: 9e06 ce88 c280 ce9e 0133 4922 052d 3520  .........3I".-5
00000030: 69ce b3                                  i..

Aqui está um link online.

Basicamente, o código se parece com:

.γG"..."♣-5 iγ
  G"..."♣        split uncompressed string on spaces
 γ               set gamma to this
            iγ   index of the input in gamma
.γ       -5      and get 5 - this from gamma

2

Na verdade , 56 bytes

' "war peace freedom slavery ignorance strength"s;)í1^@E

Experimente online!

Infelizmente, sem nenhum componente de compactação, é mais curto não compactar a string e descompactá-la manualmente.

Explicação:

' "war peace freedom slavery ignorance strength"s;)í1^@E
' "war peace freedom slavery ignorance strength"s         split the string on spaces
                                                 ;)       make a copy, push it to the bottom of the stack
                                                   í      index of input in list
                                                    1^    XOR with 1
                                                      @E  that element in the list

2

Haskell, 104 111 bytes

data O=WAR|FREEDOM|IGNORANCE|PEACE|SLAVERY|STRENGTH deriving(Show,Enum)
f s=toEnum$mod(3+fromEnum s)6::O

Idéia:

  • Enumere as palavras-chave de modo que sua contraparte esteja a 3 posições
  • Pegue a palavra-chave, obtenha sua posição fromEnum, mova 3 etapas para a direita (módulo 6) e converta novamente para a palavra-chave
  • A ::Oé necessária porque a inferência de tipo tem alguns problemas. Dar fuma assinatura f :: O -> Oteria o mesmo efeito, mas não é tão curto.

Editar:

Substituído

f s=toEnum$mod(3+fromEnum s)6

por

f=toEnum.(`mod`6).(+3).fromEnum

graças a @Laikoni.


2
O uso da notação de ponto completo para fé mais curto:f s=toEnum$mod(3+fromEnum s)6
— Laikoni

2

Dyalog APL , 66 bytes

Qualquer um destes:

'slavery' 'freedom' 'ignorance' 'strength' 'war' 'peace'⊃⍨6|⎕UCS⊃⍞usa esse método (requer o ⎕IO←0padrão em muitos sistemas).

'strength' 'freedom' 'war' 'peace' 'slavery' 'ignorance'(⍳⊃(⌽⊣))⊂⍞ faz uma pesquisa e escolhe o elemento correspondente da lista invertida.


2

Qbasic, 138 99 bytes

D$="ignorancefreedom  peace    strength slavery  war      ":INPUT A$:?MID$(D$+D$,INSTR(D$,A$)+27,9)

D$armazena todas as palavras do lado esquerdo do mantra, depois todas as do lado direito. Cada palavra é preenchida com espaços para exatamente 9 letras por palavra. D$depois é anexado a si mesmo.

Em seguida, instré usado para encontrar o índice da palavra inserida pelo usuário. A outra parte do mantra é sempre armazenada exatamente 9 * 3 posições ainda mais na cadeia, por isso imprimimos uma substring começando nessa posição, tendo 9 caracteres.


2

SmileBASIC, 92 bytes

A$="PEACE
E$="WAR
R$="SLAVERY
L$="FREEDOM
G$="STRENGTH
T$="IGNORANCE
INPUT I$?VAR(I$[1]+"$")

2

Python , 80 bytes

De alguma forma superou o xnor!

Essa é uma função lambda sem nome, que retorna o resultado.

lambda w,a="war slavery ignorance strength freedom peace".split():a[~a.index(w)]

Experimente online!

A lista de palavras é organizada de modo que cada uma esteja na posição oposta à sua contraparte. Dada a palavra w, encontramos seu índice na lista de palavras e, em seguida, bit a bit NOT ( ~). Isso vira todos os bits, que são computadosn => -n-1 . Devido à indexação negativa do Python, obtém o índice oposto na lista.

Como uma espécie de bônus não intencional, você pode passar qualquer lista de palavras opostas para essa função como o segundo argumento.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.