Kisi kode seni ASCII golf


19

Tantangan

Buat program terpendek yang memenuhi persyaratan

Persyaratan

  1. Kode harus menghasilkan kisi 0s 5x5, seperti:

    00000
    00000
    00000
    00000
    00000
    
  2. Kode harus menerima input (kolom, baris, karakter). Kisi harus berubah sesuai:

    Mulailah:

    00000
    00000
    00000
    00000
    00000
    

    Memasukkan:

    (2,5,*)
    

    Keluaran:

    0*000
    00000
    00000
    00000
    00000
    

    (Catatan: sudut kiri bawah adalah posisi 1,1.)

  3. Program harus mengembalikan pesan kesalahan selain dari kisi jika input baris / kolom bukan 1,2,3,4, atau 5. Ini bisa berupa pesan pilihan Anda (asalkan bukan kisi), begitu 0juga output kesalahan yang dapat diterima.

  4. Program harus bekerja dengan semua karakter ASCII yang dapat dicetak (dari keyboard AS).

PEMENANG

Pemenangnya adalah orang yang memiliki kode terpendek dan memenuhi semua persyaratan. Jika lebih dari satu jawaban berfungsi dan memiliki panjang (terpendek) yang sama, orang yang menjawab pertama akan menjadi pemenang.


8
Program harus mengembalikan pesan kesalahan . Pesan kesalahan apa? Bisakah program kembali 0untuk kesalahan dan grid untuk sukses?
Rod

1
Di mana asal pada matriks? apakah harus nol atau satu diindeks?
george

3
Selamat datang di PPCG.
Erik the Outgolfer

4
Program harus bekerja dengan semua karakter di keyboard AS. Mengapa tidak hanya ASCII? Saya bahkan tidak tahu karakter papan ketik AS, dan itu tidak menambah tantangan
Luis Mendo

1
@LuisMendo Saya pikir keyboard AS adalah ASCII, atau setidaknya subset.
Conor O'Brien

Jawaban:


11

Dyalog APL , 17 13 10 byte

Meminta array tertutup yang berisi (baris, kolom) dan kemudian untuk karakter. Memberikan KESALAHAN INDEKS pada input yang salah.

⊖⍞@⎕⊢5 50

Cobalah online!

 flip terbalik hasil

 karakter yang diinput

@ mengganti konten di posisi

 input yang dievaluasi (baris, kolom tertutup)

 dari

5 5⍴ 5 × 5 array

0 nol


Apakah perlu? Saya pikir dalam hal ini berlebihan.
Conor O'Brien

1
@ ConorO'Brien @ ConorO'Brien jika tidak ada, pengurai melihat (⊂⎕)5 5sebagai array 3-elemen tunggal - argumen untuk .
Adám

Itu adalah 13 karakter Unicode, bukan 13 byte, bukan?
wilx

1
@wilx Klik pada kata byte !
Adám

Jawaban ini adalah pemenangnya.
Dave Jones

5

Ruby, 157 149 byte

g=(1..5).map{[0]*5}
loop{puts g.map(&:join).join ?\n
x=gets.match /\((.),(.),(.)\)/
a,b=x[1].hex,x[2].hex
1/0 if a<1||a>5||b<1||b>5
g[5-b][a-1]=x[3]}

Kesalahan pada input yang salah atau keluar dari posisi terikat

Terima kasih kepada ConorO'Brien (8 byte) dan afuous (2 byte) untuk membantu menghemat byte


loop do...end-> loop{...}; Saya pikir Array.new(5,[0]*5)berhasil juga, atau bahkan [*[0]*5]*5.
Conor O'Brien

@ ConorO'Brien Nope, Array.new(5,[0]*5)buat array referensi dan [*[0]*5]*5buat array datar
TuxCrafting

Oh benar Abaikan yang pertama *. Maka itu masih menciptakan berbagai referensi.
Conor O'Brien

Array.new(5){[0]*5}dapat diganti dengan (1..5).map{[0]*5}untuk menghemat 2 byte.
Berlangsung

4

Batch, 199 byte

@echo off
if %1 gtr 0 if %1 lss 6 if %2 gtr 0 if %2 lss 6 goto g
if
:g
for /l %%j in (5,1,-1)do call:l %* %%j
exit/b
:l
set s=000000
if %2==%2 call set s=%%s:~0,%1%%%3%%s:~%1%%
echo %s:~1,5%

