“99 garrafas de fizz”


55

Desafio

Escreva um programa que produza a letra para 99 garrafas de cerveja, mas vez de "beer", "fizz" se o número de garrafas na parede for múltiplo de 3, "buzz" se for múltiplo de 5 e "fizzbuzz" se for múltiplo de 3 e múltiplo de 5. Se o número de garrafas na parede não for múltiplo de 3 ou 5, basta exibir "cerveja" como de costume.

Letra da música

99 bottles of fizz on the wall, 99 bottles of fizz.
Take one down and pass it around, 98 bottles of beer on the wall.

98 bottles of beer on the wall, 98 bottles of beer.
Take one down and pass it around, 97 bottles of beer on the wall.

97 bottles of beer on the wall, 97 bottles of beer.
Take one down and pass it around, 96 bottles of fizz on the wall.

96 bottles of fizz on the wall, 96 bottles of fizz.
Take one down and pass it around, 95 bottles of buzz on the wall.

95 bottles of buzz on the wall, 95 bottles of buzz.
Take one down and pass it around, 94 bottles of beer on the wall.

....

3 bottles of fizz on the wall, 3 bottles of fizz.
Take one down and pass it around, 2 bottles of beer on the wall.

2 bottles of beer on the wall, 2 bottles of beer.
Take one down and pass it around, 1 bottle of beer on the wall.

1 bottle of beer on the wall, 1 bottle of beer.
Go to the store and buy some more, 99 bottles of fizz on the wall.


Isso é , então a submissão mais curta em cada idioma vence.


30
Eu tenho 95 garrafas de fizz. Eu tiro uma. Agora eu tenho 94 garrafas de cerveja. Lógica.
Okx

2
Posso tomar uma garrafa de fizzbeer?
Stephen

11
Supõe-se que haja uma nova linha após a 3ª garrafa?
Kritixi Lithos

2
É necessária uma nova linha entre as duas linhas? Antes da edição de Kritixi Lithos, não havia nenhum e agora existe.
dzaima

11
@Okx Bem, a cerveja é efervescente e dá-lhe um zumbido ...
Draco18s

Respostas:


12

Python 2 , 263 253 245 bytes

i=99
x=''
while i:x+=', %s on the wall.\n\n%s on the wall, %s.\n'%(('%d bottle%s of %s'%(i,'s'*(i>1),(i%3<1)*'fizz'+(i%5<1)*'buzz'or'beer'),)*3)+'GToa kteo  otnhee  dsotwonr ea nadn dp absusy  isto maer omuonrde'[i>1::2];i-=1
print x[35:]+x[:33]

Experimente online!


Isso é incrível! Você pode explicar por que interpolar as strings é a opção mais curta?
Musicman523

2
Por exemplo, ['ab','cd'][x]pode ser reescrito como 'acbd'[x::2], apenas para salvar alguns bytes
Rod

7

C (GCC), 276 274 bytes

Obrigado a Neil por salvar dois bytes!

#define w" on the wall"
#define c(i)printf("%d bottle%s of %s",i,"s"+!~-i,i%3?i%5?"beer":"buzz":i%5?"fizz":"fizzbuzz"),printf(
i;f(){for(i=99;i;c((i?:99))w".\n\n"))c(i)w", "),c(i)".\n"),printf(--i?"Take one down and pass it around, ":"Go to the store and buy some more, ");}

Quem não ama parênteses incomparáveis ​​em expansões de macro?

Ungolfed:

#define c(i)                               \
    printf(                                \
        "%d bottle%s of %s",               \
        i,                   /* Number  */ \
        i-1 ? "s" : "",      /* Plural  */ \
        i % 3                /* FizzBuzz*/ \
            ? i % 5                        \
                ? "beer"                   \
                : "buzz"                   \
            : i % 5                        \
                ? "fizz"                   \
                : "fizzbuzz"               \
    )

i;
f() {
    for(i = 99; i; ) {
        c(i); printf(" on the wall, ");
        c(i); printf(".\n");
        printf(
            --i
                ? "Take one down and pass it around, "
                : "Go to the store and buy some more, "
        );

        // This has been stuffed into the for increment
        c((i?:99)); printf(" on the wall.\n\n");
    }
}

Veja ao vivo em Coliru!

Versão alternativa (276 bytes)

