Przytnij tablicę!


27

Biorąc pod uwagę tablicę liczb całkowitych i dwie liczby jako dane wejściowe, usuń pewną liczbę pierwszego i ostatniego elementu, określoną liczbami. Dane wejściowe mogą być w dowolnej kolejności.

Powinieneś usunąć pierwsze x elementów, gdzie x jest pierwszym wprowadzeniem numerycznym, a także usunąć ostatnie y elementów, gdzie y jest drugim wprowadzeniem numerycznym.

Wynikowa tablica ma długość co najmniej dwóch.

Przykłady:

[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
Co dokładnie oznacza „usuwać” wartości z tablicy - szczególnie, aby usunąć je z końca? W językach takich jak C, gdzie tablica jest tylko wskaźnikiem do pierwszego elementu i długości, czy możemy po prostu zmienić długość, aby obciąć tablicę? Tak zwykle bywało w programowaniu w świecie rzeczywistym, ale wyzwanie nie jest dla mnie jasne.
Cody Gray

@CodyGray Usuwanie wartości z tablicy jest tym, jak powinno wyglądać , ale niekoniecznie tym, co dzieje się za kulisami.
Okx

4
Co rozumiesz przez „wyglądać”? Tablice nie mają wygląd - to wszystko za kulisami!
Cody Gray


2
@Okx Nie, to bardzo błędne, polecam dodanie tabeli wyników.
Erik the Outgolfer

Odpowiedzi:


16

Haskell, 55 39 33 29 bajtów

Zaoszczędzono 16 bajtów dzięki Laikoni

Zaoszczędź jeszcze 6 bajtów dzięki Laikoni

Zaoszczędzono jeszcze 4 bajty dzięki Laikoni

Jestem pewien, że można to poprawić, ale jako początkujący dałem z siebie wszystko.

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

Stosowanie

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

Wypróbuj online!


5
Witamy w szczególności w PPCG i Haskell! Celem jest użycie jak najmniejszej liczby bajtów, abyś mógł na przykład usunąć większość spacji i skrócić xs.
Laikoni

@Laikoni Ah, dzięki! Edytowany, nie widzę, żebym się skracał bez anonimowej funkcji i używania aplikacji dla funkcji (nie jestem pewien, jak to działa).
Henry

Wygląda dobrze teraz! :) Jeśli zmienia f x a bsię f a b x, można po prostu upuść x: f a b=reverse.drop b.reverse.drop a.
Laikoni

1
@Laikoni Wow, ciekawa sztuczka infix. Dzięki jeszcze raz! Byłem w stanie skrócić go do 33 bajtów, ale próba zrobienia a#b=let r=reverse in r.drop b.r.drop ato 38 bajtów. A może wolno nam zadeklarować funkcję poza tym?
Henry

1
@Laikoni Dzięki za wprowadzenie, bardzo pomocne. Właśnie znalazłem tę stronę dzisiaj, ale zdecydowanie nie mogę się doczekać, aby zagrać tutaj jeszcze trochę!
Henry


6

Mathematica, 17 bajtów

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

wkład

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


Niezłe wykorzystanie ;;! Udało mi się cię związać Drop@##2~Drop~-#&(jeśli weźmiemy wkład w dziwnej kolejności, jak 1, {1,2,3,4,5,6}, 2), ale nie lepiej.
Greg Martin

6

Python , 28 26 bajtów

-2 bajty dzięki @Rod

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

Wypróbuj online!


zapisz 6 ...lambda a,n,m:a[n:~m]
Aaron

@Aaron to zbyt mocno usuwa jeden element.
ovs

mój zły ... To często sztuczka, której czasami używam, i nie sprawdziłem w pełni wymagań wyzwania ..
Aaron

@Aaron plasterek ma wyższy priorytet operatora niż +i dlatego jest stosowany do [0]. Będzie trzeba wsporniki: (a+[0])[n:~m].
ovs

tak, zdałem sobie sprawę, że później .. Próbuję zrealizować mój pomysł
Aaron

6

C # (.NET Core) , 55 54 bajtów

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