Kesalahan keluar jika posisinya di luar jangkauan.


Saya pikir Anda dapat menggunakan simbol untuk <, seperti ^<. tidak yakin.
Conor O'Brien

3

PHP, 111 100 97 byte

$s=str_repeat("00000\n",5);$s[($x=($a=$argv)[1])+29-6*$y=$a[2]]=$a[3];echo$x&&$y&&$x<6&$y<6?$s:E;

mencetak Ejika baris / kolom di luar jangkauan.
Jalankan denganphp -r <code> <row> <column> <character>


3

Python, 66 byte

lambda a,b,n,l='00000\n':6>b>0<a<6and(5-b)*l+l[:a-1]+n+l[a:]+~-b*l

Tidakkah ini gagal untuk a = 4, b = 3?
Titus

@Titus tidak lagi; D
Rod

1
Solusi juga berfungsi untuk Python3
george

3

Dyalog APL, 24 20 18 byte

Disimpan 4 byte berkat Zgarb! Disimpan 2 byte berkat Adam!

a←5 5⍴0⋄a[⊂⎕]←⍞⋄⊖a

Anjuran untuk input. Lihat di bawah untuk penjelasan.


20 byte

{a←5 5⍴0⋄a[⊂⍺]←⍵⋄⊖a}

Tetapkan ke suatu fungsi dan panggil saja y x f 'c'. Misalnya:

      f←{a←5 5⍴0⋄a[⊂⍺]←⍵⋄⊖a}

      5 2 f '*'
0 * 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0

      6 6 f '*'
INDEX ERROR                   
     ←{a←5 5⍴0 ⋄ a[⊂⍺]←⍵ ⋄ ⊖a}
               ∧              

      0 0 f '*'
INDEX ERROR                   
     ←{a←5 5⍴0 ⋄ a[⊂⍺]←⍵ ⋄ ⊖a}
               ∧   

Penjelasan

{a←5 5⍴0⋄a[⊂⍺]←⍵⋄⊖a}

{...}adalah fungsi dengan argumen kiri dan argumen kanan . memisahkan pernyataan, jadi ada tiga pernyataan:

a←5 5⍴0⋄a[⊂⍺]←⍵⋄⊖a

Pernyataan pertama a←5 5⍴0diatur ake 5oleh 5kotak 0s.

Pernyataan kedua menetapkan anggota pada koordinat yang ditentukan oleh ke (yaitu, karakter).

Akhirnya, kita melakukan pada adan kembali itu, menghasilkan pengalaman pertama dari aterbalik.


{a←5 5⍴0⋄a[⊂⌽⍺]←⍵⋄⊖a}menghemat beberapa byte.
Zgarb

@ Zgarb Oh, fantastis! Saya tidak tahu pengindeksan bekerja seperti itu.
Conor O'Brien

Anda dapat menyimpan dua byte dengan mengonversi ke tubuh tradfn:a←5 5⍴0⋄a[⊂⎕]←⍞⋄⊖a
Adám

@ Adam bagaimana cara kerjanya? Tampaknya tidak berfungsi di TryAPL.
Conor O'Brien

@ Conor'Brien Benar. TryAPL melarang meminta input, tetapi Anda bisa mendapatkan versi lengkap secara gratis.
Adám

3

JavaScript (ES6), 73 76 byte

Melempar TypeErrorjika kolom atau baris di luar jangkauan.

(c,r,C,a=[...`00000
`.repeat(5)])=>(a[29+c-r*6]=C,c<1|r<1|c>5|r>5||a).join``

Demo


Manis, tetapi apakah ada kesalahan jika salah satu catau rkurang dari 1?
Produksi ETH

@ ETHproductions Ini hanya pengujian c == 0 || r == 0. Tapi saya kira Anda benar: Saya akan memperbaruinya untuk mencegah nilai negatif.
Arnauld

3

C #, 199 Bytes

Berdasarkan jawaban Pete Arden

string g(int c, int r, char a){if(c<1|c>5|r<1|r>5)return "Index Error";var b="00000";var d=new[]{b,b,b,b,b};c--;d[r-1]=new string('0',c)+a+new string('0',4-c);return string.Join("\r\n",d.Reverse());}

