Selezione scorrevole


13

Dopo la mia entrata in Obfuscated Hello World ho pensato che sarebbe stato divertente condividere il codice sottostante. Ma perché mostrare semplicemente il codice, rendiamolo anche un golf!

Sfida

Scrivi uno script che fa scorrere una stringa attraverso il terminale, da destra a sinistra, sistemandosi sul lato sinistro.

Ingresso

Accetta una stringa come argomento.

Risultato

Stampa il riquadro scorrevole su STDOUT. Larghezza massima di ~ 50 caratteri. Inizia con 0 o 1 carattere visualizzato. Spazio tra le lettere durante lo scorrimento. Si interrompe quando impostato (senza spazio aggiuntivo tra i caratteri di parola). Scorrimento lento, ma non troppo lento (<1s per iterazione).

Esempio

Esecuzione di script con arg 'Hello World'

                                                   H

dopo

                H    e    l    l    o         W    o

dopo

H    e    l    l    o          W    o    r    l    d

dopo

Hell    o         W    o    r    l    d

infine

Hello World

Per un esempio corrente, prova il mio codice dalla sfida "Hello World". Alla fine posterò il mio. Attualmente è di 202 caratteri in Perl. Ora che ci sono alcuni concorrenti, ho pubblicato il mio nelle risposte.

Vincitore

Non voglio che le restrizioni siano assolute, ecco perché le ho lasciate un po 'vaghe. Vincerà la sceneggiatura più breve che segue lo spirito del mio originale.

Appunti

Questo gioco presuppone l' xtermambiente. Se un altro ambiente dovesse rivelarsi utile, verranno confrontati solo ambienti simili e per ciascuno potrà essere dichiarato un vincitore separato.

Addendum (25 aprile 2012)

Per affrontare alcuni problemi in erba, sto prendendo una decisione. Il conteggio dei personaggi deve includere il codice necessario per:

  1. Flush STDOUT (Looking at you Ruby)
  2. Implementare sleepcon un ritardo di <1 s (Ti guardo Perl)

Questo può essere fatto quando la riga di comando passa a un interprete, ma quei caratteri contano nel totale (senza spazi bianchi circostanti).


Sono un po 'preoccupato per i comportamenti dei terminali per questo genere di cose ... xterm, vt102...?
dmckee --- ex gattino moderatore

Sto assumendo xterm, ma non penso che importi troppo. Forse non capisco la tua preoccupazione?
Joel Berger,

Questi trucchi sono di solito prodotti facendo affidamento sul modo in cui i vari terminali gestiscono alcuni dei caratteri non stampabili e i terminali differivano in ciò che potevano fare e in quali sequenze producevano gli effetti. Per la riproducibilità potrebbe essere utile disporre di un ambiente terminale specificato.
dmckee --- ex gattino moderatore

1
Ti servirà nel modo giusto se qualcuno pubblica una risposta molto breve che dipende da un oscuro terminale per il quale non hai un emulatore, ma OK.
dmckee --- ex gattino moderatore

ok penso di averlo ora. Grazie per i pensieri :-)
Joel Berger

Risposte:


5

python 2 - 146 caratteri

edit: lo ha reso una funzione anziché un input tramite stdin. il primo argomento è la stringa e il secondo argomento è la lunghezza che vuoi che sia. così sarebbe l'invocazione f('Hello World', 50). L'ho anche reso molto più fluido; quando ogni personaggio "è atterrato" c'è stata una pausa imbarazzante

import os,time
def f(x,n):
 y=' '*n+'  '.join(x);z=0
 while y:w=y[0]==x[z];y=y[1+w:];z+=w;os.system('cls');print((x[:z]+y)[:n]);time.sleep(0.1)

vecchio, 158 caratteri:

import os,time,sys
x=' '.join(sys.argv[1:])
y=' '*50+'  '.join(x)
z=0
while y:z+=y[0]==x[z];y=y[1:];os.system('cls');print((x[:z]+y)[:50]);time.sleep(0.1)

Usando bash (almeno in una recente installazione di MacOSX e CentOS), il comando shell usato per cancellare lo schermo del terminale dovrebbe essere 'clear' non 'cls'.
Paolo

'cls' per Windows, 'clear' per build OSX / Linux, credo
Blazer