Wypróbuj online!

Używa List<int>jako danych wejściowych.

  • 1 bajt zapisany dzięki TheLethalCoder!

1
Właśnie miałem odpowiedzieć na to +1. Można jednak zapisać bajt, przyjmując Listdane wejściowe jako, dzięki czemu można go użyć Countzamiast Length.
TheLethalCoder

Wymyśliłem rozwiązanie, Wherektóre jest tylko trochę dłuższe niż ten sposób, z którego jestem również całkiem zadowolony :)
TheLethalCoder

Nie trzeba dodawać using System.Linq;do liczby bajtów :)
Stefan

@Stefan Muszę liczyć każde usingdodanie w mojej odpowiedzi oraz metody Skipi Takepotrzeby using.
Charlie

hm. w porządku. Na innym wyzwaniu powiedziano mi, że te zastosowania nie są konieczne.
Stefan

5

Perl 5 , 21 bajtów

19 bajtów kodu + -apflagi.

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

Wypróbuj online!

Używa automatycznego -apodziału wejścia wewnątrz @F, a następnie zachowuje tylko jego fragment zgodnie z innymi danymi wejściowymi: od indeksu <>(drugie wejście) do indeksu $#F-<>(rozmiar tablicy minus trzecie wejście). I $_jest domyślnie drukowane dzięki -pflagom.


5

Rdza, 29 bajtów

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

Nazwij to w następujący sposób:

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

Świetnie się bawiłem, walcząc z funkcją sprawdzania pożyczek, zastanawiając się, jakie było najkrótsze podejście, aby mieć wpływ na żywotność zwróconego wycinka. Jego zachowanie wokół zamknięć jest nieco nieobliczalne, ponieważ będzie wnioskować o żywotnościach, ale tylko wtedy, gdy w rzeczywistości nie zadeklarujesz parametru jako typu odniesienia. Niestety koliduje to z koniecznością zdefiniowania typu argumentu w podpisie, ponieważ wywołanie metody n.len musi znać typ, na którym działa.

Inne podejścia próbowałem obejść ten problem:

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 bajty

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

Pobiera List<int>dane wejściowe i zwraca wartość an IEnumerable<int>.


Działa to również dla 64 bajtów:

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

4

TIS-100, 413 405 bajtów

472 cykli, 5 węzłów, 35 linii kodu

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

M4,6 na górze nie jest częścią kodu, ale sygnalizuje umieszczenie modułów pamięci.

wprowadź opis zdjęcia tutaj

Zagraj na tym poziomie, wklejając go do gry:


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

Więc przypuszczam, że to również liczy się jako odpowiedź lua ...


Możesz teraz spróbować online! Uwaga: musiałem zrobić sprytne i użyć górnej części pliku kodu jako jednego źródła danych wejściowych, ponieważ TIO zapewnia obecnie tylko jeden plik wejściowy.
Phlarx

4

MATL , 6 bajtów

QJi-h)

Wypróbuj online!

Dane wejściowe podano jako 1) liczbę elementów do przycięcia od początku; 2) liczba elementów do przycięcia od końca; 3) tablica. Wyjaśnienie

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 bajtów

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

Drugi ujemny parametr slicezatrzymujący krojenie mod końca, jednak gdy mwynosi zero, musimy przekazać symbol zastępczy ( Infinitytutaj, chociaż (a,n,m,o)=>a.slice(n,-m||o)również działa).


3

R , 32 31 30 bajtów

-1 bajt dzięki Rift

-1 bajt dzięki Jarko Dubbeldam

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

Ocenia anonimową funkcję:

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

1+ljest konieczne, ponieważ R ma indeksowanie 1. sum(n|1)jest równoważne, length(n)ale bajt jest krótszy.

Wypróbuj online!


1
zapisywanie 1 bajtu zpryr::f(n[(1+l):(length(n)-r)])
Rift

1
Suma (n | 1) jest krótsza niż długość (n)
JAD

@JarkoDubbeldam doskonale, dziękuję.
Giuseppe

3

MATL , 10 bajtów

tniQwi-&:)