#define c(i)printf("%d bottle%s of %s",i,i-1?"s":"",i%3?i%5?"beer":"buzz":i%5?"fizz":"fizzbuzz"),printf(
i,*w=" on the wall";f(){for(i=99;i;c((i?:99))"%s.\n\n",w))c(i)"%s, ",w),c(i)".\n"),printf(--i?"Take one down and pass it around, ":"Go to the store and buy some more, ");}

Isso é super legal! Fico sempre chocado com o quão boas respostas C podem ser com a manipulação de strings.
Musicman523

Salve alguns bytes mudando #define w" on the wall"para *w=" on the wall".
MD XF

@MDXF mmh, recebo exatamente a mesma contagem de bytes. Estou esquecendo de algo?
Quentin

Eu acho que eles significavam que você pode substituir #define wpor *w=para salvar bytes lá. Honestamente, eu não conheço muito bem o C jogado no golfe, mas meu palpite é que ele gera wum caractere global * implicitamente definido.
Musicman523

4
@ musicman523 O problema é que #defined wé uma literal de string, que é automaticamente colada com literais de string adjacentes. Se wfor uma variável, eu tenho que usar a formatação de string real dentro printf.
Quentin

6

Röda , 273 bytes

f{a=`bottle`f=` on the wall`g=`99 ${a}s of fizz`;[`$g$f, $g.
`];seq 98,1|{|b|d=`s`d=``if[b=1];c=``c=`fizz`if[b%3=0];c.=`buzz`if[b%5=0];c=`beer`if[c=``];e=`$b $a$d of $c`;[`Take one down and pass it around, $e$f.

$e$f, $e.
`]}_;[`Go to the store and buy some more, $g$f.`]}

Experimente online!

Golf ainda mais pela manhã.


6

PHP, 242 bytes

function f($k){return"$k bottle".(s[$k<2])." of ".([fizz][$k%3].[buzz][$k%5]?:beer);}$w=" on the wall";for($b=f($c=99);$c;)echo"$b$w, $b.
",--$c?"Take one down and pass it around":"Go to the store and buy some more",", ",$b=f($c?:99),"$w.

";

Experimente online!

PHP, 244 bytes

for($e=s,$b=fizz,$c=99;$c;)echo strtr("301245, 30124.
6, 708295.

",[" bottle",$e," of ",$c,$b," on the wall",--$c?"Take one down and pass it around":"Go to the store and buy some more",$k=$c?:99,$e=s[2>$k],$b=[fizz][$k%3].[buzz][$k%5]?:beer]);

Experimente online!

use a função strtr

PHP, 245 bytes

$f=function($k)use(&$b){$b="$k bottle".(s[$k<2])." of ".([fizz][$k%3].[buzz][$k%5]?:beer);};for($w=" on the wall",$f($c=99);$c;)echo"$b$w, $b.
",--$c?"Take one down and pass it around":"Go to the store and buy some more",", {$f($c?:99)}$b$w.

";

Experimente online!

use uma função anônima na seqüência de caracteres para obter uma sustring, dependendo do número inteiro

Expandido

$f=function($k)use(&$b){$b="$k bottle".(s[$k<2])." of ".([fizz][$k%3].[buzz][$k%5]?:beer);};
for($w=" on the wall",$f($c=99);$c;)
echo"$b$w, $b.
",--$c?"Take one down and pass it around":"Go to the store and buy some more"
,", {$f($c?:99)}$b$w.

";

11
Se eu não miscount você pode salvar 2 bytes ( 250 bytes no total): function x($n){return"$n bottle".($n-1?s:'')." of ".(($n%3?'':fizz).($n%5?'':buzz)?:beer);}$y=" on the wall";for($b=99;$b;){$c=x($b);echo"$c$y, $c.↵",--$b?"Take one down and pass it around":"Go to the store and buy some more",", ".x($b?:99)."$y.↵↵";}. :)
insertusernamehere

11
@insertusernamehere Você fez uma contagem incorreta de algumas alterações, pois economiza mais 2 bytes. Obrigado. E você tem me dar uma pequena idéia de usar useem combinação com a função anônima que economiza 1 Byte nesta versão
Jörg Hülsermann

5

05AB1E , 151 146 143 bytes