Consigli su come avviare il programma per coloro che non hanno a che fare con Python su base giornaliera, sarebbero utili. Avvia Python. incolla codice, chiama ha f("Hello World, 40)funzionato per me.
utente sconosciuto

@utente I um. Ho messo l'invocazione lassù?
Blazer,

4

Rubino, 93 91 89 caratteri

u="\1";s=u*50+[*$*[0].chars]*(u*3);$><<s.tr(u," ")[0,50]+" \r"while s.sub!u,""*sleep(0.1)

Il testo da visualizzare deve essere fornito come argomento della riga di comando, ad es

ruby marquee.rb "Hello World"

per l'esempio mostrato sopra. Sfortunatamente non posso mostrare l'animazione qui, quindi devi provare tu stesso il codice.

Versione precedente:

s=" "*67+[*$*[0].chars]*"   ";(s.size*3/4).times{|j|s[j/3]='';$><<s[16,50]+" \r";sleep 0.1}

Dimensioni impressionanti. Non è molto fluido, sono io (sono su una macchina piuttosto a basso consumo al momento) o è così che funziona il codice?
Joel Berger,

Capito, ho dovuto impostare in STDOUT.sync=true;modo che si scarichi automaticamente. L'equiv Perl è $|++. Ecco altri 17 caratteri, ma comunque ben al di sotto dei miei. Beh, non posso avere Ruby che batte Perl! Devo iniziare a lavorare. Ben fatto.
Joel Berger,

Se chiamo ruby1.8 "Hello World"ricevo, non esattamente con mia sorpresa, un errore che dice:ruby1.8: No such file or directory -- Hello World (LoadError)
utente sconosciuto

@userunknown forse dovresti inserire anche il percorso del file sorgente: ruby foo.rb args;-)
Patrick Oscity,

@padde: Sì, dovrei. Purtroppo Howard ha modificato il suo post senza informarmi del suo cambiamento. Dai un'occhiata alla storia per capire la mia domanda.
utente sconosciuto

3

C, 94 83 80 173 caratteri

