La chaîne X est-elle une sous-séquence de la chaîne Y?

23

Étant donné les chaînes X et Y, déterminez si X est une sous- séquence de Y. La chaîne vide est considérée comme une sous-séquence de chaque chaîne. (Par exemple, ''et 'anna'sont des sous-séquences de 'banana'.)

Contribution

  • X, une chaîne alphanumérique sensible à la casse éventuellement vide
  • Y, une chaîne alphanumérique sensible à la casse éventuellement vide

Sortie

  • Vrai ou faux (ou équivalents), indiquant correctement si X est une sous-séquence de Y.

Exemples d'E / S

X      Y        output

''     'z00'    True
'z00'  'z00'    True 
'z00'  '00z0'   False
'aa'   'anna'   True
'anna' 'banana' True
'Anna' 'banana' False

Critères

  • Le programme le plus court gagne, comme déterminé par le nombre d'octets de code source.

Exemples de programmes

res
la source
1
Pourquoi est «anna» substr de «banane»?
kaoD
4
@kaoD - annaest une sous- séquence (mais pas une sous-chaîne) de banana. La chaîne X est une sous-séquence de la chaîne Y juste si X peut être obtenu à partir de Y en supprimant zéro ou plusieurs des éléments de Y; par exemple, en supprimant le bet le second ade bananadonne anna.
res
2
Cela a environ une solution unique dans chaque langage de script offrant des regex qui sont à la fois triviales à voir et impossibles à jouer plus loin.
Joey

Réponses:

18

Perl 5 , 17 octets (+1?), Programme complet

s//.*/g;$_=<>=~$_

Essayez-le en ligne!

Appelez avec le pdrapeau à l'interpréteur perl, comme dans perl -pe 's//.*/g;$_=<>=~$_'. Selon les règles de notation établies lorsque ce défi a été initialement publié , ce drapeau coûte un octet supplémentaire. Selon des règles plus récentes , AFAICT, il peut être gratuit.

Dans les deux cas, les chaînes d'entrée doivent être fournies sur des lignes séparées par des retours à la ligne sur stdin. La sortie (vers stdout) sera 1si la première chaîne d'entrée est une sous-chaîne de la seconde, ou rien du tout si ce n'est pas le cas.

Notez que les deux lignes d'entrée doivent avoir une nouvelle ligne à la fin, sinon le programme ne fonctionnera pas correctement. Alternativement, vous pouvez ajouter l' lindicateur de ligne de commande à l'invocation pour que perl supprime les sauts de ligne; selon les règles de notation en vigueur, cela peut ou non coûter un octet supplémentaire. Notez que l'utilisation de cet indicateur ajoutera également une nouvelle ligne à la sortie.

Version originale (extrait, 18 octets / caractères)

$x=~s//.*/g,$y=~$x

L'entrée est donnée dans les variables $xet le $yrésultat est la valeur de l'expression (dans un contexte scalaire). Notez que cela $xest modifié dans le processus. (Oui, je sais que l'utilisation $_au lieu de $xme permettrait d'enregistrer quatre caractères, mais le faire dans un extrait de code qui me semble un peu trop ringard.)

Comment ça marche?

La première partie $x=~s//.*/g,, insère la chaîne .*entre chaque caractère dans $x. La deuxième partie, $y=~$xtraite $xcomme une expression rationnelle et correspond $yà elle. Dans les expressions rationnelles Perl, .*correspond à zéro ou plusieurs caractères arbitraires, tandis que tous les caractères alphanumériques se correspondent facilement.

Ilmari Karonen
la source
Selon un consensus (nouveau?), Les soumissions doivent être un programme ou une fonction, pas un extrait. Si votre soumission ne satisfait pas cela, pensez à la modifier.
user202729
@ user202729: Ce défi est beaucoup plus ancien que ce consensus, donc à moins qu'il ne soit supposé s'appliquer rétroactivement, les réponses dans ce fil devraient probablement être "grandfathered". Cela dit, je viens d'ajouter une version conforme aux règles actuelles, et peut même être un octet / caractère plus court (notez que le comptage basé sur les octets est également plus récent que ce défi, AFAIK) selon la façon dont vous comptez les commutateurs de ligne de commande.
Ilmari Karonen
9

Ruby, 32 caractères