99LRv'¬ž“fizzÒÖ“#y35SÖÏJ‚˜1(è©y“ƒ¶€µ„‹€ƒî倕…¡, ÿÏꀂ ÿ€‰€€íÒ.“ªõ®y“ÿÏꀂ ÿ€‰€€íÒ, “D#4£ðýs…ÿÿ.}‚‚˜'Ïê'±¥:`)¦¦¬#7£ðý¨“‚œ€„€€ƒï€ƒ‚¥€ä€£, ÿ.“ª)˜»

Experimente online!


4

SOGL , 136 135 134 133 133 131 bytes

Ƨ, o▓k
"πFT+╔¡‘oW
³³q"'bμ⁸‘oH? so}5\;3\«+"ΞQv↑χāσκN⌡κYT¡‘_,S─‘oθwoX▓
MH∫}¹±{▓WkƧ.¶oH¡"sΗ─χpēGķ¶¾3Ζ^9f.⅟▒E┌Fρ_╬a→‘KΘw⁽oXH‽M}HkW">⁸‘p

Primeiro de tudo, a terceira função:

                                    ▓  name this "▓" (example input: 15)                          [15]
³³                                     Create 4 extra copies of the top thing (number of things)  [15, 15, 15, 15, 15]
  q                                    output without popping one of them                         [15, 15, 15, 15, 15]
   "...‘o                              output " bottle"                                           [15, 15, 15, 15, 15]
         H?   }                        if pop-1 [isn't 0]                                         [15, 15, 15, 15]
            so                           output "s"                                               [15, 15, 15, 15]
               5\                      push if POP divides by 5                                   [15, 15, 15, 1]
                 ;                     swap [if divides & another number copy]                    [15, 15, 1, 15]
                  3\«                  push if POP divides by 3, multiplied by 2                  [15, 15, 1, 2]
                     +                 add those together                                         [15, 15, 3]
                      "...‘            push "buzz fizz fizzbuzz beer"                             [15, 15, 3, "buzz fizz fizzbuzz beer"]
                           ...‘o       output " of " (done over here to save a byte for a quote)  [15, 15, 3, "buzz fizz fizzbuzz beer"]
                                θ      split ["buzz fizz fizzbuzz beer"] on spaces                [15, 15, 3, ["buzz","fizz","fizzbuzz","beer"]]
                                 w     get the index (1-indexed, wrapping)                        [15, 15, ["buzz","fizz","fizzbuzz","beer"], "fizzbuzz"]
                                  o    output that string                                         [15, 15, ["buzz","fizz","fizzbuzz","beer"]]
                                   X   pop the array off of the stack                             [15, 15]

A primeira função:

Ƨ, o▓k
     k  name this "function" "k"
Ƨ, o    output ", "
    ▓   execute the "bottleify" function

A segunda função:

"πFT+╔¡‘oW
         W  call this "W"
"πFT+╔¡‘    push " on the wall"
        o   output it

E a parte principal:

MH∫}                                     repeat 99 times, each time pushing index
    ¹                                    wrap in an array
     ±                                   reverse it
      {                                  iterate over it
       ▓                                 execute that function
        W                                execute that function
         k                               execute that function
          Ƨ.¶o                           output ".\n"
              H¡                         push if POP-1 isn't 0 (aka 1 if pop <> 1, 0 if pop == 1)
                "...‘                    push "Stake one down and pass it aroundSgo to the store and buy some more"
                     K                   push the first letter of that string
                      Θ                  split ["take one down and pass it aroundSgo to the store and buy some more" with "S"]
                       w                 gets the xth (1-indexed, wrapping) item of that array
                        ⁽o               uppercase the 1st letter and output
                          X              pop the array off
                           H‽            if pop-1 [isn't 0]
                             M           push 100
                              }          ENDIF
                               H         decrease POP
                                k        execute that function
                                 W       execute that function
                                  ">⁸‘p  output ".\n\n"

Perdeu alguns bytes devido a um erro que Ocoloca uma nova linha antes e depois dela (e de alguma forma isso remonta à V0.9 (este é o código V0.11))


4

Java, 344 340 339 bytes

(-4 bytes após o efervescimento do golfe; -1 byte removendo o espaço em branco perdido)

interface X{static void main(String[]a){for(int i=99;i>0;System.out.printf("%s on the wall, %s.%n%s, %s on the wall.%n%n",b(i),b(i--),i<1?"Go to the store and buy some more":"Take one down and pass it around",b(i<1?99:i)));}static String b(int i){return i+" bottle"+(i>1?"s":"")+" of "+(i%3<1?"fizz":"")+(i%5<1?"buzz":i%3<1?"":"beer");}}

Um pouco sem golfe (usando recuo de 1 espaço para eliminar a rolagem horizontal):

interface X {
 static void main(String[]a){
  for(int i=99;i>0;System.out.printf("%s on the wall, %s.%n%s, %s on the wall.%n%n",
   b(i),b(i--),
   i<1?"Go to the store and buy some more":"Take one down and pass it around",
   b(i<1?99:i)));
 }
 static String b(int i){
  return i+" bottle"+(i>1?"s":"")+" of "+(i%3<1?"fizz":"")+(i%5<1?"buzz":i%3<1?"":"beer");
 }
}

4

JavaScript (ES6), 316 309 bytes

Este é um programa completo e não uma função. Nada muito criativo, é apenas a abordagem ingênua (daí o número de bytes!). Estou usando, em console.log()vez de, alert()porque muitos navegadores têm limite no número de caracteres que podem ser exibidos usandoalert() . Observe que todos os espaços em branco e novas linhas são necessários.

a="";for(i=99;i>0;i--){b=j=>"bottle"+(j>1?"s":"");d=a=>(a%3?"":"fizz")+(a%5?"":"buzz")||"beer");w=" on the wall";o=" of ";a+=`${i+" "+b(i)+o+d(i)+w+", "+i+" "+b(i)+o+d(i)}.
${i>1?"Take one down and pass it around, ":"Go to the store and buy some more, "}${(y=i-1?i-1:99)+" "+b(y)+o+d(y)+w}.

`;}console.log(a)

