Diziyi kırp!


27

Bir tamsayı dizisi ve giriş olarak iki sayı verildiğinde, sayılarla belirtilen ilk ve son öğelerin belirli bir miktarını kaldırın. Giriş istediğiniz sırada olabilir.

X'in ilk sayısal giriş olduğu ilk x öğesini silmeli ve y'nin ikinci sayısal giriş olduğu son y öğesini de kaldırmalısınız .

Elde edilen dizinin en az iki uzunluğa sahip olduğu garanti edilir.

Örnekler:

[1 2 3 4 5 6] 2 1 -> [3 4 5]
[6 2 4 3 5 1 3] 5 0 -> [1 3]
[1 2] 0 0 -> [1 2]

2
Tam olarak, bir diziden değerleri “çıkarmak”, özellikle de onları sondan kaldırmak ne anlama geliyor? Bir dizinin ilk elemana ve uzunluğa yalnızca bir işaretçi olduğu C gibi dillerde, diziyi kesmek için uzunluğu değiştirebilir miyiz? Yani ne var normalde gerçek dünya programlama yapılabilir, ancak meydan bana belirsizdir.
Cody Gray

@CodyGray diziden değerleri kaldırılıyor o gereken budur bakmak şart değil sahne arkasında neler olup bittiğini gibi ama.
Okx

4
Ne demek "benziyor"? Dizilerin bir bakışı yok - hepsi perde arkasında!
Cody Gray


2
@Okx Hayır, bu çok adamcağız, afiş eklemenizi tavsiye ederim.
Outgolfer Erik,

Yanıtlar:


16

Haskell, 55 39 33 29 bayt

Laikoni sayesinde 16 bayt kaydedildi

Laikoni sayesinde 6 bayt daha kaydedildi

Laikoni sayesinde 4 bayt daha kaydedildi

Bunun geliştirilebileceğinden eminim, ama yeni başlayanlar için elimden gelenin en iyisini yaptım.

r=(reverse.).drop
a#b=r b.r a

kullanım

(5#0) [6,5,4,3,2,1,3]

Çevrimiçi deneyin!


5
Özellikle PPCG ve Haskell golf oynamalarına hoş geldiniz! Amaç mümkün olduğu kadar az bayt kullanmaktır, bu nedenle örneğin boşlukların çoğunu kaldırabilir ve kısaltabilirsiniz xs.
Laikoni

@Likonik Ah, teşekkürler! Düzenlendi, anonim bir işlev olmadan kendimi kısalttığımı ve işlevler için uygulayıcı kullandığımı göremiyorum (nasıl çalıştığından emin değilim).
Henry

Şimdi iyi görünüyorsun! Eğer değiştirirseniz :) f x a biçin f a b x, sadece bırakın x: f a b=reverse.drop b.reverse.drop a.
Laikoni

1
@Likonik Vay, ilginç infix hile. Tekrar teşekkürler! Bunu 33 byte kısaltabildim, fakat yapmaya çalışmak a#b=let r=reverse in r.drop b.r.drop a38 byte. Yoksa bunun dışında ilan edilmiş bir işleve sahip olmamıza izin verilir mi?
Henry

1
@Likonikon Girişiniz için teşekkürler, çok faydalı. Bugün sadece bu siteyi buldum, ancak kesinlikle burada biraz daha oynamayı dört gözle bekliyorum!
Henry


6

Mathematica, 17 bayt

#[[#2+1;;-#3-1]]&

giriş

[{1, 2, 3, 4, 5, 6}, 2, 1]


Güzel kullanımı ;;! Seni bağlamayı başardım Drop@##2~Drop~-#&(eğer girişi garip bir düzende alırsak 1, {1,2,3,4,5,6}, 2), ama daha iyi değil.
Greg Martin

6

Python , 28 26 bayt

@Rod sayesinde -2 bayt

lambda a,n,m:a[n:len(a)-m]

Çevrimiçi deneyin!


6'dan tasarruf edin ...lambda a,n,m:a[n:~m]
Aaron

@Aaron bu, bir öğeyi çok fazla kaldırır.
ovs

benim kötüsüm .. Bazen kullandığım yaygın bir numaradır ve mücadelenin gerekliliklerini tam olarak kontrol etmedi ..
Aaron