s=->x,y{y=~/#{[*x.chars]*".*"}/}

Cette solution renvoie nilsi xn'est pas une sous-séquence de yet un nombre dans le cas contraire (c'est-à-dire des équivalents rubis à falseet true). Exemples:

p s['','z00']        # => 0   (i.e. true)
p s['z00','z00']     # => 0   (i.e. true)
p s['z00','00z0']    # => nil (i.e. false)
p s['anna','banana'] # => 1   (i.e. true)
p s['Anna','banana'] # => nil (i.e. false)
Howard
la source
1
j'ai fait essentiellement la même chose, mais c'est trop similaire donc je ne le posterai pas. Je pense qu'il est acceptable de laisser le lambda, ce qui vous laisserait avec y=~/#{[*x.chars]*".*"}/(23 caractères). à votre santé!
Patrick Oscity
1
ou même y=~/#{x.split("")*".*"}/(21 caractères) :)
Patrick Oscity
@padde Le split est en fait 24 caractères.
Howard
1
désolé, je suppose que j'ai accidentellement laissé de côté y=~pendant que je
tripotais
Ma version est plus courte de 2 caractères.
Hauleth
7

Haskell, 51 37

h@(f:l)%(g:m)=f==g&&l%m||h%m;x%y=x<=y

Merci à Hammar pour cette amélioration substantielle. C'est maintenant une fonction infixe, mais il ne semble pas y avoir de raison qu'elle ne le soit pas.

Manifestation:

GHCi> :{
GHCi| zipWith (%) [""   , "z00", "z00" , "anna"  , "Anna"]
GHCi|             ["z00", "z00", "00z0", "banana", "banana"]
GHCi| :}
[True,True,False,True,False]
a cessé de tourner dans le sens antihoraire
la source
Étant donné que la liste vide est plus petite que toute autre liste, vous pouvez simplifier les cas de base pour s x y=x<=y. En outre, vous pouvez en enregistrer quelques autres en en faisant un opérateur et en utilisant un @-pattern au lieu de (f:l). Cela le réduit à 37 caractères:h@(f:l)%(g:m)=f==g&&l%m||h%m;x%y=x<=y
hammar
6

Python (48 caractères)

import re;s=lambda x,y:re.search('.*'.join(x),y)

Même approche que la réponse Ruby d'Howard. Dommage sur le besoin de Python d'importer le paquet regex et son "verbose" lambda. :-)

Eric
la source
1
Je suis d'accord, lambda est verbeux.
CalculatorFeline
4

Python, 59 caractères

def s(x,y):
 for c in y:
  if x:x=x[c==x[0]:]
 return x==""

J'ai pensé que ma réponse serait mieux exprimée en Python.

Edit: Ajout des suggestions de res.

Gareth
la source
Sûrement donné x="a"et y="ab"vous sortiriez de la boucle avec y=="b"et reviendriez false?
Peter Taylor
@PeterTaylor Oui, j'ai remarqué quand j'exécutais les exemples comme tests après avoir posté que j'avais mélangé xet yplus. Dans mes fonctions ydoit être une sous-séquence de x. Je pense que je ferais mieux de les changer pour éviter toute confusion.
Gareth
Vous pouvez obtenir ce jusqu'à 59 caractères: def s(x,y): for c in y: if x:x=x[c==x[0]:] return x=="". Il ne s'affiche pas correctement dans un commentaire, mais je pense que vous pouvez voir ce que je veux dire. (De plus, un espace supplémentaire suffit pour augmenter le niveau de retrait.)
res
@res Merci, Python n'est pas un langage que j'utilise autant que vous pouvez probablement le dire. Bon golf. (63 caractères selon le script utilisateur Codegolf - il faut compter les nouvelles lignes).
Gareth
1
Vous pouvez utiliser l'extension de découpage pour vous protéger contre x ''et enregistrer plusieurs caractères en écrivantx=x[c==x[0:1]:]
Nolen Royalty
4

GolfScript (22 caractères)

