LINUX.ORG.RU

Работа с последовательностями в разных языках

 , , , ,


7

9

Навеяно темой Ментальный вирус, пример взят и дополнен оттуда. Интересует реализация подобной операции на других языках. Лично я хотел бы увидеть на Lisp, Java, Smalltalk, Erlang.

array = ["John", "James", "Jakob", "Peter", "Janette", "Tom", "Vasya", "Jean", "Juilia", "Heather"]

puts array.select{|v|v[/^J[a-z]+/]}. # ВЫБРАТЬ ПО someregexp
each_slice(3). # КАЖДЫЙ КУСОК ПО 3 ЭЛЕМЕНТА
map{|v| "#{v[0]} and #{v[1]} follow #{v[2]}"}. # ПОДСТАВИТЬ ЗНАЧЕНИЯ В СТРОКУ
join("\n") # ОБЪЕДИНИТЬ
# John and James follow Jakob
# Janette and Jean follow Juilia

Пошагово для тех, кто не знаком с Ruby:

array.select{|v|v[/^J[a-z]+/]}
# ["John", "James", "Jakob", "Janette", "Jean", "Juilia"]
array.select{|v|v[/^J[a-z]+/]}.
each_slice(3).to_a # в массив
# [["John", "James", "Jakob"], ["Janette", "Jean", "Juilia"]]
array.select{|v|v[/^J[a-z]+/]}.each_slice(3).
map{|v| "#{v[0]} and #{v[1]} follow #{v[2]}"}
# ["John and James follow Jakob", "Janette and Jean follow Juilia"]
array.select{|v|v[/^J[a-z]+/]}.each_slice(3).map{|v| "#{v[0]} and #{v[1]} follow #{v[2]}"}.
join("\n") 
# "John and James follow Jakob\nJanette and Jean follow Juilia"

Использовать только стандартную библиотеку.

Целесообразность операции не важна. Вопрос кратности количества найденных элементов трем не рассматриваем.



Последнее исправление: ymn (всего исправлений: 3)
Ответ на: комментарий от vertexua

штуки помощнее Одерский на курсеровских курсах таки мне рассказал. Я как раз всякие простенькие вещи заменяю

RedPossum ★★★★★
()
Ответ на: комментарий от vertexua

нет, Functional Programming Principles in Scala. Там и про Akka есть?

RedPossum ★★★★★
()
Ответ на: комментарий от vertexua

Когда будет на асме, приходи

когда сделаешь быстрее на асме - тоже забегай

wota ★★
()
Ответ на: комментарий от RedPossum

Держи однострочник на java.

for(int i = 0;
	(i > (new ArrayList<String>(){{
				for(String str : asList("John", "James", "Jakob", "Peter", "Janette", "Tom", "Vasya", "Jean", "Juilia", "Heather"))
					if(str.startsWith("J")) add(str);
			}}.toArray().length - 3)
	? false
	: System.out.format("%s and %s follows %s \n",
		copyOfRange(new ArrayList<String>(){{
			for(String str : asList("John", "James", "Jakob", "Peter", "Janette", "Tom", "Vasya", "Jean", "Juilia", "Heather"))
				if(str.startsWith("J")) add(str);
		}}.toArray(), 0+i, 3+i)) != null
	);
	i+=3);
DiKeert ★★
()
Ответ на: комментарий от RedPossum

На самом деле if(str.startsWith(«J»)) add(str); тоже вносится во внутрение for-ы и все становится еще веселее =).

DiKeert ★★
()
Ответ на: комментарий от anonymous

мне тебя жаль, но ты так ничего и не понял.

себя пожалей, ты так и не научился внятно разговаривать и аргументировать

wota ★★
()

Scala

Один из способов, если я верно понял задачу:

  val list = List("John", "James", "Jakob", "Peter", "Janette", "Tom", "Vasya", "Jean", "Juilia", "Heather")

  for {
    a <- list.filter(_(0) == 'J').sliding(3, 3)
    if a.size == 3
  } println(a(0) + " and " + a(1) + " follow " + a(2))