@Aaron, dilimden daha yüksek bir operatör önceliğine sahiptir +ve bu nedenle uygulanır [0]. Sen parantez gerekir: (a+[0])[n:~m].
ovs

yah, daha sonra farkettim ..
Aaron

6

C # (.NET Core) , 55 54 bayt

using System.Linq;(a,x,y)=>a.Skip(x).Take(a.Count-x-y)

Çevrimiçi deneyin!

Bir List<int>giriş olarak kullanır .

  • TheLethalCoder sayesinde 1 byte kaydedildi!

1
Bu + 1'e cevap vermek üzereydim. Ancak, Listgiriş olarak alarak bir bayt kaydedebilirsiniz, böylece Countyerine kullanabilirsiniz Length.
TheLethalCoder

Bunu kullanarak bir çözüm buldum Where, sadece biraz daha uzun, bundan çok mutluyum :)
TheLethalCoder

using System.Linq;Bayt sayısını eklemek zorunda değilsin :)
Stefan

@Stefan Cevabımı usingeklediğim her şeyi Skipve buna Takeihtiyaç duyan yöntemleri saymalıyım using.
Charlie

hm. Tamam. Başka bir meydan okumada, gerekli olmadığında bu kullanımları söylendi.
Stefan

5

Perl 5 , 21 bayt

19 bayt kod + -apbayrakları.

$_="@F[<>..$#F-<>]"

Çevrimiçi deneyin!

Kullanım -agiriş iç otomatik bölme için @F, daha sonra, sadece diğer girişlere göre bunun bir dilim tutmak: dizinden <>(ikinci giriş) indeksine $#F-<>(dizi eksi üçüncü girdi büyüklüğü). Ve $_örtülü sayesinde yazdırılır -pbayrağı.


5

Pas, 29 bayt

|n,i,j|&n[i..<[_]>::len(n)-j]

Aşağıdaki gibi arayın:

let a = &[1, 2, 3, 4, 5, 6];
let f = |n,i,j|&n[i..<[_]>::len(n)-j];
f(a, 2, 1)

Borç kontrolcüsü ile savaşırken çok eğlendim. İade edilen bir dilimin ömrünü kısaltmak için en kısa yaklaşımın ne olduğunu buldum. Kapakların etrafındaki davranışları, yaşam sürelerini kısaltacağından biraz düzensizdir, ancak yalnızca parametreyi referans türü olarak tanımlamazsanız. Ne yazık ki bu, imzadaki argüman tipini tanımlamak için gerekli olanla n.len metod çağrısı üzerinde çalıştığı tipin bilinmesi gerektiğini gerektirir.

Bu soruna geçici bir çözüm bulmaya çalıştığım diğer yaklaşımlar:

fn f<T>(n:&[T],i:usize,j:usize)->&[T]{&n[i..n.len()-j]}     // full function, elided lifetimes
let f:for<'a>fn(&'a[_],_,_)->&'a[_]=|n,i,j|&n[i..n.len()-j] // type annotation only for lifetimes. Currently in beta.
|n:&[_],i,j|n[i..n.len()-j].to_vec()                        // returns an owned value
|n,i,j|&(n as&[_])[i..(n as&[_]).len()-j]                   // casts to determine the type
|n,i,j|&(n:&[_])[i..n.len()-j]                              // type ascription (unstable feature)
|n,i,j|{let b:&[_]=n;&b[i..b.len()-j]}                      // re-assignment to declare the type


4

C #, 62 bayt

using System.Linq;(l,x,y)=>l.Where((n,i)=>i>=x&i<=l.Count-y-1)

Bir Alır List<int>giriş ve getiri bir şekilde IEnumerable<int>.


Bu ayrıca 64 bayt için çalışır:

using System.Linq;(l,x,y)=>l.Skip(x).Reverse().Skip(y).Reverse()

4

TIS-100, 413 405 Bayt

472 döngü, 5 düğüm, 35 kod satırı