Wypróbuj online!

Wyjaśnienie:

Trochę za długo zajmuje zaledwie 11 bajtów, ale piszę to szczegółowo, aby samemu się tego nauczyć.

---- 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

Zapomniałeś o indeksowaniu końcowym ;)
Sanchises

(wciąż mam opinię - uważam, że jest to gra w golfa dobrze i wyjaśniłem, biorąc pod uwagę zastosowaną metodę)
Sanchises

Nie, nie zapomniałem o tym! Próbowałem, ale nie wymyśliłem, jak to zrobić (i naprawdę próbowałem). Doszedłem do wniosku, że nie da się czegoś odjąć J, kiedy się tak używa. Podejrzewałem, że się myliłem, po prostu nie mogłem tego rozgryźć na całe życie ... Dzięki za link do twojej odpowiedzi, jestem nowicjuszem MATL ...
Stewie Griffin

Nie martw się, jestem też bardzo dużo nauki jeszcze - na przykład, kolejność wejść do )bardziej notorycznie ( dreszcz ...
Sanchises

@ Sanchises Bardzo późny komentarz, ale cieszę się, że nie tylko ja uważam kolejność wprowadzania za (mylącą. :) Za każdym razem zacząłem recytować „ddi” (= „miejsce docelowe, dane, indeksy” z podręcznika) i czasami źle się mylę.
Sundar - Przywróć Monikę

3

C ++, 96 95 bajtów

Dzięki @Tas za uratowanie bajtu!

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

Wypróbuj online!

C ++ (MinGW), 91 bajtów

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

Miałeś na myśli #include<list>? Państwo mogłoby golić bajt mając int f. Kompilatory pozwolą, aby funkcja nie powróciła, ale ostrzegają przed nią
Tas

Tak, dzięki, int fbędzie działał na większości kompilatorów, edytuję to. W MinGW nawet całkowite pominięcie rodzaju funkcji działa. I tak, #include<list>byłby to zgodny ze standardami sposób dołączania nagłówka, ale #import<list>powinien działać przynajmniej na GCC, MinGW i MSVC, więc też powinien być w porządku.
Steadybox

2

APL (Dyalog) , 8 7 bajtów

⌽⎕↓⌽⎕↓⎕

Wypróbuj online!

Pobiera tablicę jako pierwsze wejście, a następnie dwie liczby osobno.

Wyjaśnienie

            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

Alternatywne rozwiązanie 7-bajtowe:⎕↓⎕↓⍨-⎕
Adám


2

Brain-Flak , 60 bajtów

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

Wypróbuj online!

Dane wejściowe są w tym formacie:

x

a
r
r
a
y

y

Gdzie xjest liczba do pobrania z przodu, yto liczba do pobrania z tyłu, a tablica zawiera tyle liczb, ile chcesz, oddzielonych znakami nowej linii. Oto moje pierwsze dwie (dłuższe) próby:

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

A oto wyjaśnienie:

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

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

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

>)[()]}{}

1
Miło widzieć od czasu do czasu rozwiązanie Turing Tarpit.
Okx

2

APL (Dyalog) , 5 bajtów

(⌽↓)/

Wypróbuj online!


Format wejściowy to y x A

Wyjaśnienie

/ to Reduce, która wstawia funkcję po lewej stronie między każdą parą elementów argumentu

(⌽↓)jest ciągiem funkcji równoważnym z {⌽⍺↓⍵}, który usuwa pierwsze elementy tablicy, a następnie odwraca tablicę. ( to lewy argument i prawy argument)

Jest więc (⌽↓)/y x Arównoważne z tym ⌽y↓⌽x↓A, co jest potrzebne.


2

Java 8, 82 bajty

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

Wypróbuj tutaj.

Alternatywnie z taką samą ( 82 ) liczbą bajtów za pomocą pętli:

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

Wypróbuj tutaj.

Wyjaśnienie:

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):