Ungolfed:

let accumulator = "";
for(let i = 99; i>0; i--){
    let bottleString = j => "bottle"+(j>1?"s":""),
    drink = a =>(a%3?"":"fizz")+(a%5?"":"buzz")||"beer",
    wallString = " on the wall",
    of=" of ";
    accumulator += `${i+" "+bottleString(i)+of+drink(i)+wallString+", "+i+" "+bottleString(i)+of+drink(i)}.
${i>1?"Take one down and pass it around, ":"Go to the store and buy some more, "}${(y=i-1?i-1:99)+" "+bottleString(y)+of+drink(y)+wallString}.

`;
}

console.log(accumulator);

Aqui está o trecho:

a="";for(i=99;i>0;i--){b=j=>"bottle"+(j>1?"s":"");d=a=>(a%3?"":"fizz")+(a%5?"":"buzz")||"beer";w=" on the wall";o=" of ";a+=`${i+" "+b(i)+o+d(i)+w+", "+i+" "+b(i)+o+d(i)}.
${i>1?"Take one down and pass it around, ":"Go to the store and buy some more, "}${(y=i-1?i-1:99)+" "+b(y)+o+d(y)+w}.

`;}console.log(a)

BTW, com esta resposta, ganhei o distintivo de bronze no ! Nunca pensei que fosse conseguir isso nunca (embora não seja uma grande conquista)!


Sua dfunção não precisa de nenhum ()s porque ?:é associativa à direita, mas você pode realmente salvar ainda mais bytes usando d=a=>(a%3?"":"fizz")+(a%5?"":"buzz")||"beer".
Neil

3

Retina , 230 bytes


99$*_
_\B
Take one down and pass it around, $.'#.¶¶$.'#, $.'.¶
^
99#, 99.¶
_
Go to the store and buy some more, 99#.
#
 on the wall
1\b|(\d+)
$& bottle$#1$*s of $&$*_
\b(_{15})+\b
fizzbuzz
\b(_{5})+\b
buzz
\b(___)+\b
fizz
_+
beer

Experimente online! Explicação:


99$*_

Inserções 99 _s.

_\B
Take one down and pass it around, $.'#.¶¶$.'#, $.'.¶

Altera todos, exceto o último, _para a sequência Take one down and pass it around, $.'#.¶¶$.'#, $.'.¶, onde há uma nova linha e $.'é a contagem de sublinhados restantes. Isso efetivamente conta de 98 para 1.