m4,6
@0
MOV 0 ANY
S:MOV UP ACC
JEZ A
MOV ACC ANY
JMP S
A:MOV RIGHT ACC
L:JEZ B
MOV DOWN NIL
SUB 1
JMP L
B:MOV 0 RIGHT
MOV RIGHT NIL
@1
MOV RIGHT LEFT
MOV LEFT DOWN
MOV RIGHT DOWN
MOV DOWN LEFT
@2
MOV UP ACC
MOV UP LEFT
MOV ACC LEFT
@4
MOV 0 RIGHT
MOV UP NIL
S:MOV LEFT ACC
JEZ A
MOV ACC RIGHT
JMP S
A:MOV UP ACC
L:JEZ B
MOV RIGHT NIL
SUB 1
JMP L
B:MOV 0 UP
K:MOV RIGHT ACC
MOV ACC DOWN
JNZ K
@7
MOV UP ANY

Üstte bulunan m4,6, kodun bir parçası değil, bellek modüllerinin yerleşimini gösterir.

görüntü tanımını buraya girin

Bunu oyuna yapıştırarak bu seviyeyi kendin oyna:


function get_name()
    return "ARRAY TRIMMER"
end
function get_description()
    return { "RECIEVE AN ARRAY FROM IN.A", "RECIEVE TWO VALUES A THEN B FROM IN.T", "REMOVE THE FIRST A TERMS AND LAST B TERMS FROM IN.A", "ARRAYS ARE 0 TERMINATED" }
end

function get_streams()
    input = {}
    trim = {}
    output = {}

  arrayLengths = {}

    a = math.random(1,5) - 3

    b = math.random(1,7) - 4

    arrayLengths[1] = 9+a
    arrayLengths[2] = 9+b
    arrayLengths[3] = 8-a
    arrayLengths[4] = 9-b

    s = 0

    trimIndex = 1

  for i = 1,4 do
      for k = 1,arrayLengths[i] do
          x = math.random(1,999)
      input[k+s] = x
            output[k+s] = x
        end

        input[s + arrayLengths[i] + 1]= 0
        output[s + arrayLengths[i] + 1]= 0

        a = math.random(0,3)
        b = math.random(0,arrayLengths[i]-a)

        trim[trimIndex] = a
        trim[trimIndex+1] = b

        trimIndex = trimIndex + 2

    s = s + arrayLengths[i] + 1
    end

    s = 1
    trimIndex = 1

    for i = 1,4 do

      for i = s,s+trim[trimIndex]-1 do
          output[i]=-99
        end

        for i = s + arrayLengths[i] - trim[trimIndex+1], s + arrayLengths[i]-1 do
      output[i]=-99
        end

  trimIndex = trimIndex +2
  s = s + arrayLengths[i] + 1
    end

    trimmedOut = {}
    for i = 1,39 do
            if(output[i] ~= -99) then
                    table.insert(trimmedOut, output[i])
            end
    end

    return {
        { STREAM_INPUT, "IN.A", 0, input },
        { STREAM_INPUT, "IN.T", 2, trim },
        { STREAM_OUTPUT, "OUT.A", 1, trimmedOut },
    }
end
function get_layout()
    return {
        TILE_COMPUTE,   TILE_COMPUTE,   TILE_COMPUTE,   TILE_COMPUTE,
        TILE_MEMORY,    TILE_COMPUTE,    TILE_MEMORY,   TILE_COMPUTE,
        TILE_COMPUTE,   TILE_COMPUTE,   TILE_COMPUTE,   TILE_COMPUTE,
    }
end

Sanırım bu da bir lua cevabı olarak sayılıyor ...


Şimdi çevrimiçi deneyebilirsiniz! Not: Zekice yapmak ve kod dosyasının tepesini bir giriş kaynağı olarak kullanmak zorunda kaldım, çünkü TIO şu anda sadece bir giriş dosyası sağlıyor.
Phlarx

4

MATL , 6 bayt

QJi-h)

Çevrimiçi deneyin!

Giriş 1) baştan kesilecek eleman sayısı; 2) uçtan kesilecek elemanların sayısı; 3) dizi. açıklama

Q   % Implicit input (1). Increment by 1, since MATL indexing is 1-based.
Ji- % Complex 1i minus real input (2). In MATL, the end of the array is given by `1i`.
h   % Concatenate indices to get range-based indexing 1+(1):end-(2).
)   % Index into (implicitly taken) input array. Implicit display.


