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)

Ответ на: комментарий от DiKeert
strs.removeAll(Arrays.asList(copyOfRange(strs.toArray(), 0, 3)));

замени на

strs.subList(0, 3).clear();
иначе при повторении имен у тебя код с ума сойдет. и это если не считать того, что в твоем коде многократно пересоздается массив со строками.

maloi ★★★★★
()
Последнее исправление: maloi (всего исправлений: 1)

О, Олимпиада продолжается? =)

package main

import . "regexp"
import . "fmt"

func main() {
	array := []string{"John", "James", "Jakob", "Peter", "Janette", "Tom", "Vasya", "Jean", "Juilia", "Heather"}
	filtered := make(chan string)
	go func() {
		for _, s := range array {
			matched, _ := MatchString("^J[a-z]+", s)
			if matched { filtered <- s }
		}
		close(filtered)
	}()
	first := true
	for x := range filtered {
		y := <-filtered
		z := <-filtered
		if first { first = false } else { Println() }
		Printf("%s and %s follow %s", x, y, z)
	}
}
korvin_ ★★★★★
()
Ответ на: комментарий от dr_jumba

А можно еще на Форте, пожалуйста? :)

На JBForth у меня почти ничего не было, что бы пригодилось для сабжевой задачи. Только сами массивы, да циклы по ним. Регулярных выражений не было. Можно подцепить любую популярную библиотеку в виде jar, но это лишние строки и некрасиво :)

JBForth2, в котором такое можно бы было сделать аналогично и красиво [пока?] так и не стартовал.

Ну а на классическом Форте нет регулярных выражений :) Так что задачу придётся решать с лишними словами... Хотя, в принципе, получится не так уж и сложно, если решать именно эту задачу. Надо будет подумать на этот счёт :) С другой стороны, в классическом Форте строки не очень для таких задач удачные (addr u).

KRoN73 ★★★★★
()

Вот не могу понять, что двигало авторами руби, когда они включили в стандартную библиотеку each_sliced. Да, задача - мерялка стандартными библиотеками.

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

Т.е. ты не знаешь примеры быдлокода, но утверждаешь, что не быдлокодер?

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

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

array.select{|v|v[/^J[a-z]+/]}.
each_slice(3).
map{|v| "#{v[0]}#{v[1]&&' and '+v[1]}#{v[2]&&' follow '+v[2]}"}.
join("\n")
dr_jumba
() автор топика
Ответ на: комментарий от anonymous

python - 6.4sec
ruby - 12.6sec

Упс, версия питона без регекспов была. с регекспом python2.7 за 14 сек отработал, а pypy за 4сек

anonymous
()

версия на JS (ECMAScript 5th Edition)

var array = ["John", "James", "Jakob", "Peter", "Janette", "Tom", "Vasya", "Jean", "Juilia", "Heather"]
array.reduce(function(p, c,i){return i%3===0?p +' follow '+c:i%3===2?p +' and '+c:i>1?p+"\n"+c:c;})
anthill
()
Ответ на: комментарий от anonymous

мой вариант на racket посчитался за 2.5 сек:

