Сколько экземпляров запущено?

13

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

пример

Пользователь запускает программу в первый раз - мы назовем этот экземпляр 1. Экземпляр 1 отображается 1/1, потому что это первый экземпляр, который будет запущен из 1 запущенных в данный момент экземпляров.

Во время работы Экземпляра 1 пользователь запускает программу второй раз, чтобы стать Экземпляром 2. Теперь отображается Экземпляр 1 1/2, являющийся первым экземпляром из 2 запущенных в данный момент экземпляров. Экземпляр 2 отображается 2/2, потому что это второй экземпляр из 2 запущенных в данный момент экземпляров.

Допустим, пользователь продолжает порождать больше экземпляров, пока их не станет 5 . Для запуска, их выходы: 1/5 2/5 3/5 4/5 5/5.

Теперь, скажем, пользователь решает прекратить Экземпляр 3. Затем Экземпляр 4 становится новым Экземпляром 3, а Экземпляр 5 - новым Экземпляром 4, потому что они соответственно являются третьим и четвертым экземплярами, которые были запущены из того, что сейчас составляет 4. экземпляров. Таким образом, изменение каждого экземпляра в выводе будет следующим:

  • 1/51/4
  • 2/52/4
  • 3/5 → (прекращено)
  • 4/53/4
  • 5/54/4

правила

  • Вы можете вывести два числа (номер экземпляра, общее количество экземпляров) в любом приемлемом формате.
  • Каждый раз, когда экземпляр запускается или завершается, все остальные экземпляры должны обновить свои соответствующие выходные данные в течение 100 миллисекунд.
  • Если вы решите обновить вывод, печатая на новую строку (или другой «добавляющий» формат вывода; в отличие от замены), вы должны печатать только при изменении количества экземпляров, а не в любое другое время.
  • Это код гольф. Самая короткая программа в байтах побеждает.
  • В своем ответе вам предлагается указать, что пользователь должен сделать, чтобы открыть более одного экземпляра, и / или записать скринкаст для демонстрации.