3

JavaScript (ES6), 27 bayt

(a,n,m)=>a.slice(n,-m||1/m)

sliceSonundan mitibaren dilimi durduran negatif bir ikinci parametre , ancak msıfır olduğunda , bir yer tutucuyu geçmemiz gerekir ( Infinityburada (a,n,m,o)=>a.slice(n,-m||o)da çalışır).


3

R , 32 31 , 30 bayt

Rift sayesinde -1 bayt

Jarko Dubbeldam sayesinde -1 bayt

pryr::f(n[(1+l):(sum(n|1)-r)])

Anonim bir işlev için değerlendirir:

function (l, n, r) 
    n[(1 + l):(sum(n|1) - r)]

1+lR'nin 1 tabanlı endekslemeye sahip olması nedeniyle gereklidir. sum(n|1)eşittir, length(n)ancak bir bayt daha kısadır.

Çevrimiçi deneyin!


1
1 byte ile tasarrufpryr::f(n[(1+l):(length(n)-r)])
Rift

1
Sum (n | 1) uzunluktan daha kısa (n)
JAD

Mükemmel @JarkoDubbeldam, teşekkür ederim.
Giuseppe

3

MATL , 10 bayt

tniQwi-&:)

Çevrimiçi deneyin!

Açıklama:

Sadece 11 byte için biraz uzun, ama ben de kendim öğrenmek için onu ayrıntılı olarak yazıyorum.

---- Input ----
[1 2 3 4 5 6]
2
1
----- Code ----
           % Implicit first input
t          % Duplicate input.
           % Stack: [1 2 3 4 5 6], [1 2 3 4 5 6]
 n         % Number of elements
           % Stack: [1 2 3 4 5 6], 6
  i        % Second input
           % Stack: [1 2 3 4 5 6], 6, 2
   Q       % Increment: [1 2 3 4 5 6], 6, 3
    w      % Swap last two elements
           % Stack: [1 2 3 4 5 6], 3, 6
     i     % Third input
           % Stack: [1 2 3 4 5 6], 3, 6, 1
      -    % Subtract
           % Stack: [1 2 3 4 5 6], 3, 5
       &:  % Range with two input arguments, [3 4 5]
           % Stack: [1 2 3 4 5 6], [3 4 5]
         ) % Use as index
           % Stack: [3 4 5]
           % Implicit display


(Yine de bir artı-var - Bunun iyi bir şekilde golf oynadığına ve kullandığınız yöntemi göz önünde bulundurarak açıkladığına inanıyorum)
Sanchises

Hayır, unutmadım! Denedim ama nasıl çalışacağını çözmedim (ve gerçekten denedim). JBu şekilde kullanıldığında bir şeyi çıkarmanın imkansız olduğu sonucuna vardım . Yanlış olduğumdan şüphelenmiştim, sadece hayatım boyunca çözemedim ... Cevabınıza bağlantı verdiğiniz için teşekkür ederim, ben çok MATL acemi ...
Stewie Griffin