Te java.lang.System.arraycopy()metoda kopiuje tablicę z określonej tablicy źródłowej, które rozpoczynają się w określonym miejscu, do określonego położenia tablicy docelowej. Podsekwencja komponentów tablicy jest kopiowana z tablicy źródłowej, do której odwołuje się, srcdo tablicy docelowej, do której odwołuje się dest. Liczba skopiowanych komponentów jest równa lengthargumentowi.

Składniki w pozycjach srcPospoprzez srcPos + length - 1w tablicy źródłowej są kopiowane do pozycji destPospoprzez destPos + length - 1, odpowiednio, z tablicy docelowej.


Czy możesz zaoszczędzić bajty, nie używając curry?
TheLethalCoder

@TheLethalCoder Nie, w tym przypadku nie. (a,n,m)->ma taką samą liczbę bajtów jak a->n->m->. Chociaż masz rację, mógłbym po prostu użyć zwykłego połączenia zamiast curry. Jestem przyzwyczajony do używania curry, gdy mam dwa (lub więcej) parametrów. Już popełniłem błąd przy użyciu curry, gdy mam kilka parametrów kilka razy ..
Kevin Cruijssen

Ach, masz rację, przeliczyłem bajty i zrobiłem to, a curry jest zdecydowanie najlepszym rozwiązaniem!
TheLethalCoder

Brak linku TIO? -
totalnie ludzki,

2
Przepraszam, nie mogę tego przepuścić. Opublikowałem własną odpowiedź, ponieważ ... jest wbudowana (ok, nie do końca, ale prawie)! : o
Olivier Grégoire


2

Kotlin , 30 bajtów

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

Wypróbuj online!

Bierze List<Int>jako dane wejściowe i spada od początku, a następnie od końca.


1
Nie mam dostępu do try it online. Czy możesz dodać kod dzwoniącego? jak skompilować lambda bez definicji typu w Kotlinie? Dzięki.
mazzy

1
@ mazzy to może być włamanie, ale możesz określić typy w definicji typu zmiennej jakoval f: (List<Int>, Int, Int) -> List<Int>
YGolybev

Rozumiem! Miły. Nie wiem, czy jest to poprawne w CodeGolf.
mazzy

2

Brachylog , 11 10 bajtów

kb₍B&t;Bk₍

Wypróbuj online!

Pobiera dane wejściowe jako [x, A, y], gdzie A jest tablicą do przycięcia.

(-1 bajt dzięki @Fatalize.)


Można go skrócić o 1 bajt jako takiego: kb₍B&t;Bk₍. ,dołącza się (patrz wynik tego programu częściowego ), nie działa jak . Nie próbuj też kopiować rzeczy ze starych ( Brachylog v2, 2016 - początek 2017) odpowiedzi, ponieważ była to pierwsza wersja języka, a programy nie są kompatybilne (w szczególności ,w Brachylog v1 jest teraz Brachylog v2)
Fatalize

@Fatalize Thanks, zaktualizowano. Tak samo ,było w poprzedniej wersji, ale w tym przypadku tpo prostu nie miało to znaczenia, ponieważ i tak było po niej - szczęśliwy zbieg okoliczności. I tak, zdałem sobie sprawę z różnic wersji po tym, jak to opublikowałem, wciąż zastanawiałem się i grzebałem na tym etapie. :)
sundar - Przywróć Monikę


1

Pyth, 5 bajtów

>E<QE

Wypróbuj tutaj

Przyjmuje argumenty w odwrotnej kolejności. <oraz >w przycinaniu Pyth na podstawie kolejności argumentów. Na przykład <Q5odetnie wszystkie wartości na wejściu po piątej.



1

CJam , 8 bajtów

{_,@-<>}

Anonimowy blok, który pobiera dane wejściowe ze stosu w kolejności x , y , tablica i zastępuje je tablicą wyjściową.

Wypróbuj online!

Wyjaśnienie

Rozważmy wejść 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
Dobra uwaga, więc dla zabawy, oto alternatywne 8-bajtowe rozwiązanie :) tio.run
Martin Ender

1

q / kdb, 12 bajtów

Rozwiązanie:

{(0-z)_y _x}

Przykład:

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

Wyjaśnienie:

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

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.