prozium ★★
()
Ответ на: комментарий от RedPossum

Более аккуратно, без дублирования:

for(final List strs = new ArrayList<String>(){{
		for(String str : asList("John", "James", "Jakob", "Peter", "Janette", "Tom", "Vasya", "Jean", "Juilia", "Heather"))
			if(str.startsWith("J")) add(str);
	}};
	!strs.isEmpty();
	new Callable(){
		@Override
		public Object call() throws Exception {
			System.out.format("%s and %s follows %s \n", copyOfRange(strs.toArray(), 0, 3));
			strs.removeAll(Arrays.asList(copyOfRange(strs.toArray(), 0, 3)));
			return null;
		}
	}.call()
);
DiKeert ★★
()
Ответ на: комментарий от DiKeert

Я думаю вот окончальный вариант однострочника на Java:

for(final List strs = new ArrayList<String>(){{
		for(String str : asList("John", "James", "Jakob", "Peter", "Janette", "Tom", "Vasya", "Jean", "Juilia", "Heather"))
			if(str.startsWith("J")) add(str);
	}};
	!strs.isEmpty();
	new Object(){{
		System.out.format("%s and %s follows %s \n", copyOfRange(strs.toArray(), 0, 3));
		strs.removeAll(Arrays.asList(copyOfRange(strs.toArray(), 0, 3)));
	}}
);
DiKeert ★★
()
Ответ на: комментарий от Zubok

Лично я повеселился развлекаясь с основным совим рабочим инструментом =).

DiKeert ★★
()
Ответ на: комментарий от zz

Еще один вариант на Clojure, но в другом стиле:

(def all-names ["John" "James" "Jakob" "Peter" "Janette" "Tom" "Vasya" "Jean" "Juilia" "Heather"])
 