^
99#, 99.¶

Adiciona a primeira linha do primeiro verso no formato "compacto".

_
Go to the store and buy some more, 99#.

Adiciona a segunda linha do último verso. Por que eu preciso pular os bastidores para usar o que _eu não sei, mas $parece combinar duas vezes, então não posso usar isso. Vai saber.

#
 on the wall

Substitui uma corda que aparece várias vezes no verso.

1\b|(\d+)
$& bottle$#1$*s of $&$*_

Isso corresponde aos números inteiros nos versículos, e sufoca a (s) garrafa (s) apropriada (s) e expande novamente para unário novamente, em preparação para escolher a bebida. (Economizo 1 byte no 99s dessa maneira.)

\b(_{15})+\b
fizzbuzz
\b(_{5})+\b
buzz
\b(___)+\b
fizz
_+
beer

Substitua múltiplos exatos pela bebida apropriada.


2

sed , 468 459 456 bytes

s:^:99 bottles of fizz on the wall, 99 bottles of fizz.:
p
s:99:I8:g
s:fizz:XYYZ:g
x
s:^:Take one down and pass it around, I8 bottles of XYYZ on the wall.\n:
G
x
:
g
s:XXX:fizz:g
s:Y{5}:buzz:g
s:\bX*Y*Z:beer:g
s:[XYZ]::g
y:ABCDEFGHI:123456789:
s:\b0::g
/ 1 /bq
p
x
s:^::
tc
:c
s:(\S)0:\1@:g
Td
y:ABCDEFGHI:0ABCDEFGH:
:d
y:123456789@:0123456789:
s:(XXX)*(Y{5})*(Y*Z):XY\3:g
x
b
:q
s:es:e:g
aGo to the store and buy some more, 99 bottles of fizz on the wall.

Experimente online!

Requer -r sinalizador.

Explicação

Espaço preensão segura o padrão de duas linhas de repetição, com números representados como [A-I][0-9](dígitos separadas para dezenas e unidades) e o tipo de bebida, como representado X*Y*Z, onde Xmantém um registo de -N mod 3, e Yde-N mod 5 .

Em cada iteração posterior, os números se diminuído e os Xs e Ys são atualizados. Em seguida, o espaço de espera é copiado para o espaço do padrão, transformado em linhas da música e impresso.


2

C, 349 345 344 bytes

#define b(x)x^1?" bottles":" bottle"
#define g i-1?"Take one down and pass it around":"Go to the store and buy some more"
*w=" on the wall";*s(x){return x?x%15?x%5?x%3?"beer":"fizz":"buzz":"fizzbuzz":"fizz";}i=100;main(){while(--i){printf("%d%s of %s%s, %d%s of %s.\n%s, %d%s of %s%s.\n",i,b(i),s(i),w,i,b(i),s(i),g,i-1?i-1:99,b(i-1),s(i-1),w);}}

Bem, lá vai você. Isso levou uma hora.

Experimente online!


2

Javascript (ES6), 236 234 233 232 bytes

for(i=99;i;console.log(z()+`, ${z(_)}.
${--i?'Take one down and pass it around':'Go to the store and buy some more'}, ${z()}.

`))z=(o=' on the wall',j=i||99)=>j+` bottle${j>1?'s':_} of `+((j%3?_:'fizz')+(j%5?_='':'buzz')||'beer')+o

Demo

// replace console.log to avoid 50-log limit in snippets:
console.log=_=>document.write(`<pre>${_}</pre>`)

for(i=99;i;console.log(z()+`, ${z(_)}.
${--i?'Take one down and pass it around':'Go to the store and buy some more'}, ${z()}.

`))z=(o=' on the wall',j=i||99)=>j+` bottle${j>1?'s':_} of `+((j%3?_:'fizz')+(j%5?_='':'buzz')||'beer')+o

Ungolfed

i = 99  // start counter at 99