(require racket/match)
(time (for ([x (in-range 1000000)]) (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")])))))

cpu time: 2584 real time: 2586 gc time: 272

вариант анонимуса с regexp-ами за 22.3 секунды:

(require unstable/sequence)
(time (for ([x (in-range 1000000)])(string-join (for/list ([x (in-slice 3 (filter (curry regexp-match? #rx"J.*") lst))]) 
	       (apply format "~a and ~a follow ~a" x)) 
	     "\n")))

cpu time: 22344 real time: 22347 gc time: 229

если убрать regexp-ы из кода анонимуса, то за 12 секунд:

(require unstable/sequence)
(time (for ([x (in-range 1000000)]) (string-join (for/list ([x (in-slice 3 (filter (lambda (w) (eq? (string-ref w 0) #\J)) lst))]) 
	       (apply format "~a and ~a follow ~a" x)) 
	     "\n")

cpu time: 11952 real time: 11947 gc time: 201

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

Входные данные предобработанные

входные данные - строки, в std::string точно также лежат буфер и длина

регекспов нет вообще (J123 - пройдет у тебя, хотя не должен)

во-первых там регекспы нахрен не уперлись, без них сделать проще и быстрее, во-вторых - это твои фантазии, ТС не говорил о таком, входные данные - список имен, ну и многие решения выше не используют регекспы по тем же причинам

вывод на stdout добавь

ты что мерять собрался? скорость выхлопа stdout?

компилировать с -O0

LOL

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

фикс

var array = ["John", "James", "Jakob", "Peter", "Janette", "Tom", "Vasya", "Jean", "Juilia", "Heather"];
array.filter(function(e){return e.match(/^J[a-z]+/)!==null;}).reduce(function(p, c,i){
return i===1?p+' and '+c:i%3===2?p +' follow '+c:i%3===1?p +' and '+c:i>1?p+"\n"+c:c;
})

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

(==) 'J' . head

fail, в этом вашем хаскеле даже регекспов в стандарной поставке нема? хоть parsec-то туда входит? или для «честного» (в меру адекватности тс) решения нужно элементы конечного автомата ручками расписывать..

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

или для «честного» (в меру адекватности тс) решения нужно элементы конечного автомата ручками расписывать..

адекватное решение никогда не будет проверять, что входной список имен должен состоять только из букв - это детский сад и подгузники, проверка данных должна происходить один раз - при их вводе, а все алгоритмы, которые будут с этими данными работать, не должны делать ненужную и «копипащенную» работу

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

по-моему, батенька, вы додумываете за тс его «задачу», или сия реакция обусловлена тем, что и в сях непросто регэкспы расчехлить? (оправдание)

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

по-моему, батенька, вы додумываете за тс его «задачу»

наоборот - остаюсь строго в ее рамках:

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

или сия реакция обусловлена тем, что и в сях непросто регэкспы расчехлить? (оправдание)

мой код на плюсах и там они есть из коробки:

http://en.cppreference.com/w/cpp/regex

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

наоборот - остаюсь строго в ее рамках:

«строго в рамках» можно было и сразу printf, в европах видимо хорошо кормят, раз так легко сидится на двух стульях (уж соблаговолите простить слабость: не удержался от ехидства)

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

«строго в рамках» можно было и сразу printf

можно, но для «бенчмарка» не нужно по очевидным причинам

уж соблаговолите простить слабость: не удержался от ехидства

что вы, ехидничайте на здоровье

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

но для «бенчмарка»

эм.. мне лично не очевидно, что целью было выяснять производительность, почему-то показалось, что инересовались выразительностью синтаксиса

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

инересовались выразительностью синтаксиса

вот мой первый вариант:

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

кстати, с cout был бы короче, а последние варианты были для другого(?) анонимуса, который интересовался скоростью

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

что вы, ехидничайте на здоровье

знаете, такое амбивалентное чувство: и колкость кажется интересной - уж к месту хочется употребить, но и остатки совести говорят, что мол эгоцентрично

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

Регекспа нету

в стандартной библиотеке cl нету регекспов, а так: (ppcre:all-matches «^J[a-z]+» string)

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

Из on lisp вроде бы. Во вногих книгах и вводных статьях приводится эта функция. Но я сначала решал задачу в лоб и не сообразил, что форматовская итерация сама может все сделать.

staseg ★★★★★
()
Ответ на: комментарий от anonymous
{-# LANGUAGE OverloadedStrings #-}

import Control.Category
import Data.ByteString.Char8 ( ByteString )
import qualified Data.ByteString.Char8 as BS
import Data.List.Split
import Text.Regex.Posix
import Debug.Trace

foo :: [ByteString] -> ByteString
foo =
  filter (=~ ("^J[a-z]+" :: ByteString)) >>>
  chunksOf 3 >>>
  map (
    \xs -> case xs of
      [a, b, c] -> BS.unwords [a, "and", b, "follow", c]
      _ -> ""
    ) >>>
  trace "..." >>>
  BS.unlines

main :: IO ()
main = BS.putStr $ foo ["John", "J123", "James", "Jakob", "Peter", "Janette", "Tom", "Vasya", "Jean", "Juilia", "Heather", "Jodd"]

в этом вашем хаскеле даже регекспов в стандарной поставке нема? хоть parsec-то туда входит?

http://lambda.haskell.org/platform/doc/current/index.html

quasimoto ★★★★
()

Напишите кто-нибудь на Rust, что ли. :}

geekless ★★
()

LINQ to the rescue!

using System;
using System.Collections.Generic;
using System.Linq;

namespace ConsoleApplication6
{
    internal class Program
    {
        private static void Main(string[] args)
        {
            var passengers = new List<string> { "John", "James", "Jakob", "Peter", "Janette", "Tom", "Vasya", "Jean", "Juilia", "Heather" };
            Console.WriteLine(string.Join("\n", (from p in passengers
                                                     .Where(p => p.StartsWith("J"))
                                                     .Select((p, i) => new {Passenger = p, Index = i})
                                                     .GroupBy(x => (x.Index/3))
                                                 select string.Format("{0} and {1} folow {2}",
                                                      p.Select(p1 => p1.Passenger).ToArray())).ToArray()));
            Console.ReadLine();
        }
    }
}
n15n
()
Ответ на: комментарий от quasimoto

http://lambda.haskell.org/platform/doc/current/index.html

довольно спорно, что это стандартная поставка: туда и opengl входит, и non-portable пакеты.. вот если бы в каком haskell2010

_ -> «»

боюсь, сударь, вы недоизголялись: можно было do [a,b,c] <- [xs]; BS...

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

вот если бы в каком haskell2010

Это вон к плюсам11, там регулярные выражения прямо в std. А так - не вижу чем платформа под данную ось хуже пакета с перло-руби-питоном под неё же (кроме размера, конечно).

можно было do [a,b,c] <- [xs]; BS...

Да, только return $ BS и потом ещё concat >>> в общей цепочке.

quasimoto ★★★★
()

шах и мат, бугага

СтрокаИмениНуралиеваБорисаГеоргиевича = "John,James,Jakob,Peter,Janette,Tom,Vasya,Jean,Juilia,Heather";
Массив = _сф.м_СоздатьИзСтроки(СтрокаИмениНуралиеваБорисаГеоргиевича,",");
Имена = Новый Массив;
Для каждого Имя Из Массив Цикл
    Если Лев(Имя,1)="J" Тогда
	Имена.Добавить(Имя);
    КонецЕсли; 
КонецЦикла; 
Результат = "";
Для сч=0 По Цел(Имена.Количество()/3-1) Цикл
    Результат = Результат + Имена[сч*3]+" and "+Имена[сч*3+1]+" follow "+Имена[сч*3+2]+Символы.ПС;
КонецЦикла;
Сообщить(Результат);

шучу :)

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

я думал раньше обратят внимание, да - для полностью переносимого решения придется заюзать препроцессор, но на быстродействие это очевидно никак не повлияет

wota ★★
()

Мой вариант (Scala).

val persons = Array("John", "James", "Jakob", "Peter", "Janette", "Tom", "Vasya", "Jean", "Juilia", "Heather");
Console.println(persons filter(item => item.contains("J")));
persons.filter(p => p.contains("J")).grouped(3).foreach(person => Console.printf("%s%s%s%s%s\n", person(0), " follow ", person(1), " and ", person(2)));
LongLiveUbuntu ★★★★★
()
Последнее исправление: LongLiveUbuntu (всего исправлений: 1)

На D, по образу и подобию Ruby-версии:

import std.algorithm, std.range, std.regex, std.array, std.string, std.stdio : writeln;

void main() {
    auto names = ["John", "James", "Jakob", "Peter", "Janette", "Tom", "Vasya", "Jean", "Juilia", "Heather"];
    writeln(names.filter!(s => !s.match(r"^J[a-z]+").empty).array
                 .chunks(3)
                 .map!(b => format("%s and %s follow %s", b[0], b[1], b[2]))
                 .join("\n"));
}
lomereiter
()
Ответ на: комментарий от KRoN73

Кстати, написать each_slice для библиотеки — дело двух строчек.

Написал nslice() из четырёх строк :) Теперь можно написать буквально как в топикстарте:

<?php

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

echo blib_array::factory(["John", "James", "Jakob", "Peter", "Janette", "Tom", "Vasya", "Jean", "Juilia", "Heather"])
    ->pgrep('/^J[a-z]+/')
    ->nslice(3)
    ->map(function($x) { return "{$x[0]} and {$x[1]} follow {$x[2]}"; })
    ->join("\n");

Заодно заметил, что у меня логика nshift выбивается из общего фона. Переделал.

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

Прикольно с этим nslice получается таблица умножения:

echo blib_array::factory()
    ->range(11,99)
    ->map(function($x) { $a = floor($x/10); $b = $x%10; return $a*$b; })
    ->filter()
    ->nslice(9)
    ->map(function($row) { return $row->join("\t"); })
    ->join("\n");

$ php multab.php 
1	2	3	4	5	6	7	8	9
2	4	6	8	10	12	14	16	18
3	6	9	12	15	18	21	24	27
4	8	12	16	20	24	28	32	36
5	10	15	20	25	30	35	40	45
6	12	18	24	30	36	42	48	54
7	14	21	28	35	42	49	56	63
8	16	24	32	40	48	56	64	72
9	18	27	36	45	54	63	72	81
KRoN73 ★★★★★
()

J.

'%s and %s follow %s'&printf " 1 (($~ ((, & 3) @: (% & 3) @: $)) 'J[a-z]*' rxall 'John James Jakob Peter Janette Tom Vasya Jean Juilia Heather')

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

Тогда так:

val persons = Array("John", "James", "Jakob", "Peter", "Janette", "Tom", "Vasya", "Jean", "Juilia", "Heather");
persons.foreach(p => if(p.startsWith("J")) Console.printf("%s%c" , p, ' '));
println;
persons.filter(p => p.startsWith("J")).grouped(3).
foreach(person => Console.printf("%s%s%s%s%s\n", person(0), " follow ", person(1), " and ", person(2)));

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

вот имхо более идиоматичный шелл:

echo John James Jakob Peter Janette Tom Vasya Jean Juilia Heather | tr \  \\\n | grep -i \^j | pr -at3 | awk '{print $1, "and", $2, "follow", $3}'
val-amart ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.