2010-06-06 31 views
4

Je travaille depuis longtemps sur une fonction J, qui est supposée balayer une liste et placer des copies consécutives d'un élément dans des boîtes séparées et concaténées. Mes efforts me ont pris dans la mesure où la fonctionRésumé des structures matricielles encadrées dans J

(<;. 2) ((2&(~:/\)),1:)

qui teste les entrées de liste successives pour l'inégalité, renvoie une liste de valeurs booléennes, et coupe la liste dans des boîtes qui se terminent à chaque fois que le numéro 1 apparaît. Voici un exemple d'application:

(<;. 2) ((2&(~:/\)),1:) 1 2 3 3 3 4 1 1 1 
+-+-+-----+-+-----+ 
|1|1|0 0 1|1|0 0 1| 
+-+-+-----+-+-----+ 

La tâche serait terminée si je pouvais alors remplacer tous les booléens avec leurs valeurs correspondantes dans l'argument d'entrée. J'ai cherché une sorte de fonction de mystère qui me permettrait de faire quelque chose comme

final =: mysteryfunction @ (<;. 2) ((2&(~:/\)),1:) 

    final 1 2 3 3 3 4 1 1 1  
+-+-+-----+-+-----+ 
|1|2|3 3 3|4|1 1 1| 
+-+-+-----+-+-----+ 

Dans une situation idéale, il y aurait un moyen de représenter abstraitement le modèle de nidification généré par (<;. 2) ((2&(~:/\)),1:) et l'appliquer à l'original liste d'entrée. (c'est-à-dire "Ce tableau contient le premier élément encadré en profondeur un, le deuxième élément encadré en profondeur un, les troisième, quatrième et cinquième éléments encadrés en profondeur un, ..., alors prenez cette liste sans boîte ») J'ai essayé de tromper avec ;., S:, L:, L. et &. pour produire ce comportement, mais je n'ai pas eu beaucoup de chance. Y a-t-il une sorte d'opérateur ou de principe qui me manque pour que cela se produise? Cela ne me surprendrait pas si je réfléchissais à toute la question, mais je suis à court d'idées.

EDIT:

À l'heure actuelle, la seule solution de travail que j'ai est celui-ci:

isduplicate =: ((2&(~:/\)),1:) 

testfun =: 3 : 0 
numduplicates =. #S:0 ((<;.2) isduplicate y) 
distinctboxes =. <"0 (isduplicate#]) y 
numduplicates # each distinctboxes 
) 

C'est un processus en deux étapes de génération du codage de longueur d'exécution de la liste, puis défaisant l'encodage sans se débarrasser des boîtes. Comme je le fais à l'origine dans le but de résoudre le 99 problems en tandem en utilisant J et Haskell, je me demande si je résous le problème 9 en résolvant d'abord le problème 12.

Répondre

2

Vous y êtes presque. Ajouter un ~ et placez les parenthèses différemment, et c'est tout:

(<;.2~ (2&(~:/\) , 1:)) 1 2 3 3 3 4 1 1 1 
┌─┬─┬─────┬─┬─────┐ 
│1│2│3 3 3│4│1 1 1│ 
└─┴─┴─────┴─┴─────┘ 

Une explication/illustration rapide:

s =: 1 2 3 3 3 4 1 1 1 

    f =: 2&(~:/\) , 1: 
    f s 
1 1 0 0 1 1 0 0 1 

    g =: <;.2 

    (f s) g s 
┌─┬─┬─────┬─┬─────┐ 
│1│2│3 3 3│4│1 1 1│ 
└─┴─┴─────┴─┴─────┘ 

Maintenant que (f s) g s finale, parfois comme un « crochet gauche », peut être écrit (g~ f) s (l'adverbe ~ est appelé "passive" en J, l'homologue Haskell serait flip). Alternativement, vous pouvez également écrire tacitement comme la fourchette (f g ]) s.

Chapter 9 of "Learning J" traite abondamment ce sujet, si vous voulez en savoir plus.

Mise à jour: J'ai précédemment utilisé un (</.~ (+/\&(1,(2&(~:/\))))) de regroupement, mais votre approche originale basée sur les coupes est plus élégante (et plus courte) que celle-ci. Comme il s'agit vraiment du crochet gauche, j'ai mis à jour pour utiliser votre approche directement.

+0

Voilà comment vous faites cela! J'ai passé des jours à fouiller dans la documentation, essayant de faire en sorte que J applique des boîtes aux éléments en utilisant une sortie booléenne. Merci pour l'aide. – estanford

+0

De rien. En regardant par-dessus, j'ai probablement * devrait * avoir mentionné que cela utilise __dyadic__ cut ('; .2) au lieu de l'utilisation monadique de couper dans votre code d'origine. Et une dernière remarque: si nous allions chercher la brièveté du code (et aussi la clarté, imo) je l'écrirais probablement en utilisant la variante cut-1 (au lieu de cut-2), qui se scinde en 1: '(<;. 1 ~ 1,2 & (~:/\)) '- agréable et juteuse! – earl

0

Cette version de la fonction que j'avais dans l'esprit est meilleur, mais pas encore assez tacite pour être parfait. (Au moins, cela ne posera pas la question d'un autre problème sur la route, en tout cas.) Une fois que je trouverai comment représenter la logique de cette boucle en tant qu'expression tacite, je serai prêt.

NB. boxmerge takes a boxed argument and razes the first two 
NB. elements together into a new box. 
boxmerge =: [:}.]1}~[:<[:;2&{. 

NB. conseq checks to see whether the first two boxes of a boxed 
NB. array contain the same distinct element. (By assumption, each 
NB. box contains only one distinct element.) The name is an 
NB. abbreviation of the question, "consecutive boxes equal?" 
conseq =: [:=/[:~.&.>2&{. 

partfun =: ]`(boxmerge)@.conseq ^:_ 

listpack =: 3 : 0 
mylist =. y 
listbin =. >a: 
while. (mylist -: (>a:)) = 0 do. 
newlist =. partfun mylist 
listbin =. listbin,{. newlist 
mylist =. }. newlist 
end. 
listbin 
) 

L'idée derrière la boucle while est d'appliquer partfun à une liste, ravel la tête sur une autre liste, décapitent la liste initiale et continuer à le faire jusqu'à ce que la liste initiale a été complètement vidé. J'ai l'impression qu'il devrait y avoir un moyen de représenter cette logique avec des expressions tacites. (En fait, je pense que je l'ai même vu dans la documentation en ligne.) Je ne peux pas penser à la séquence appropriée de ^:, $: et @. 's j'ai besoin de mettre le dernier clou dans le cercueil .

1

Je pense que vous y pensez trop. Faut-il être complètement tacite? Voici quelque chose que je viens de jeter ensemble:

s<;.2~ ((2&(~:/\)),1:) s=:1 2 3 3 3 4 1 1 1 
┌─┬─┬─────┬─┬─────┐ 
│1│2│3 3 3│4│1 1 1│ 
└─┴─┴─────┴─┴─────┘ 

Évidemment, il attribue simplement la liste d'entrée de gouttes puis dans l'expression ;..Si cela doit être complètement tacite, je suis sûr que vous pouvez le masser pour passer la liste d'entrée à la liste booléenne, puis utiliser quelque chose comme {. < ;.2 {: pour obtenir la sortie.