(defn filter-names-by [regexp, names]
  "...and returns collection of names."
  (filter #(re-matches regexp %) names))
 
(def matched-names (filter-names-by #"J[a-z]+" all-names))
 
(defn names->story [names]
  "Creates astonishing story from plain names."
  (clojure.string/join 
    "\n" 
    (for [[first second third]
          (partition 3 matched-names)]
      (format "%s and %s follow %s" first second third))))
 
(def story (names->story matched-names))
(print story)

За подсветкой синтаксиса можно сходить на http://ideone.com/wqvINE

Anatolik ★★
()
Ответ на: комментарий от Anatolik

Упс, должно быть так:

(def all-names ["John" "James" "Jakob" "Peter" "Janette" "Tom" "Vasya" "Jean" "Juilia" "Heather"])
 
(defn filter-names-by [regexp, names]
  "...and returns collection of names."
  (filter #(re-matches regexp %) names))
 
(def matched-names (filter-names-by #"J[a-z]+" all-names))
 
(defn names->story [names]
  "Creates astonishing story from plain names."
  (clojure.string/join 
    "\n" 
    (for [[first second third]
          (partition 3 names)]
      (format "%s and %s follow %s" first second third))))
 
(def story (names->story matched-names))
(print story)
http://ideone.com/aWFYXA

Anatolik ★★
()
Ответ на: комментарий от wota

Буферы, указатели, операции над ними, memcpy… От читабельности ничего не осталось, а если что менять, то проще переписать :}

Deleted
()
Ответ на: комментарий от Deleted

Буферы, указатели, операции над ними, memcpy…

для сишника или плюсовика - знакомые и родные вещи

От читабельности ничего не осталось, а если что менять, то проще переписать :}

в реальном коде будет нормальное оформление без экономии строк и комментарии

wota ★★
()

разве что для each_slice написать функцию:

array = ["John", "Jorjua", "James", "Jakob", "Peter", "Janette", "Tom", "Vasya", "Jean", "Juilia", "Heather"]

def group(item, count):
    """ Группировка элементов последовательности по count элементов """
    return [item[i:i+count] for i in range(0, len(item), count)]
    
f = group(filter(lambda n: n.startswith("J"), array), 3)

Итого ~ 3 строчки.

anonymous
()

J:

(>@(0&{),' and ',>@(1&{),' follow ',>@(2&{))"1@(]$~3,~%&3@#)@(]#~[:'J'&= 0&{@>"0);:'a b fsdfs sfdfsdv John and James follow Jakob Janette and Jean follow Juilia' 
Выводит:
John and James follow Jakob   
Janette and Jean follow Juilia
У меня фейспалм наворачивается с вашего вон неумнско язкового вонаби функционального петушения.

anonymous
()
Ответ на: комментарий от anonymous

Читаемость:

   format =: (>@(0&{) , ' and ' , >@(1&{) , ' follow ' , >@(2&{))"1
   group =: ] $~ 3 ,~ %&3@#
   select =: ] #~ [: 'J'&= 0&{@>"0
   format group select ;: 'a b fsdfs sfdfsdv John and James follow Jakob Janette and Jean follow Juilia' 
John and James follow Jakob   
Janette and Jean follow Juilia

anonymous
()
<?php

require_once('../config.php');

$array = blib_array::factory(["John", "James", "Jakob", "Peter", "Janette", "Tom", "Vasya", "Jean", "Juilia", "Heather"])
    ->pgrep('/^J[a-z]+/');

while($x = $array->nshift(3))
    echo "{$x[0]} and {$x[1]} follow {$x[2]}\n";

$ php lor-8872206.php 
John and James follow Jakob
Janette and Jean follow Juilia

Так, вроде бы? :) Хотя и не совсем буквально по топикстарту.

KRoN73 ★★★★★
()
Ответ на: комментарий от KRoN73

Кстати, написать each_slice для библиотеки — дело двух строчек. Но неспортивно и мне такая возможность пока явно не нужна :) Поэтому сделал, хоть и менее красиво, но на том, что есть.

KRoN73 ★★★★★
()

идиоматический код на racket

#lang racket
(require racket/match)

(display
 (let* ([names '("John" "James" "Jakob" "Peter" "Janette" "Tom" "Vasya" "Jean" "Juilia" "Heather")]
	[jn (filter (lambda (w) (eq? (string-ref w 0) #\J)) names)])
   (for/fold ([res ""]) ([w jn] [i (in-range (length jn))]) 
     (match (remainder i 3)
       [0 (string-append res w " ")]
       [1 (string-append res "and " w " ")]
       [2 (string-append res "follow " w "\n")]))))
x4DA ★★★★★
()
(flet ((j-str (x) (string-match-p "^J[a-z]+" x))
       (p-str (a b c &rest rest)
              (print (format "%s and %s follow %s" a b c))
              (when rest (apply 'p-str rest))))
  (apply 'p-str
         (remove-if-not
          'j-str '("John"  "James"  "Jakob"  "Peter" "Janette" "Tom" "Vasya" "Jean" "Juilia" "Heather"))))

elisp например. Хотя наверное можно симпатичнее :D

vasily_pupkin ★★★★★
()
Последнее исправление: vasily_pupkin (всего исправлений: 1)
$ perl -E 'print join(" ", "John", "James", "Jakob", "Peter", "Janette", "Tom", "Vasya", "Jean", "Juilia", "Heather") =~ s/\b(J[a-z]+)\b(?:\s|\b[^J][^\s]*\b)*\b(J[a-z]+)\b(?:\s|\b[^J][^\s]*\b)*\b(J[a-z]+)\b(?:\s|\b[^J][^\s]*\b)*/$1 and $2 follow $3\n/gr'
John and James follow Jakob
Janette and Jean follow Juilia
$ _
arsi ★★★★★
()
Ответ на: комментарий от DiKeert

А какой смысл в том, чтобы писать «короче и однострочнее»? Это ведь затрудняет разработку и сопровождение.

Anatolik ★★
()
~$ cat 1.cpp
#include <stdint.h>

int main() {
    struct { const char* s; int len; } v[] = {{"John",4}, {"James",5}, {"Jakob",5}, {"Peter",5}, {"Janette",7}, {"Tom",3}, {"Vasya",5}, {"Jean",4}, {"Juilia",6}, {"Heather",7}};
    char buf[128];

    for(int k=0;k<1000000;++k) {
        int n=0; char* s=buf;
        for( auto i : v ) if(*i.s=='J') {
            if(n++) {
                if(n==2) { *((int64_t*)s)=0x20646e6120; s+=5; }
                else if(n==3) { *((int64_t*)s)=0x20776f6c6c6f6620; s+=8; }
                else { *s++='\n'; n=1; }
            }
            if(i.len<9) {
                *((int64_t*)s)=*((int64_t*)i.s);
                s+=i.len;
            } else {
                for(auto w=i.s;*w;*s++=*w++);
            }
        } 
        *s=0;
    }
}
~$ g++ -O3 -std=c++11 1.cpp && time ./a.out 

real	0m0.015s
user	0m0.012s
sys	0m0.000s

более быстрый (и ужасный) вариант

wota ★★
()
Ответ на: комментарий от anonymous

Вход меняем на 'a b fsdfs sfdfsdv John James Jakob Janette Jean Juilia'

Не дошел, брат аноним, смысл фразы сей, ведь шо так - шо так — однох%йственно.

anonymous
()
Ответ на: комментарий от DiKeert

Видите ли, у нас здесь очень специальное соревнование — меряемся кому чем нравится;)

Anatolik ★★
()
Ответ на: комментарий от anonymous

f = group(filter(lambda n: n.startswith(«J»), array), 3)

Вот чего не пойму, так это что ж вы дальше не пошли

f = 
  group
    3
    filter
      lambda n: 
        n.startswith
          "J"
          array
А что, своеобразненько. А то от endов гордо избавились, а скобок тьма-тьмущая.

special-k ★★★★
()
Последнее исправление: special-k (всего исправлений: 1)
Ответ на: комментарий от wota

Ты совсем поехал уже? Входные данные предобработанные, регекспов нет вообще (J123 - пройдет у тебя, хотя не должен), вывод на stdout добавь, компилировать с -O0, так как это синтетический тест оптимизированный вручную.

anonymous
()
Ответ на: комментарий от vasily_pupkin
(mapconcat #'identity (loop for (fi se th)
                            on (remove-if-not #'(lambda (sn) (string-match-p "^J[a-z]+" sn))
                                              '("John"  "James"  "Jakob"  "Peter" "Janette" "Tom" "Vasya" "Jean" "Juilia" "Heather"))
                            by #'cdddr collect (format "%s and %s follow %s" fi se th)) "\n")
Bad_ptr ★★★★★
()
a = unlines. map (\[a,b,c] -> unwords [a,"and",b,"follow",c]) . slice 3 . filter ((==) 'J' . head)

slice a [] = []
slice a xs = let (h,t) = splitAt a xs
             in h:slice a t
qnikst ★★★★★
()
Ответ на: комментарий от x4DA
;;#lang racket/base
(require unstable/sequence
         racket/match)

(define ((with-rx rx) v)
  (regexp-match? rx v))

(define names (list "John" "James" "Jakob" "Peter" "Janette" "Tom" "Vasya" "Jean" "Juilia" "Heather"))

(define filtered (filter (with-rx #rx"^J[a-z]+") lst))

(display
  (for/fold ([result ""])
    ([lst (in-slice 3 (in-list filtered))])
    (match-define (list a b c) lst)
    (define str (format "~a and ~a follow ~a\n" a b c))
    (string-append result str)))
qaqa ★★
()
Ответ на: комментарий от dr_jumba

Интересно, как будет выглядеть код на руби, если пропатчить задачу, наложив проверки, что если в подпоследовательности три элемента, печатаем A and B follow C, если два — A and B, если один — A. На руби получится это сделать также «однострочно» как в стартовом посте? Для затравки, немного модифицированный мой вчерашний вариант на лишпике:

(format nil "~{~a~^ and ~a~^ follow ~a~^~%~}"
	(remove-if-not
	 (lambda (x) (eql (elt x 0) #\J))
	 '("John" "James" "Jakob" "Peter" "Janette" "Tom" "Vasya" "Heather")))
staseg ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.