X[0]+Y{1$(@={\}*;}/0=!

Suppose que l'entrée est considérée comme deux variables prédéfinies Xet Y, bien que cela soit plutôt inhabituel dans GolfScript. Laisse 1pour vrai ou 0pour faux sur la pile.

Peter Taylor
la source
4

C (52 caractères)

s(char*x,char*y){return!*x||*y&&s(*x-*y?x:x+1,y+1);}

Cas de test

Peter Taylor
la source
s(char*x,char*y){x=!*x||*y&&s(x+(*x==*y),y+1);}
l4m2
4

Burlesque (6 caractères)

6 caractères dans Burlesque: R@\/~[ (en supposant que x et y sont sur la pile. Voir ici en action.)

mroman
la source
3

PHP, 90 caractères

<?function s($x,$y){while($a<strlen($y))if($y[$a++]==$x[0])$x=substr($x,1);return $x=="";}
Gareth
la source
Vous pouvez supprimer la ifdéclaration et simplifier $x=substr($x,$y[$a++]==$x[0]): ideone.com/Ch9vK
mellamokb
Voici également une solution de 82 caractères légèrement plus courte utilisant la récursivité: ideone.com/IeBns
mellamokb
3

Scala 106:

def m(a:String,b:String):Boolean=(a.size==0)||((b.size!=0)&&((a(0)==b(0)&&m(a.tail,b.tail))||m(a,b.tail)))
Utilisateur inconnu
la source
3

CoffeeScript 112 100 95 89

Ma première tentative de code golf ... j'espère que je n'ai pas honte à ma famille!

z=(x,y)->a=x.length;return 1if!a;b=y.indexOf x[0];return 0if!++b;z x[1..a],y[b..y.length]

Edit : il s'avère que Coffeescript est plus indulgent que je ne le pensais avec les espaces blancs.

Merci à res et Peter Taylor pour quelques conseils pour le rendre un peu plus élégant

Johno
la source
Quelques autres caractères peuvent être éliminés comme suit (ce ne sera pas afficher droit dans un commentaire, mais je pense que vous pouvez voir ce que je veux dire): z=(x,y)-> a=x.length return 1if a==0 b=y.indexOf x[0] return 0if b<0 z x[1..a],y[b+1..y.length]. (Dans certains navigateurs, par exemple Chrome, vous pouvez voir le code de commentaire correctement affiché en cliquant avec le bouton droit, puis en inspectant l'élément.)
res
a.lengthne sera jamais négatif, vous pouvez donc enregistrer un caractère de plus en le remplaçant if a==0par if a<1. Je ne sais pas comment fonctionne la tokenisation de CoffeeScript, mais s'il lexe if0comme deux tokens, vous pouvez en enregistrer deux de plus en inversant les deux conditions (ie if1>a).
Peter Taylor
Bons points. if1>an'est pas valide, mais if!aest et est un caractère plus court! J'ai aussi réalisé que je pouvais raser un caractère supplémentaire conversion b+1à bet incrémenter sur la ligne précédente, ce qui rend également la même ifastuce possible car il avait affaire à un 0 / situation de non-0.
Johno
3

C #, 70 113 107 90 caractères

static bool S(string x,string y){return y.Any(c=>x==""||(x=x.Remove(0,c==x[0]?1:0))=="");}
mizer
la source
6
Cela ne recherche-t-il pas une sous-chaîne plutôt qu'une sous-séquence?
Gareth
oui, j'ai mal lu. Devrait être corrigé maintenant.
mizer
1
Aussi amusant que Linq soit, je pense que vous pouvez économiser 10% en utilisant la récursivité à la place.
Peter Taylor
Voici ma meilleure tentative. Encore plus longtemps. static bool S(string x,string y){if(x!=""&&y=="")return false;return x==""||S(y[0]==x[0]?x.Remove(0,1):x,y.Remove(0,1));}
mizer
Vous pouvez réduire le récursif à x==""||y!=""&&S(...), mais il est toujours plus long que la version mise à jour de Linq. Bonne utilisation de Any!
Peter Taylor
3

Mathematica 19 17 27

LongestCommonSequencerenvoie la plus longue sous-séquence non contiguë de deux chaînes. (À ne pas confondre avec LongestCommonSubsequence, qui renvoie la sous-séquence contiguë la plus longue.

Ce qui suit vérifie si la sous-séquence contiguë la plus longue est la première des deux chaînes. (Vous devez donc entrer la chaîne la plus courte suivie de la plus grande.)

LongestCommonSequence@##==#& 

Exemples

LongestCommonSequence@## == # &["", "z00"]
LongestCommonSequence@## == # &["z00", "z00"]
LongestCommonSequence@## == # &["anna", "banana"]
LongestCommonSequence@## == # &["Anna", "banana"]

Vrai Vrai Vrai Faux

Le test critique est le troisième, car "anna" est contenue non contiguë dans "banana".

DavidC
la source
3

Python 3.8 (version préliminaire) , 42 octets

lambda a,b:''in[a:=a[a[:1]==c:]for c in b]

Essayez-le en ligne!

Python 3.8 (pré-version) , 48 octets

lambda a,b,j=0:all((j:=1+b.find(c,j))for c in a)

Essayez-le en ligne!

Python 2 , 48 octets

lambda a,b:re.search('.*'.join(a),b)>0
import re

Essayez-le en ligne!

Copié de cette réponse de Lynn . Le >0peut être omis si la sortie vérité / falsey est correcte.

Python 2 , 50 octets

f=lambda a,b:b and f(a[a[:1]==b[0]:],b[1:])or''==a

Essayez-le en ligne!

Python 2 , 50 octets

lambda a,b:reduce(lambda s,c:s[c==s[:1]:],b,a)==''

Essayez-le en ligne!

xnor
la source
Grande utilisation du morse.
Jonathan Allan
2

C - 74 71 64

Cela ne bat pas la solution de Peter Taylor, mais je pense que c'est assez amusant (en plus, c'est un programme de travail complet, pas seulement une fonction)

main(int c,char**v){for(;*v[1]!=0;++v[1])v[2]+=*v[1]==*v[2];return*v[2];}

main(int c,char**v){for(;*v[1];++v[1])v[2]+=*v[1]==*v[2];return*v[2];}


main(c,v)char**v;{while(*v[1])v[2]+=*v[1]++==*v[2];return*v[2];}

Et non golfé:

main(int argc, char** argv){
   char * input = argv[1];
   char * test  = argv[2];

   // advance through the input string. Each time the current input
   // character is equal to the current test character, increment
   // the position in the test string.

   for(; *input!='\0'; ++input) test += *input == *test;

   // return the character that we got to in the test string.
   // if it is '\0' then we got to the end of the test string which
   // means that it is a subsequence, and the 0 (EXIT_SUCCESS) value is returned
   // otherwise something non-zero is returned, indicating failure.
   return *test;
}

Pour le tester, vous pouvez faire quelque chose comme:

./is_subsequence banana anna && echo "yes" || echo "nope"    
# yes
./is_subsequence banana foobar && echo "yes" || echo "nope"    
# nope
Gordon Bailey
la source
!=0dans une condition est un peu verbeux ... Le programme vs fonction est quelque chose que la question doit spécifier clairement, et ici ce n'est pas le cas, donc les réponses prennent différentes options.
Peter Taylor
Merde, c'est !='\0'une mauvaise (bonne?) Habitude d'écrire du code non-golf, je l'ai laissé glisser dans mes deux dernières rondes de golf, je devrai être plus prudent à l'avenir. Quant au programme vs fonction, oui, vous avez absolument raison.
Gordon Bailey
@GordonBailey désolé pour la bosse, mais j'ai apporté quelques modifications dans une version plus courte.
oldrinb
2

Python, 66 62 59 58 caractères

Une sorte de solution amusante, certainement un problème soigné.

def f(n,h,r=0):
 for c in h:r+=n[r:r+1]==c
 return r==len(n)
Nolen Royalty
la source
2

Rubis 32 30 28

f=->a,b{b.match a.tr'','.*'}

Cela retournera l' MatchDatainstance si aest une sous-séquence de bou nilautrement.

Ancienne version qui trouve une sous-chaîne au lieu d'une sous-séquence

Rubis 15

f=->a,b{!!b[a]}

En utilisant une String#[](str)méthode qui retourne strif strest une sous-chaîne de selfet !!pour retourner Booleansi la valeur retournée peut être utilisable en tant que booléen (et n'a pas besoin d'être trueou false), elle ne peut être que de 13 caractères:

f=->a,b{b[a]}

Il retournera nilsi an'est pas une sous-chaîne de b.

Hauleth
la source
2
Bien, mais la question demande une sous-séquence plutôt qu'une sous-chaîne.
Gareth
2

SWI-Prolog, SICStus

La sous- liste de prédicats intégrée / 2 de SICStus vérifie si tous les éléments de la première liste apparaissent également dans la deuxième liste. Ce prédicat est également disponible dans SWI-Prolog via une bibliothèque de compatibilité, qui peut être chargée par la requête [library(dialect/sicstus/lists)]..

Exemple d'exécution:

25 ?- sublist("","z00").
true.

26 ?- sublist("z00","z00").
true .

27 ?- sublist("z00","00z0").
false.

28 ?- sublist("aa","anna").
true .

29 ?- sublist("anna","banana").
true .

30 ?- sublist("Anna","banana").
false.

Le nombre d'octets peut être techniquement égal à 0, car tout ce que nous faisons ici est d'interroger, tout comme la façon dont nous exécutons un programme et lui fournissons une entrée.

n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳
la source
2

PHP, 41 octets

imprime 1 pour vrai et rien pour faux

<?=!levenshtein($argv[1],$argv[2],0,1,1);

Si seules les insertions du mot 1 au mot 2 sont effectuées, le compte est nul pour les cas réels

levenshtein

Essayez-le en ligne!

PHP, 57 octets

imprime 1 pour vrai et 0 pour faux

Crée une expression régulière

<?=preg_match(_.chunk_split($argv[1],1,".*")._,$argv[2]);

Essayez-le en ligne!

Jörg Hülsermann
la source
1
-2 octets: l'interlignage .*n'est pas nécessaire. -2 octets: ne pas attribuer $argvà $a. +24 octets: besoin array_map(preg_quote())de caractères spéciaux (utilisez des parenthèses comme délimiteurs pour éviter le deuxième preg_quoteparamètre.)
Titus
2
@Titus le début. * Est nécessaire pour l'entrée d'une chaîne vide et pour l'entrée je ne dois gérer qu'une chaîne alphanumérique sensible à la casse éventuellement vide. Vous avez raison avec la citation s'il y a des caractères spéciaux. Merci d'avoir compté l'assigné. Copiez et collez par une solution antérieure et n'y pensez pas
Jörg Hülsermann
1
preg_matchne se plaindra pas d'une expression régulière vide tant que les délimiteurs sont là. Cela correspondra à tout. Mais preg_quote est seulement +22 octets, et non +24: array_map(preg_quote,str_split(...)).
Titus
1
Mais alors, la saisie est garantie d'être alphanumérique :) Mais vous n'avez toujours pas besoin du leader .*.
Titus
2

Brachylog , 2 octets

⊆ᵈ

Essayez-le en ligne!

Comme avec cette réponse, est un prédicat intégré qui déclare une relation entre les variables d'entrée et de sortie, et est un méta-prédicat qui le modifie pour déclarer cette même relation entre les premier et deuxième éléments de la variable d'entrée à la place (et unifier la variable de sortie avec le deuxième élément mais comme c'est un problème de décision qui ne finit pas par avoir d'importance ici). X⊆Yest une affirmation que X est une sous-séquence de Y, donc c'est le cas [X,Y]⊆ᵈ.

Ce prédicat (qui bien sûr sort par le succès ou l'échec qui s'imprime true.ou false.lorsqu'il est exécuté en tant que programme) prend l'entrée comme une liste de deux chaînes. Si l'entrée est un peu plus flexible ...

Brachylog , 1 octet

Essayez-le en ligne!

Prend la chaîne X comme variable d'entrée et la chaîne Y comme variable de sortie. Sorties par succès ou échec, comme précédemment. S'il est exécuté en tant que programme complet, X est fourni comme entrée et Y est fourni comme premier argument de ligne de commande.

Chaîne indépendante
la source
1

CoffeeScript 73

Voici une réponse alternative à CoffeeScript, en utilisant des expressions rationnelles au lieu de la récursivité:

z=(x,y)->a='.*';a+=c+'.*'for c in x;b=eval('/'+a+'/');(y.replace b,'')<y

Si la botte de foin correspond à une expression rationnelle très gourmande construite à partir de l'aiguille, elle sera remplacée par une chaîne vide. Si la botte de foin est plus courte qu'elle n'a commencé, l'aiguille était une sous-séquence.

Renvoie false lorsque xet ysont deux chaînes vides. Pensez que nous avons besoin d'un philosophe pour nous dire si une chaîne vide est une sous-séquence d'elle-même!

(Publié comme une réponse distincte de ma précédente car elle semble suffisamment différente pour la justifier).

Johno
la source
1

PowerShell, 38

$args[1]-clike($args[0]-replace'','*')

Bien sûr, une telle solution basée sur l'expression rationnelle ou la correspondance de modèles présente de graves problèmes de performances avec des chaînes plus longues. Mais comme la brièveté est le critère ...

Joey
la source
1

Une sorte d'anti-solution générant toutes les sous-séquences de Y:

Python 93

l=len(y)
print x in[''.join(c for i,c in zip(bin(n)[2:].rjust(l,'0'),y)if i=='1')for n in range(2**l)]
daniero
la source
1

APL (31)

La gestion des chaînes fait un peu défaut dans APL.

{(⊂'')∊N←⍵↓⍨¨1,⍨=/⊃¨⍵:~×⍴⊃N⋄∇N}

usage:

      {(⊂ '') ∊N ← ⍵ ↓ ⍨¨1, ⍨ = / ⊃¨⍵: ~ × ⍴⊃N⋄∇N} 'anna' 'banane'
1
      {(⊂ '') ∊N ← ⍵ ↓ ⍨¨1, ⍨ = / ⊃¨⍵: ~ × ⍴⊃N⋄∇N} 'Anna' 'banane'
0
      {(⊂ '') ∊N ← ⍵ ↓ ⍨¨1, ⍨ = / ⊃¨⍵: ~ × ⍴⊃N⋄∇N} '' 'banane'
1
marinus
la source
1

Python 132

Similaire à Daniero. Ce n'était pas la solution la plus simple, mais c'était amusant à essayer. Je suis nouveau sur Python, donc je suis sûr que je pourrais le raccourcir si j'en savais un peu plus.

def f(i):
    s=x;j=0
    while j<len(s):t=~i%2;s=[s[:j]+s[j+1:],s][t];j+=t;i>>=1
    return s==y
print True in map(f,range(1,2**len(x)))
scleaver
la source
1

Python - 72

def f(a,b):
 c=len(a)
 for i in b:a=a.replace(i,"",1)
 print len(a+b)==c
Homme de codage
la source
1

Python ( 75 52)

s=lambda a,b:a==''or b>''and s(a[a[0]==b[0]:],b[1:])

Solution récursive simple. Golf pour la première fois, donc tous les conseils pour le réduire sont très appréciés :)

Testé avec les éléments suivants:

assert s('anna', 'banana') == True
assert s('oo0', 'oFopp0') == True
assert s 'this', 'this is a string') == True
assert s('that', 'this hat is large') == True
assert s('cba', 'abcdefg') == False

Merci à @lirtosiast pour quelques astuces booléennes intelligentes.

foslock
la source
1
Vous pouvez le réduire à 52 caractères:s=lambda a,b:a==''or b>''and s(a[a[0]==b[0]:],b[1:])
lirtosiast
Merci, c'est intelligent, en utilisant le booléen comme index 0/1 dans l'épissure :)
foslock
1

PHP, 75 65 64 octets

for(;$p=@strpos(_.$argv[2],$c=$argv[1][$i++],$p+1););echo""==$c;

prend l'entrée des arguments de la ligne de commande; affiche 1pour vrai, chaîne vide pour faux. Courez avec -r.

explication:

  • strposrevient falsesi l'aiguille $cn'est pas dans la botte de foin $argv[2](après la position $p),
    provoquant la rupture de la boucle.
  • strposrevient également falsepour une aiguille vide, rompant la boucle à la fin de $argv[1].
  • Si $argv[1]est une sous-séquence de $argv[2], $csera vide lorsque la boucle se cassera.
  • strposdoit @supprimer l' Empty needleavertissement.
Titus
la source
+$pau lieu de cela $p+1après il n'y a pas besoin de souligner
Jörg Hülsermann
@ JörgHülsermann +1 est nécessaire pour avancer dans la chaîne de meule de foin; et le trait de soulignement évite l' $p=-1initialisation. Mais ... je peux éviter false!==.
Titus
1

Swift, 27

print(Y.range(of:X) != nil)
Dimitrie-Toma Furdui
la source
Bienvenue chez PPCG!
Martin Ender