z = (   // define function z which takes arguments with defaults:
   o = ' on the wall', // o = defaults to ' on the wall'
   j = i || 99         // j = defaults to value of counter i - or 99 when i == 0
) => 
    j +                 // our current j counter
    ' bottle' +
    (j > 1 ? 's' : _) + // choose 's' when we have more than 1 bottle, or blank _
    (
        (j % 3 ? _ : 'fizz') +      // if j % 3 is 0, add 'fizz', otherwise blank _
        (j % 5 ? _ = '' : 'buzz')   // if j % 5 is 0, add 'buzz', otherwise blank _
                                    // _ gets defined here since it's the first place it's used
            ||                      // if no fizz or buzz, result is a falsey empty string
        'beer'                      // replace falsey value with 'beer'
    ) +
    o                               // append o

while (i) {         // while counter is non-zero
    console.log(    // output string:
        z() +       // call z without o argument
        ', ' +
        z(_) +      // call z with blank _ for o to block ' on the wall' here
        '.\n' +
        ( --i       // decrement i, if still non-zero:
            ? 'Take one down and pass it around'
                    // otherwise:
            : 'Go to the store and buy some more'
        ) + 
        ', ' +
        z() +       // another call to z without o
        '.\n\n'
    )
}

1

Ruby , 261 bytes

99.downto(1){|i|w=' on the wall'
f=->x{a='';x%3<1&&a+='fizz';x%5<1&&a+='buzz';a<?a&&a='beer';"%d bottle%s of %s"%[x,x<2?'':?s,a]}
puts [f[i]+w,f[i]+?.+$/+(i<2?'Take one down and pass it around':'Go to the store and buy some more'),f[i<2?99:i-1]+w+?.+$/*2]*', '}

Experimente online!


1

shortC , 314 312 bytes

Db(x)x^1?" bottles":" bottle"
Dg i-1?"Take one down and pass it around":"Go to the store and buy some more"
*w=" on the wall";*s(x){Tx?x%15?x%5?x%3?"beer":"fizz":"buzz":"fizzbuzz":"fizz";}i=100;AW--i){R"%d%s of %s%s, %d%s of %s.\n%s, %d%s of %s%s.\n",i,b(i),s(i),w,i,b(i),s(i),g,i-1?i-1:99,b(i-1),s(i-1),w

Desculpe, não há explicação, mas esqueci completamente como isso funciona.


Você deve adicionar outra resposta, em suma, C, que siga a lógica dessa resposta, para ver como ela é importante. Além disso, parece que em ambas as suas respostas você só pode usar a sua macro para g uma vez, você deve ser capaz de inline e economizar alguns bytes
musicman523

Você pode postar a versão expandida?
CalculatorFeline

@CalculatorFeline O código C equivalente já está aqui , se é isso que você está pedindo
musicman523

1

Carvão , 307 297 bytes

A”|‽2?{:×G↗”¦αA“6«eMηOU¶¿”¦ζA“9“e▷·gqε-g}”¦βA“9B{⦃⁺Bφ=;λO”¦ωAfizz¦φAbuzz¦γAbeer¦ηA”↶C▶▶d℅d¬r·US\λTθNevT◧→GM⁸ω┦τA“M↧k↓⁺*f÷,ψZ¢▶\¿|P“№κ×υpξXoW”¦σA.¶πF⮌…¹¦¹⁰⁰«A⎇⁻ι¹αζθ¿∧¬﹪鳬﹪ι⁵A⁺φγ﹪ι³Aφ﹪ι⁵AγεAηε⁺⁺⁺⁺⁺⁺⁺IιθεβIιθεπ¿⁻ι¹A⁻ι¹λA⁹⁹λA⎇⁻λ¹αζθ¿∧¬﹪볬﹪λ⁵A⁺φγ﹪λ³Aφ﹪λ⁵AγεAηε¿⁻ι¹AτδAσδ⁺⁺⁺⁺δλθεω

Experimente online!

SIM, NÓS PODEMOS! Link para a versão detalhada, isso pode ser muito praticado, tenho certeza.


Infelizmente você se esqueceu de realmente fazer o link com o detalhado versão, mas que funcionam de s parece suspeito ...
Neil

1

tcl, 298

proc B i {set x " bottle[expr $i>1?"s":""] of [expr $i%3?$i%5?"beer":"":"fizz"][expr $i%5?"":"buzz"]"}
set i 99
time {puts "$i[B $i][set w " on the wall"], $i[B $i].
Take one down and pass it around, [incr i -1][B $i]$w."} 98
puts "1[B $i]$w, 1[B $i].
Go to the store and buy some more, 99[B 9]$w."

demonstração

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.