Tidak Disatukan:

public static string G(int c, int r, char a)
    {
        if (c < 1 || c > 5 || r < 1 || r > 5) return "Index Error"; // Check it's not out of range
        var b = "00000";
        var d = new [] { b, b, b, b, b };                           // Generate display box, and fill with the default character
        c--;                                                        // Convert the X to a 0 based index
        d[r - 1] = new string('0',c) + a + new string('0',4-c);     // Replace the array's entry in y coordinate with a new string containing the new character
        return string.Join("\r\n", d.Reverse());                    // Reverse the array (so it's the right way up), then convert to a single string
    }

Selamat datang di situs ini! Saya bukan ahli C #, tetapi sepertinya ada beberapa spasi yang bisa Anda hapus.
DJMcMayhem

1
(Maaf, tidak tahu etiket kiriman) G Pendek (): public static string G (int c, int r, char a) {return (0 <c && c <6 && 0 <r && r <6)? String.Compat (Enumerable.Range (1,29) .Pilih (i => i% 6> 0? I / 6 == 5-r && i% 6 == c? A: '0': '\ n')): "Kesalahan Indeks";}
Eric

2

05AB1E , 27 22 byte

Tidak mengembalikan kisi ketika baris / kolom> 5.

‚6‹Pi25L²<5*¹+Q5äR»1³‡

Cobalah online!

Versi sebelumnya

‚6‹Pi26G¾5²<*¹+NQi\³}})5äR»

2

Jelly , 28 byte

Ini terasa terlalu lama ...

Ṫ0ẋ24¤;ṙÑs5UY
’ḅ5
Ṗḟ5R¤
-ÑÇ?

TryItOnline!

Bagaimana?