Örneğin girişlerin sırası ile - Yapma etme, ben hala çok öğrenme da değilim )ve daha herkesin bildiği ( titreme ...
Sanchises

@Sanchises Çok geç yorum, ama (kafa karıştırıcı giriş emri bu sadece ben değil sevindim . :) Her seferinde "ddi" (= "hedef, veri, dizinlerden") okudum ve bazen yanlış anladım.
sundar - Reinstate Monica,

3

C ++, 96 95 bayt

Bir bayt tasarrufu için @Tas teşekkürler!

#import<list>
int f(std::list<int>&l,int x,int y){for(l.resize(l.size()-y);x--;)l.pop_front();}

Çevrimiçi deneyin!

C ++ (MinGW), 91 bayt

#import<list>
f(std::list<int>&l,int x,int y){for(l.resize(l.size()-y);x--;)l.pop_front();}

Bunu mu demek istediniz #include<list>? Sen olabilir alarak bir bayt tıraş int f. Derleyiciler bir işlevin geri dönmemesine izin verir, ancak buna karşı uyarırlar
Tas

Evet, teşekkürler, int fçoğu derleyici üzerinde çalışacak, onu düzenleyeceğim. MinGW'de, fonksiyonun çalışmasının türünü tamamen göz ardı ederek bile. Ve evet, #include<list>başlığı dahil etmek için standartlara uygun bir yol olabilir, ancak #import<list>en azından GCC, MinGW ve MSVC üzerinde çalışmalı, bu yüzden iyi olmalı.
Steadybox

2

APL (Dyalog) , 8 7 bayt

⌽⎕↓⌽⎕↓⎕

Çevrimiçi deneyin!

Bu, diziyi ilk giriş olarak alır, ardından iki sayı ayrı ayrı alır.

açıklama

            from the input array
⎕↓           drop the first input elements
            reverse the array
⎕↓           drop first input elements
            reverse again to go back to the original array

Alternatif 7 byte çözüm:⎕↓⎕↓⍨-⎕
Ad


2

Beyin Flak , 60 bayt

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

Çevrimiçi deneyin!

Giriş bu formatta:

x

a
r
r
a
y

y

Nerede xönden almaya sayıdır, yarkasından almaya sayıdır ve dizi size satırbaşıyla ayrılmış, istediğiniz gibi ancak birçok sayılardır. İşte ilk iki (daha uzun) denemelerim:

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

Ve işte bir açıklama:

#Two times:
(()()){({}<

    #Remove *n* numbers from the top of the stack
    {({}<{}>[()])}{}

    #Reverse the whole stack
    ([]){{}({}<>)<>([])}{}<>

>)[()]}{}

1
Her zaman ve sonra bir turing tarpit çözümü görmek güzel.
Okx

2

APL (Dyalog) , 5 bayt

(⌽↓)/

Çevrimiçi deneyin!


Giriş formatı y x A

açıklama

/ Argümanının her bir çift çifti arasında işlevi sola ekleyen Reduce (Düşür) işlevi

(⌽↓)bu , dizinin {⌽⍺↓⍵}ilk elemanlarını silen ve daha sonra diziyi tersine çeviren, eşdeğer bir fonksiyon trenidir . ( soldaki tartışma doğru argümandır)

Böylece, ihtiyaç duyulan (⌽↓)/y x Aşey eşdeğerdir ⌽y↓⌽x↓A.


2

Java 8, 82 bayt

a->n->m->{int l=a.length-m-n,r[]=new int[l];System.arraycopy(a,n,r,0,l);return r;}

Burada dene.

Bir döngü kullanarak aynı ( 82 ) byte-count ile alternatif :

(a,n,m)->{int l=a.length-m,r[]=new int[l-n],i=0;for(;n<l;r[i++]=a[n++]);return r;}

Burada dene.

Açıklama:

a->n->m->{                      // Method with integer-array and two integer parameters and integer-array return-type
  int l=a.length-m-n,           //  Length of the array minus the two integers
      r[]=new int[l];           //  Result integer-array
  System.arraycopy(a,n,r,0,l);  //  Java built-in to copy part of an array to another array
  return r;                     //  Return result-String
}                               // End of method

System.arraycopy:

arraycopy(Object src, int srcPos, Object dest, int destPos, int length):

java.lang.System.arraycopy()Yöntem kopya hedef dizinin belirli bir konuma, belirtilen pozisyonda başlayan belirtilen kaynak diziden bir dizi. Dizi bileşenlerinin bir sırası, tarafından başvurulan srchedef diziye başvurulan kaynak diziden kopyalanır dest. Kopyalanan bileşenlerin sayısı,length argümana .

Pozisyonlarda bileşenler srcPosaracılığıyla srcPos + length - 1kaynak dizideki pozisyonlara kopyalanır destPosyoluyla destPos + length - 1hedef dizinin sırasıyla.


Körleme yapmadan bayt tasarrufu yapabilir misiniz?
TheLethalCoder

@TheLethalCoder Hayır, bu durumda değil. (a,n,m)->aynı bayt sayıma sahip a->n->m->. Haklı olsan da, körleme yerine normal bir arama yapabilirdim. İki (veya daha fazla) parametreye sahip
olduğumda currying kullanmaya alışkınım

Ahh haklısınız baytları yanlış saydım ve yaptım ki, iyi de kızamıyorum!
TheLethalCoder

TIO bağlantısı yok mu? -
totallyhuman

2
Üzgünüm, bunun geçmesine izin veremem. Kendi cevabımı gönderdim çünkü ... bir yerleşik var (tamam, tam olarak değil ama neredeyse)! : o
Olivier Grégoire


2

Kotlin , 30 bayt

{a,s,e->a.drop(s).dropLast(e)}

Çevrimiçi deneyin!

Alır List<Int>girdi olarak ve başlamak düşüşlerini ardından ucundan.


1
Erişimim yok try it online. Arayan kodu ekleyebilir misiniz? Kotlin'de tür tanımsız lambda nasıl derlenir? Teşekkürler.
mazzy

1
@mazzy muhtemelen bir hack olabilir, ancak değişken tipi tanımındaki türleri belirtebilirsinizval f: (List<Int>, Int, Int) -> List<Int>
YGolybev

Anladım! Güzel. Bunun CodeGolf'ta geçerli olup olmadığını bilmiyorum.
mazzy

2

Brachylog , 11 10 bayt

kb₍B&t;Bk₍

Çevrimiçi deneyin!

Girdiyi [x, A, y] olarak alır, burada A kırpılacak dizidir.

(@Fatalize sayesinde -1 bayt.)


Aşağıdaki gibi 1 bayt ile kısaltın edebilirsiniz: kb₍B&t;Bk₍. ,ekler ( bu kısmi programın sonucuna bakınız ) gibi davranmaz . Ayrıca eskiden (2016-başındaki 2017) Brachylog'dan gelen şeyleri kopyalamaya çalışmayın, çünkü dilin ilk versiyonuydu ve programlar geriye dönük olarak uyumlu değildi (özellikle ,Brachylog v1'de Brachylog v2'de)
Fatalize

@Fatalize Teşekkürler, güncellendi. Böylece ,önceki sürümde ekledim, ama bu durumda sadece bir önemi yoktu, çünkü tyine de bir şans vardı - şanslı tesadüf. Ve evet, bunu gönderdikten sonra sürüm farklılıklarını fark ettim, hala bu aşamada bazı şeyleri çözüp duruyordum. :)
sundar - Reinstate Monica