EDIT: aggiunto un sacco di codice, implementa tutte le funzionalità richieste ora. La costante 1e8può essere ottimizzata per controllare la velocità. Sulla mia macchina è abbastanza veloce così com'è.
Alcuni personaggi possono sicuramente essere salvati qui. lpuò essere statico (salva l'inizializzazione), cpuò diventare un puntatore (sostituzione b+c).

char b[99],c=1;
main(a,t,w,i,l)char**t;{
    for(l=0;b[l++]=*t[1]++;b[l++]=32);
    for(w=80;i--||
        printf("\033[F\033[K%*.*s\n",w-=l<a,a++,b,i=1e8)>l+6||
        b[++c]&&memmove(b+c-1,b+c,l););
}

Vecchia versione (80 caratteri), con funzionalità parziale:
salvati un paio di caratteri sostituendoli char**tcon int*t. Funziona bene a 32 bit ( int**tsupporterebbe 64 bit).

main(i,t,w)
    int*t;
{
    for(w=80;i--||printf("\033[F\033[K%*s\n",w,t[1],i=1e8)*--w;);
}

2

K&R C - 431 416 caratteri

Rispetta lo standard in misura elevata. Utilizza ncurses quindi dovrebbe essere in gran parte indipendente dal terminale. Vi è una leggera balbuzie quando il testo colpisce il lato a causa di qualche trucco giocato per preservare lo spazio bianco previsto nella stringa.

La stringa da usare dovrebbe essere passata come primo argomento sulla riga di comando (e dovrebbe essere evasa se contiene spazi, tanto più se contiene un !come il mio test string ( Hello, World!)).

#include <ncurses.h>
#include <unistd.h>
#define T usleep(1e5),S(l)
#define U mvprintw(23,0,"%s",l),refresh()
char l[63],*p,*q,r;
S(char*s){r=0;if(*s==32)q=s++;else{for(;*s-32||*(s+1)-32;s++); 
for(q=s;*s==32;s++);(s-q)&1?s--:usleep(1e5);}
for(r=0;*s;*q++=*s++){*s-32?r=1:0;}return r;}
main(int c,char**v){initscr();curs_set(0);for(c=0;c<62;l[c++]=32);
for(p=*++v;*p;){l[52]=*p++;U;T;U;T;U;T;}for(;T;U);getch();endwin();}

In una forma più leggibile e commentata:

#include <ncurses.h>
#include <unistd.h>

char l[63] /* take advantage of 0 initialization */,
  *p,*q, r;

/* Remove the first unwanted space. Unwanted means at the begining of
 * the line, all of even length blocks between non-spaces, and
 * all-bu-one of odd length blocks between non-spaces.
 *
 * Return true if the removed space occurs before a non-space character.
 */
S/*lide marquee*/(char*s){
  r=0; /* initialize the return value */
  if(*s==' '){
    q=s++;
  } else {
    /* Find the start of first block of contiguous spaces */
    for(;*s-' '||*(s+1)-' ';s++); 
    for(q=s;*s==' ';s++); /* q holds the start, s finds it's end */
    /* if this block is even length remove all, if odd, all but one */
    if( (s-q)%2 )s--; else usleep(1e5);
  }
  /* copy from s to q all the way to the end */
  for(r=0;*s;*q++=*s++){ 
    if(*s-' ')r=1; /* note if we pass a non-space */
  } 
  return r;
}

main(int c,char**v){
  initscr();curs_set(0); /* setup ncurses with invisible cursor */
  for(c=0;c<62;l[c++]=' '); /* initialize l */
  for(p=*++v;*p;){ /* load the message into the marque, skipping space */
    l[52]=*p++;
    mvprintw(23,0,"%s",l),
    refresh();
    usleep(1e5),
    S(l);
    usleep(1e5),
    S(l);
    usleep(1e5),
    S(l);
  }
  for(;usleep(1e5),S(l);mvprintw(23,0,"%s",l),refresh()); /* keeping sliding until we're done. */
  getch();
  endwin();
}

C'è un grande potenziale di accorciamento, in particolare sostituendolo ifcon gli operatori. Ad esempio - if((s-q)%2)s--;else usleep(1e5);-> s-q&1?s--:usleep(1e5);(o s-=s-q&1||usleep(1e5);)
ugoren,

@ugoren: Sì, e avevo dimenticato di sostituire la ' 's con equivalenti numerici.
dmckee --- ex-moderatore gattino

Qualche altro trucco: sostituisci x==32con x-32(inverte il significato, quindi inverti if-else), o con x<33(supponendo che 0..31 non sia mai stato usato). Inizializza con i valori che hai ( for(curs_set(c=0);...). *(s+1)-> s[1]. Rimuovere le parentesi graffe non necessarie (la sostituzione ;con ,aiuterà).
ugoren,

2

Perl 5.13.2, 96

$_=join$;x4,$;x46,split//,pop;print substr(s/$;/ /gr,0,50)." \r"while$|=s/$;//+select'','','',.1

Rubando molto dalla risposta di @ Kevin Reid , in particolare il /rtrucco disponibile nel nuovo Perls.

Perl, 115

Come la risposta di @ Joel Berger , questo diventerebbe molto più breve se potessi usare sleep 1ed essere lento, o passare -MTime::HiRes=sleepla riga di comando per abilitare sleep.1. In caso contrario, l'unico modo integrato per ottenere brevi dormi è select'','','',.1che è piuttosto lungo.

$|=@_=(($")x45,map{($")x4,$_}split//,pop);for(0..$#_){print@_," \r";splice@_,($_-=45)<0?0:$_/4,1;select'','','',.1}

Perl, 128

$_=$"x9 .pop;s/./    $&/g;$.=-46;$\=" \r";while($|=/./g){print substr($_,0,50);pos=++$.<0?0:$./4;s/\G.//;select'','','',.1}print

Perl, 133

$|=@_=split//,pop;for$i(reverse-$#_..50){for(@_){print$"x($j||$i),$_;($i+=$j=($i++>0)*4)>50&&last}print"    \r";$j=select'','','',.1}

sì, mi sono morso con la mia regola su quella! Non mi ero reso conto che altri lang avrebbero avuto un sonno incorporato. Oh bene.
Joel Berger,

alcuni suggerimenti, è possibile rimuovere lo spazio dopo ciascuno xe la forma di blocco mapne salverà alcuni.
Joel Berger,

1

JavaScript 180 218 caratteri

Versione di produzione:

function f(){i--&&(i>50?h=h.substr(1):h=h.replace(" ",i==16?"&nbsp;":""),document.body.innerHTML="<pre>"+h.substr(0,50)+"</pre>",setTimeout(f,99))}h=(new Array(50)).join(" ")+"HelloWorld".split("").join("   "),i=80,f()

Versione Ungolfed:

h=new Array(50).join(" ")+("HelloWorld".split("").join("   "));
i=80;

function f(){
        if(i--){
            if(i>50){
                h=h.substr(1);
            }else{
                h=h.replace(" ",(i==16)?"&nbsp;":"");
            }
            document.body.innerHTML="<pre>"+h.substr(0,50)+"</pre>";
            setTimeout(f,99);
        }
}
f();​

Ecco una demo di jsFiddle

Nota: se si tenta di riprodurlo, assicurarsi che il codice sia sotto il corpo


Non posso dirlo dalla demo, si "impila" sul lato sinistro o semplicemente lo fa a sinistra e poi mostra la stringa finale? Howard funziona sicuramente se non sei sicuro.
Joel Berger,

@JoelBerger il mondo ciao ha 4 spazi tra ogni lettera, quando h è il primo carattere, questi spazi vengono rimossi. Questa demo è più lenta jsfiddle.net/fYvg7/1
ajax333221

È vicino, ma è necessario rimuovere ogni spazio singolarmente.
Joel Berger,

@JoelBerger Fixed
ajax333221

Beh, odio essere una seccatura, ma un altro problema: il tuo inizia con tutte le lettere che mostrano invece di inserire una a una a destra.
Joel Berger,

1

Perl 5.13.2, 115 caratteri

$_=$"x9 .pop=~y/ /\0/r;s/./    $&/g;print(y/\0/ /r=~/(.{50})/,"\r"),select$.,$.,$.,.02while$|=s/ (\S)/$1 /g;print$/
  • Attenzione-pulito.
  • Può essere schiacciato un po 'riducendo lo spazio tra i caratteri o lo spazio bianco iniziale.
  • Richiede Perl 5.13.2 o più recente a causa dell'uso di /r.
  • La sostituzione a NUL per preservare gli spazi è inequivocabile poiché POSIX argv non è NUL-clean. Tuttavia, la sostituzione del loop trasformerà qualsiasi altro spazio bianco in nulla (eventualmente).

Titoli di coda:


amo il r bandiera, la migliore aggiunta alla lingua da allorastate
Joel Berger

1

bash 234

w=$1
p(){
i=$1
s=$2
p=$((50+s*3-i))
((p<s+1)) && p=$((s+1));
((p<50)) && echo -en "[20;"${p}H$3"  ";
}
clear
for i in {0..99}
do
for s in $(seq 0 ${#w})
do
p $i $s ${w:s:1} 
done
sleep .1
echo -en "[20;1H  "
done
echo -en "\b\b$w\n"

Uso:

./marquee.sh "Hello, fine marquee world"

ungolfed:

#!/bin/bash
w=$1
p(){
    #si String index
    it=$1
    #it=iteration
    si=$2
    pos=$((50+(si*3)-it))
    ((pos<si+1 )) && pos=$((si+1));
    ((pos<50)) && echo -en "[20;"${pos}H$3"  ";
}
clear
for it in {0..99}
do
    for si in $(seq 0 ${#w})
    do
        p $it $si ${w:si:1} 
    done
    sleep .1
    echo -en "[20;1H   "
done
echo -en "[22;1H"

1

R, 319 caratteri

Seguendo la filosofia dell'esempio di @Blazer (d è il ritardo in secondi):

f=function(x,n=50,d=0.2){
    s=strsplit(x,"")[[1]];i=1;l=length
    while (i<(n+l(s)-1)){
        if(i<=l(s))cat(rep(" ", n-i),s[1:i])
        else if((i<=n)&&(i>l(s)))cat(rep(" ", n-i),s[1:l(s)])
        else cat(paste(s[1:(i-n+1)],collapse=""),s[(i-n+2):l(s)])
        Sys.sleep(d);system("clear");i=i+1
    }
    cat(paste(s[1:l(s)],collapse=""))
}

Uso:

f("Hello World",n=20,d=0.2)

1

Perl : 144 133

$|=@s=(($")x50,map{$_,($")x4}@i=split//,pop);{$n=0;$s[$n]ne$_?last:$n++for@i;splice@s,$n,1;print"\r",@s[0..50];sleep.1;$n!=@i&&redo}

Per ottenere il sonno di <1s, devi eseguire come:

perl -MTime::HiRes=sleep scriptname 'string to print'

Dal momento che non mi dichiarerò vincitore, non mi discuterò di ciò che conta lì o no (ma non posso davvero avere Ruby vincere questo ;-))


4 in più e si inserisce in un tweet: D
ajax333221

4 personaggi proprio qui: s/' '/$"/ges/shift/pop/
effimero

sì, avevo incluso quelli, insieme a rimuovere la pushdichiarazione. Non l'avevo ancora pubblicato.
Joel Berger,

0

Q, 145

Non soddisfa esattamente i requisiti perché la riga finale rimuove tutti gli spazi presenti nella stringa di input originale.

{c:2_'((!)(#)a)_'a:((l:3*(#)x)#" "),\(1_(,/)b,'x,'b:" ");{(-1 x;);system"sleep ",($)y}'[-1_c,(l-1)$d(!:)[d]except\(&)(^)d:((!)(#)q)!q:last c;y];}

Sono necessari due argomenti, stringa di input e velocità di scorrimento

q){c:2_'((!)(#)a)_'a:((l:3*(#)x)#" "),\(1_(,/)b,'x,'b:" ");{(-1 x;);system"sleep ",($)y}'[-1_c,(l-1)$d(!:)[d]except\(&)(^)d:((!)(#)q)!q:last c;y];}["hello";0.05]
             h
            h
           h
          h  e
         h  e
        h  e
       h  e  l
      h  e  l
     h  e  l
    h  e  l  l
   h  e  l  l
  h  e  l  l
 h  e  l  l  o
h  e  l  l  o
h e  l  l  o
he  l  l  o
he l  l  o
hel  l  o
hel l  o
hell  o
hell o
hello

purtroppo questo è un punto importante. So che gli script Perl potrebbero diventare molto piccoli senza di essa.
Joel Berger,

0

PowerShell, 135

Non molto golfista e probabilmente un approccio orribile, ma sono malato e non riesco davvero a pensare ...

for($x="`r"+' '*50;$y-ne$x){$y=$x
write-host($x=$x-replace' ([^ ])','$1 ')-n
if(!($t++%5)){$x=$x-replace'.$',"$args"[$i++]}sleep -m 99}

0

J (116)

s(echo@((50#LF)&,)@([[i.@]&2e7)@(50&{.)@;@:(([,~#&' '@])&.>))"1([-=&0@/:@\:@:~:&0)^:(i.>:+/k)k=.50,3#~<:#s=.>2{ARGV

Prende la stringa di input dalla riga di comando, ad es jconsole marquee.ijs 'Hello, world!'

Se non è necessario cancellare lo schermo, ovvero l'output in questo modo:

H  e  l  l  o
H e  l  l  o
He  l  l  o
He l  l  o
...

è consentito, sarebbe più corto di 12 caratteri.

Spiegazione:

  • s.=>2{ARGV: ottiene la stringa dalla riga di comando
  • k.=50,3#~<:#s: la quantità iniziale di spazio bianco aggiunta prima di ogni personaggio, 50 prima del primo e 3 prima di tutti gli altri. (fornisce un array, '50 3 3 3 ... ')
  • ([-=&0@/:@\:@~:&0): dato un array, decrementa il primo elemento diverso da zero nell'array
  • ^:(i.>:+/k): questa funzione ha applicato N volte, dove N è 0 fino alla somma della quantità di spazi bianchi aggiunti. (dà una matrice: 50 3 3 3; 49 3 3 3; 48 3 3 3; ... 0 0 0 1; 0 0 0 0).
  • "1: esegue la seguente funzione su ciascuna riga della matrice
  • ;@:(([,~#&' '@])@.>): aggiungi la quantità di spazi indicata prima di ogni carattere nella stringa
  • (50&{.): accetta i primi 50 caratteri della stringa
  • ([[i.@]&2e7): una funzione che genera l'elenco da 0 a 2 * 10 ^ 7, quindi lo butta via. Questo richiede circa un terzo di secondo sulla mia macchina, questo provoca il ritardo.
  • ((50#LF)&,): aggiungi 50 newline prima della stringa, per cancellare lo schermo
  • echo: emette la stringa
  • s (...): fornisce la stringa come argomento sinistro alla funzione

0

APL (70)

{⎕SM∘←1,⍨1,⍨,/D{⍺,⍨⍵⍴⍕⍬}¨P←⍵-{⍵×~×⍺}\×⍵⊣⎕DL÷8⋄0∨.≠P:∇P}1↓⎕SD,1↓3⍴⍨⍴D←⍞

Prende input dalla tastiera, l'output è nella ⎕SMfinestra (che sarebbe il terminale se avessi un APL basato sul testo, immagino). La dimensione della finestra viene rilevata automaticamente, se vuoi davvero che sia 50, cambia 1↓⎕SDin 50.

Spiegazione:

  • 1↓⎕SD,1↓3⍴⍨⍴D←⍞: leggi la stringa e archivia D. Genera un vettore che descriva la quantità di spazio bianco da aggiungere prima di ogni carattere, che è la larghezza dello schermo prima del primo carattere (1↓⎕SD ) e 3 prima degli altri ( 1↓3⍴⍨⍴D).

  • ⎕DL÷8: attendere 1/8 di secondo

  • P←⍵-{⍵×~×⍺}\×⍵: nel vettore nell'argomento destro, sottrai 1 dall'elemento diverso da zero più a sinistra e memorizza il nuovo vettore in P.
  • ,/D{⍺,⍨⍵⍴⍕⍬}¨P: per ogni carattere in D, aggiungi il prefisso della quantità di spazio bianco indicata in P.
  • ⎕SM∘←1,⍨1,⍨: visualizza sullo schermo, nella colonna più a sinistra della riga superiore
  • 0∨.≠P:∇P: se in P è presente un elemento diverso da zero, ripetere con P.

0

PowerShell , 129 byte

for($x=' '*52+(($args|% t*y)-join' '*4);$x-match'  '){write-host "`r$(-join($x=$x-replace'(?<!  .*)  ')[0..50])  "-n
sleep -m 99}

Provalo online!

Questo script non rimuove gli spazi dagli argomenti in contrasto con lo script di Joey .

TIOnon visualizza correttamente l'output. Con la console Powershell, ottieni la marqueeline a scorrimento.


0

05AB1E , 42 byte

ð¶:S3úJ46ú[D50£¶ð:D?IQ#ðõ.;“…¢('\r')“.eт.W

Provalo online (senza dormire). NOTA: Non ho 05AB1E installato localmente, quindi non sono sicuro al 100% se il \rtrucco funziona (in teoria dovrebbe funzionare, tuttavia). In TIO invece \rsono interpretati come newline. Inoltre, il TIO utilizza la versione legacy, perché.e è disabilitato nella nuova versione TIO (il programma è lo stesso sia nella versione legacy che nella nuova versione 05AB1E).

Spiegazione:

ð¶:            # Replace all spaces in the (implicit) input-string with newlines
   S           # Split the string to a list of characters
    3ú         # Pad each character with 3 leading spaces
      J        # Join the characters together again
       46ú     # And pad the entire string with an additional 46 leading spaces
[              # Now start an infinite loop:
 D             #  Duplicate the string
  50£          #  And leave only the first 50 characters of this copy as substring
     ¶ð:       #  Replace the newlines back to spaces
        D?     #  Duplicate the string, and print it without trailing newline
 IQ            #  If the current string is equal to the input:
   #           #   Stop the infinite loop
 ðõ.;          #  Replace the first space with an empty string to remove it
 “…¢('\r')“    #  Push dictionary string "print('\r')"
           .e  #  Evaluate it as Python code
 т.W           #  Sleep for 100 ms

Vedere questo suggerimento 05AB1E mio (sezione Come utilizzare il dizionario? ) Per capire il motivo per cui “…¢('\r')“è "print('\r')".


0

Python, 139 byte

import os;P='\n'
def f(x,w):
 v=k=P*w+P.join(x);o=str.replace
 while v!=x:os.system('sleep 1;clear');k=o(k,P,'',1);v=o(k,P,' ');print v[:w]

Deve chiamare f('Hello World', 50)per iniziare.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.