Ṫ0ẋ24¤;ṙÑs5UY - Link 1, make grid: [row, column, character] e.g. [5,2,'*']
Ṫ             - tail: character                                  '*'
     ¤        - nilad followed by link(s) as a nilad  
 0            -     zero
  ẋ           -     repeated
   24         -     24 times                                     [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
      ;       - concatenate:                                     "000000000000000000000000*"
        Ñ     - call next link (2) as a monad                    21
       ṙ      - rotate left by                                   "000*000000000000000000000"
         s5   - split into chunks of length 5                    ["000*0","00000","00000","00000","00000"]
           U  - upend (reveres each)                             ["0*000","00000","00000","00000","00000"]
            Y - join with line feeds                              0*000
              - implicit print                                    00000
                                                                  00000
’ḅ5 - Link 2, position: [row, column]                             00000
’   - decrement                                                   00000
 ḅ5 - convert from base 5

Ṗḟ5R¤ - Link 3, input error checking: [row, column, character]
Ṗ     - pop: [row, column]
 ḟ    - filter out values in
  5R¤ - range(5): [1,2,3,4,5] - any values not in this remain giving a truthy result

-ÑÇ? - Main link: [row, column, character]
   ? - ternary if:
  Ç  -    last link (3) as a monad
-    -    -1 (if truthy - the error identification)
 Ñ   - next link (1) as a monad (if falsey - the grid)

2

JavaScript (ES6), 89 byte

f=(X,Y,Z,x=5,y=5)=>x+y>1?(x?X+x-6|Y-y?0:Z:`
`)+f(X,Y,Z,x?x-1:5,y-!x):X<1|X>5|Y<1|Y>5?e:""

Karena saya suka rekursi. Melempar ReferenceErrorpada koordinat yang tidak valid.


2

Mathematica, 38 byte

(x=Table[0,5,5];x[[-#2,#]]=#3;Grid@x)&

2

Brain-Flak 415 Bytes

Termasuk +3 untuk -c

([][()()()]){{}}{}({}<(({}<(({})<>)<>>)<>)<>([((((()()()){}){}){}){}]{}<([((((()()()){}){}){}){}]{})>)(()()()()()){({}[()]<(({})){{}(<({}[()])>)}{}({}<(({})){{}(<({}[()])>)}{}>)>)}{}({}{}){<>{{}}<>{}}<>>)<>(()()()()()){({}[()]<(((((((((()()()){}){}){}){})))))((()()()()()){})>)}{}{}<>({}<()((((((()()()){}){}()){}){}()[{}])({})({})({})({}){}{}[((((()()()){}){}){}){}()]){({}[()]<<>({}<>)>)}{}<>{}>)<>{({}<>)<>}<>

Cobalah secara Online!

Membawa karakter untuk disisipkan terlebih dahulu, lalu baris lalu kolom tanpa spasi.

Sebagian besar ini hanya penanganan kesalahan. Brain-Flak tidak memiliki cara yang baik untuk memeriksa apakah nilainya berada dalam kisaran. Untuk kesalahan, itu tidak menghasilkan apa-apa, atau hanya karakter yang seharusnya dimasukkan. Memecahkan masalah sebenarnya hanya membutuhkan 211 byte:

<>(()()()()()){({}[()]<(((((((((()()()){}){}){}){})))))((()()()()()){})>)}{}{}<>({}<()((((((()()()){}){}()){}){}()[{}])({})({})({})({}){}{}[((((()()()){}){}){}){}()]){({}[()]<<>({}<>)>)}{}<>{}>)<>{({}<>)<>}<>

2

Excel VBA, 67 Bytes

Output ke kisaran A1: E5 pada lembar aktif dari proyek vba, keluar bersama

Kesalahan run-time '1004':

Kesalahan yang ditentukan aplikasi atau yang ditentukan objek

ketika input yang tidak valid diberikan.

Kode:

Sub a(c,r,x)
c=IIf(r<1Or c>5,-1,c)
[A1:E5]=0
Cells(6-r,c)=x
End Sub

Pemakaian:

a 4,5,"#"

Output (dari contoh di atas) :

    A   B   C   D   E
1   0   0   0   #   0
2   0   0   0   0   0
3   0   0   0   0   0
4   0   0   0   0   0
5   0   0   0   0   0

1

C #, 208 Bytes

Golf:

string G(int c,int r,char a){if(c<1||c>5||r<1||r>5)return"Index Error";var b="00000";var d=new string[]{b,b,b,b,b};d[r-1]=d[r-1].Substring(0,c-1)+a+d[r-1].Substring(c);return string.Join("\r\n",d.Reverse());}

Tidak Disatukan:

public string G(int c, int r, char a)
{
  if (c < 1 || c > 5 || r < 1 || r > 5) return "Index Error";
  var b = "00000";
  var d = new string[] { b, b, b, b, b };
  d[r - 1] = d[r - 1].Substring(0, c - 1) + a + d[r - 1].Substring(c);
  return string.Join("\r\n", d.Reverse());
}

Pengujian:

Console.Write(G(6, 6, '*')); //Index Error

Console.Write(G(1, 4, '#'));

00000
#0000
00000
00000
00000

Console.Write(G(5, 5, '@'));

0000@
00000
00000
00000
00000

Console.Write(G(1, 1, '}'));

00000
00000
00000
00000
}0000

Jika cdan / atau di rluar batas itu akan melempar IndexOutOfRangeExceptionsehingga Anda mungkin dapat menghapus pernyataan if pertama meskipun saya belum memeriksa spesifikasi dengan benar untuk itu. Anda dapat mengkompilasi ke Func<int, int, char, string>untuk menyimpan byte, saya percaya Anda perlu menambahkan using System.Linq;karena Reversepanggilan meskipun saya tidak ingat dari atas kepala saya
TheLethalCoder

Ubah d[r - 1] = d[r - 1].Substring(0, c - 1) + a + d[r - 1].Substring(c);untuk d[--r] = d[r].Substring(0, c - 1) + a + d[r].Substring(c);menyimpan 4 byte
TheLethalCoder

1

WinDbg, 95 byte

j(0<(@$t0|@$t1))&(6>@$t0)&(6>@$t1)'f8<<16 L19 30;eb2000018+@$t0-@$t1*5 @$t2;da/c5 8<<16 L19';?0

Hampir setengah dari itu hanya memverifikasi indeks berada di kisaran ... Input dilakukan dengan menetapkan psuedo-register $t0, $t1dan $t2(di mana $t2memegang nilai ascii char untuk menggantikan). Misalnya, (2,5,*)seperti contohnya adalah:

0:000> r$t0=2
0:000> r$t1=5
0:000> r$t2=2a

Mencetak 0pada kesalahan.

Bagaimana itu bekerja:

j (0<(@$t0|@$t1)) & (6>@$t0) & (6>@$t1)  * If $t0 and $t1 are both positive and less than 6
'
    f 8<<16 L19 30;                      * Put 19 (0n25) '0's (ascii 30) at 2000000 (8<<16)
    eb 2000018+@$t0-@$t1*5 @$t2;         * Replace the specified cell with the new char
    da /c5 8<<16 L19                     * Print 19 (0n25) chars in rows of length 5
';
    ?0                                   * ...Else print 0

Output sampel:

0:000> r$t0=2
0:000> r$t1=5
0:000> r$t2=2a
0:000> j(0<(@$t0|@$t1))&(6>@$t0)&(6>@$t1)'f8<<16 L19 30;eb2000018+@$t0-@$t1*5 @$t2;da/c5 8<<16 L19';?0
Filled 0x19 bytes
02000000  "0*000"
02000005  "00000"
0200000a  "00000"
0200000f  "00000"
02000014  "00000"


0:000> r$t0=-2
0:000> j(0<(@$t0|@$t1))&(6>@$t0)&(6>@$t1)'f8<<16 L19 30;eb2000018+@$t0-@$t1*5 @$t2;da/c5 8<<16 L19';?0
Evaluate expression: 0 = 00000000


0:000> r$t0=4
0:000> r$t1=2
0:000> r$t2=23
0:000> j(0<(@$t0|@$t1))&(6>@$t0)&(6>@$t1)'f8<<16 L19 30;eb2000018+@$t0-@$t1*5 @$t2;da/c5 8<<16 L19';?0
Filled 0x19 bytes
02000000  "00000"
02000005  "00000"
0200000a  "00000"
0200000f  "000#0"
02000014  "00000"


0:000> r$t1=f
0:000> j(0<(@$t0|@$t1))&(6>@$t0)&(6>@$t1)'f8<<16 L19 30;eb2000018+@$t0-@$t1*5 @$t2;da/c5 8<<16 L19';?0
Evaluate expression: 0 = 00000000

1

Haskell, 77 byte

r=[1..5]
(x#y)c|x>0,x<6,y>0,y<6=unlines[[last$'0':[c|i==x,j==6-y]|i<-r]|j<-r]

Contoh penggunaan:

*Main> putStr $ (2#5) '*'
0*000
00000
00000
00000
00000

Jika xdan yberada dalam jangkauan, loop luar dan dalam [1..5]dan ambil char cjika menyentuh diberikan xdan ydan 0sebaliknya. Jika xatau ytidak dalam jangkauan, Non-exhaustive patternspengecualian dimunculkan.


1

Oktaf 49 byte

@(c,r,s)char(accumarray([6-r c],s+0,[5 5],[],48))

1

QBIC , 53 50 byte

EDIT: Sekarang saya tahu bahwa saya tidak harus menunjukkan grid mulai, saya sudah menukar input pengguna _!_!_?untuk parameter baris perintah ::;, menghemat 3 byte.

[5|?@00000|]::;~(b>5)+(c>5)>1|_Xd\$LOCATE 6-c,b|?B

Versi asli: Ini berhenti antara mencetak 0-grid dan mengambil koordinat untuk substitusi, menunjukkan 0-grid.

[5|?@00000|]_!_!_?~(b>5)+(c>5)>1|_Xd\$LOCATE 6-c,b|?B

Mencetak 5 string 5 0's, meminta pengguna untuk 2 input numerik dan 1 string input, memeriksa apakah angkanya <5 dan menggunakan LOCATEfungsi QBasic untuk menggantikan karakter yang tepat.


0

Java, 99 byte

(i,j,k)->{int[]b=new int[]{60,60,60,60,60};int[][]a=new int[][]{b,b,b,b,b};a[i-1][5-j]=k;return a;}

0

> <> (Ikan), 36 byte (tidak bersaing)

1-$p;
00000
00000
00000
00000
00000

Coba di sini!

Ini dijalankan dengan menempatkan parameter pada stack seperti [ chr, y,x ]. Salah satu nol di bagian bawah sebenarnya diubah menjadi chroleh instruksi p. Mungkin ada cara yang lebih baik untuk melakukan ini, tetapi saya pikir ini adalah situasi yang unik dan menghibur di mana fitur>> ini berguna.

Penjelasan

Program ini hanya mengurangi 1 dari x(seperti dalam> <>, 0akan benar-benar menjadi kolom pertama), bertukar xdengan y, lalu mengubah titik kotak kode x, ymenjadi chrvia p.ytidak perlu 1 dikurangkan dari itu, karena kode sudah semua diimbangi oleh 1!

Penjelasan yang tidak bersaing

Ini non-bersaing karena tidak benar-benar menghasilkan output. Saya baru saja menemukan ini sangat lucu. Jika ini dianggap output yang valid, beri tahu saya!

Ini juga non-bersaing karena ybisa 0, tapi saya percaya itu satu-satunya masalah dengan jawabannya. Saya akan memperbaikinya jika ini dianggap sebagai output yang valid, tetapi jika tidak, itu hanya membuat jawabannya kurang menghibur ...


2
Jika jawaban seperti ini tidak disarankan, harap beri tahu saya dan saya akan menghapusnya!
redstarcoder

0

Bash, 59 byte

Golf

printf '00000%0.s\n' {1..5}|sed "$1 s/./$3/$2"|grep -z "$3"

$ 1 , $ 2 - baris, kolom, $ 3 - pengganti char, kesalahan dilaporkan melalui kode keluar

Uji

>./box 2 2 "*"
00000
0*000
00000
00000
00000
>echo $?
0

>./box 6 2 '*'     
>echo $?
1

0

Vim, 60 47 42 76 penekanan tombol

Input dalam format (pada baris pertama):

25*

Dengan kursor dimulai di awal

"ax"bxx:if<C-r>a<1||<C-r>a>5||<C-r>b<1||<C-r>b>5
^
endif
6i0<ESC>Y5pG:norm <C-r>al<C-r>bkr<C-r>-
Hqqxjq5@qdd

Jika input tidak valid, maka lemparkan: E492: Not an editor command: ^

Cide yang menghasilkan output hanya 42byte, tetapi untuk membuat kesalahan, bytecount saya meningkat secara drastis.


BTW Saya tidak tahu cara membuat kesalahan di Vim
Kritixi Lithos

0

Java 8, 194 192 byte

interface M{static void main(String[]a){String r="";int i=0,j,z=new Byte(a[0]),y=new Byte(a[1]);for(;++i<6;r+="\n")for(j=0;++j<6;r+=6-i==y&j==z?a[2]:0);System.out.print(z>0&z<7&y>0&y<7?r:0);}}

Coba di sini dengan input yang benar.
Coba di sini dengan input yang salah.

Ini akan menjadi 116 114 byte sebagai fungsi dan bukan program lengkap:

(a,b,c)->{String r="";for(int i=0,j;++i<6;r+="\n")for(j=0;++j<6;r+=b==6-i&a==j?c:0);return a>0&a<7&b>0&b<7?r:"0";}

Coba di sini.

Penjelasan:

interface M{                  // Class
  static void main(String[]a){//  Mandatory main-method
    String r="";              //   Result-String, starting empty
    int i=0,j,                //   Index-integers
        z=new Byte(a[0]),     //   First input converted to integer
        y=new Byte(a[1]);     //   Second input converted to integer
    for(;++i<6;               //   Loop (1) from 1 to 6 (inclusive)
        r+="\n")              //     After every iteration: Append a new-line to the result
      for(j=0;++j<6;          //    Inner loop (2) from 1 to 6 (inclusive)
        r+=6-i==y             //     If the second input equals `6-1`,
           &j==z?             //     and the first input equals `j`:
            a[2]              //      Append the third input to the result-String
           :                  //     Else:
            0                 //      Append a zero to the result-String
      );                      //    End of inner loop (2)
                              //   End of inner loop (1) (implicit / single-line body)
    System.out.print(         //   Print:
     z>0&z<7&y>0&y<7?         //    If the coordinates are valid (1-6):
      r                       //     Print the result `r`
     :                        //    Else:
      0);                     //     Print 0 as error instead
  }                           //  End of main-method
}                             // End of class
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.