1

Pyth, 5 bayt

>E<QE

Burada dene

Argümanları ters sırada alır. <ve >argüman sırasına göre Pyth trim. Örneğin <Q5, beşinci değerden sonra girişteki tüm değerleri keser.



1

CJam , 8 bayt

{_,@-<>}

Girdileri yığından x , y , array sırasına alan ve onları çıktı dizisi ile değiştiren adsız blok .

Çevrimiçi deneyin!

açıklama

Girişlerini düşünün 2, 1, [10 20 30 40 50 60].

{      }    e# Block
            e# STACK: 2, 1, [10 20 30 40 50 60]
 _          e# Duplicate
            e# STACK: 2, 1, [10 20 30 40 50 60], [10 20 30 40 50 60]
  ,         e# Length
            e# STACK: 2, 1, [10 20 30 40 50 60], 6
   @        e# Rotate
            e# STACK: 2, [10 20 30 40 50 60], 6, 1
    -       e# Subtract
            e# STACK: 2, [10 20 30 40 50 60], 5
     <      e# Slice before
            e# STACK: 2, [10 20 30 40 50]
      >     e# Slice after
            e# STACK: [30 40 50]

1
İyi nokta, o zaman sadece eğlence için, işte alternatif 8-byte çözüm :) tio.run/##S85KzP1vxGXIFW1ooGBkoGBsoGBioGBqoGBmEPu/Olg7ps7GrvZ/…
Martin Ender

1

q / kdb, 12 bayt

Çözüm:

{(0-z)_y _x}

Örnek:

q){(0-z)_y _x}[1 2 3 4 5 6;2;1]
3 4 5
q){(0-z)_y _x}[6 2 4 3 5 1 3;5;0]
1 3
q){(0-z)_y _x}[1 2;0;0]
1 2

Açıklama:

{          } / lambda function
          x  / input array
       y _   / drop y elements from .. (takes from start)
 (0-z)       / negative z ()
      _      / drop -z elements from ... (takes from end)

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.