darrylyeo
источник
У кого-нибудь есть предложения по добавлению тегов?
Darrylyeo
Такая программа будет зависеть от ОС.
user202729
«Каждый раз, когда экземпляр запускается или завершается, все остальные экземпляры должны обновлять свои соответствующие выходные данные в течение 100 миллисекунд», даже в пределах нашего контроля, учитывая, что мы должны полагаться на ОС для связи (и тот факт, что мы могли бы породить много, многие процессы могут ') не поможет)?
Джонатан Аллан
Процесс взаимодействия @Ouros не может быть независимым от операционной системы
edc65

Ответы:

3

APL (Dyalog Unicode) , 39 байтов SBCS

Функция анонимного префикса. Вызов порождая на фиктивный аргумент (пустой числовой вектор), то есть f&⍬. Запросить текущие потоки с ⎕TNUMSи убить один или несколько потоков с ⎕TKILL n. Потоки выводят изменения в [свое число, общее число], как только они получают процессорное время, то есть в значительной степени мгновенно.

{⍵≡nn[⍋n←⎕TNUMS~0]:∇n⋄∇n⊣⎕←n⍳⎕TID,⊢/n}

Попробуйте онлайн!

{} Анонимная лямбда где аргумент (изначально пустой числовой вектор)

n[] Индекс n(подлежит определению) с:

  ⎕TNUMS~0 все Т hread Num Берс кроме номера 0(The РЕПЛ)

   n← хранить как n

    перестановка, которая будет сортировать по возрастанию

  теперь у нас есть активные темы в порядке

  ⍵≡ если аргумент идентичен этому ...

  : тогда:

   ∇⍵ Хвост рекурс на аргумент

   еще:

   ⊢/n самый правый номер резьбы

   ⎕TID, в этом T hread в ID (номер нити) предваряется , что

   n⍳ найти ɩ ndices тех , два

   ⎕← распечатать это в STDOUT

   n⊣ отказаться от этого в пользу n

    отреагировать на это

Адам
источник
2

Python 3, 694 691 байт

main.py

from requests import post as u
from _thread import*
import os
os.system("start cmd /C python s")
def l():
 def p(q):
  while 1:print(u(*q).text,end="\r")
 q=['http://localhost']
 q+=[u(q[0],'*').text]
 start_new_thread(p,(q,))
 input()
 u(q[0],'-'+q[1])
while 1:
 try:l();break
 except:0

s (сокращение от server.py)

from bottle import*
from requests import post as q
try:
 q("http://localhost")
except:
 ids=["0"]
 @post('/')
 def _():
  content = request.body.read().decode('utf-8')
  if len(content)==0:return""
  if content[0]=="*":ids.append(str(int(ids[-1])+1));return str(ids[-1])
  elif content[0]=="-":del ids[ids.index(content[1:])]
  else:return str(ids.index(content)) + "/" + str(len(ids)-1)
 run(port="80")

Почему это так долго?

К сожалению, эта функциональность, похоже, не встроена в Python. У меня было искушение использовать многопроцессорность, но это не совсем подходило для того, что мы делаем (позволяя пользователю открывать программу из любого места).

Итак, я воспользовался советом поста StackOverflow, который я видел (я не поместил ссылку), и я реализовал его, используя bottle . (Я открыт для новых предложений).

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

У меня есть два отдельных файла, sи main.py. sне хватает сервера и, поскольку он появляется в коде, я решил, что имя должно быть как можно короче.

API коммуникационного веб-сервера

Веб-сервер принимает только запросы POST и отвечает только на ввод внутри тела POST.

Все запросы проходят /(или localhost/).

Допустимый ввод:

  • * в теле сообщения будет запрашиваться у сервера возврат нового идентификатора для назначения клиенту.
  • -<id> в теле поста удалит идентификатор из активного списка идентификаторов, уменьшив все соответствующие идентификаторы и общее количество.
  • Пустой запрос в теле сообщения просто вернет пустую строку. Это то, что используется для тестирования, чтобы увидеть, если сервер в сети.

Закрытие программы

Я реализовал многопоточность, поэтому закрыть программу так же просто, как нажать Enter.

Открытие программы

Если у вас неправильно настроен Python внутри переменных среды, просто создайте .batфайл и поместите его в ту же папку, что main.pyи sследующий код (если вы установили Python для всех пользователей, он может находиться в другом месте):

set PATH=%userprofile%\AppData\Local\Programs\Python\Python36
python main.py

кредиты

От 694 до 691 байтов Adám .

Нил
источник
Вы не можете удалить :8080/?
Адам
Если бы я назначил порт на порт 80, тогда да; в противном случае нет. Порт по умолчанию для веб-браузеров (и запросов) - порт 80, но я могу удалить /.
Нил
@ Adám Я обновил его с изменением порта, таким образом сохранил 1 байт.
Нил
1

инструменты sh ​​+ linux / unix, 128 байт

если сон поддерживает числа с плавающей запятой

trap '(flock 9;grep -vw $$ p>t;mv t p)9>l' exit;(flock 9;echo $$>>p)9>l;f(){ echo $(sed -n /^$$\$/= p)/$(wc -l<p);sleep .1;f;};f

в противном случае 159 байтов

trap '(flock 9;grep -vw $$ p>t;mv t p)9>l' exit;(flock 9;echo $$>>p)9>l;perl -MTime::HiRes=usleep -nE/^$$'$/&&say("$./",$.+(@a=<>)),usleep 1e5,$.=-(@ARGV=p)' p

или сон может быть заменен на :(без операции), но это сделает активное ожидание.

Науэль Фуйе
источник
Это очень близко - «Вы должны печатать только тогда, когда меняется количество экземпляров, а не в любое другое время».
Darrylyeo
@darrylyeo просто исправил, но искал более короткое решение, но у меня не было времени, чтобы поспать 100 мс, у меня есть решение, но дольше
Науэль Фуийе
0

Java 8, (199 + 301 =) 500 байт

М.jar: (основная программа)

import javafx.collections.*;class M{static ObservableList o=FXCollections.observableArrayList();static int j,F;int i,f;{F=0;ListChangeListener e=(ListChangeListener.Change c)->{if(f<1)System.out.println((F>0&i>F?--i:i)+"/"+j);};o.addListener(e);o.add(i=++j);}public void f(){F=f=i;j--;o.remove(--i);}}

S.jar: (сервер для управления потоком программ)

import java.util.*;interface S{static void main(String[]a){List<M>l=new Stack();for(Scanner s=new Scanner(System.in);;){Float n=s.nextFloat();if(n%1==0)l.add(new M());else{int t=(int)(n*10-1);l.get(t).f();l.remove(t);}}}}

Пояснение к коду:

import javafx.collections.*;
                  // Required import for ObservableList, FXCollections, and ListChangeListener
class M{          // Program-class
  static ObservableList o=FXCollections.observableArrayList(); 
                  //  Static list to keep record of all instances
  static int j,   //  Static integer (total number of instances)
             F;   //  Static flag (remove occurred?)
  int i,          //  Non-static integer (id of this instance)
      f;          //  Non-static flag (has been removed)
  {               //  Non-static initializer-block (shorter than constructor)
    F=0;          //   Reset the static flag remove_occurred, because we add a new instance
    o.addListener((ListChangeListener.Change c)->{
                  //   Add a change listener for the ObservableList
                  //   This will monitor any additions or removes on the List
       if(f<1)    //    If this instance is not removed yet:
         System.out.println(
                  //     Print:
           (F>0&i>F?
                  //      If a removed occurred and this id is larger than the removed instance
             --i  //       Decrease its id by 1 before printing it
            :     //      Else:
             i)   //       Just print its id
           +"/"+j);
                  //      Plus the total number of instances left
    });
    o.add(        //   Add anything to the Observable list to trigger the listener
     i=++j);      //    Increase the total amount of instances, and set the id of this instance to the last one
  }               //  End of non-static initializer-block
  public void f(){//  Finalize-method
    F=f=i;        //   Set both flags to the current id
    j--;          //   Decrease the total amount of instances
    o.remove(--i);//   Remove the current instance from the list to trigger the listener
  }               //  End of Finalize-method
}                 // End of Program-class

import java.util.*;
                  // Required import for List, Stack and Scanner
interface S{      // Server-class
  static void main(String[]a){
                  //  Mandatory main-method
    List<M>l=new Stack();
                  //   List of programs
    for(Scanner s=new Scanner(System.in);
                  //   Create a STDIN-listener for user input
        ;){       //   Loop indefinitely
      int t=s.nextInt();
                  //    Get the next integer inputted
      if(t<1)     //    If it's 0:
        l.add(new M());
                  //     Startup a new program, and add its instance to the list
      else{       //    Else:
        l.get(t).f();
                  //     Close the program with this integer as id
        l.remove(t);}
                  //     And remove it from the list of programs
    }             //   End of loop
  }               //  End of main-method
}                 // End of Server-class

Общее объяснение:

Все программы будут вести учет своего собственного идентификатора; общее количество оставшихся экземпляров; произошло ли удаление; и какие программы закрылись.

Сервер - это просто класс-оболочка для запуска и остановки программ. Когда пользователь вводит 0, он запускает новую программу. Когда используемый вводит положительное целое число (т.е.2 ), он закроет программу с этим идентификатором. (Примечание: у S.jar есть библиотека M.jar для доступа к ней.)

Gif, чтобы увидеть это в действии:

введите описание изображения здесь

Мысли о гольфе это дальше:

Я только заметил, когда писал объяснение, что я использую только ObservableListдля его добавления / удаления ListChangeListener, и не использую его содержание вообще. Удаление этого и использование другого типа статического прослушивателя может быть короче.

Кевин Круйссен
источник