Ile instancji działa?


13

Napisz nieskończenie działający program, który informuje, ile instancji jest aktualnie uruchomionych. Każde wystąpienie programu powinno również zgłaszać kolejność otwierania go ze wszystkich innych aktualnie uruchomionych wystąpień.

Przykład

Użytkownik uruchamia program po raz pierwszy - wywołamy to wystąpienie 1. Wyświetla się wystąpienie 1 1/1, ponieważ jest to pierwsze wystąpienie z łącznie 1 aktualnie działających wystąpień.

Gdy instancja 1 jest uruchomiona, użytkownik uruchamia program po raz drugi, aby stać się instancją 2. Instancja 1 jest teraz wyświetlana 1/2, będąc pierwszą instancją spośród 2 aktualnie uruchomionych instancji. Zostanie wyświetlona instancja 2 2/2, ponieważ jest to druga instancja spośród 2 aktualnie uruchomionych instancji.

Załóżmy, że użytkownik kontynuuje tworzenie kolejnych instancji, dopóki nie będzie ich 5 . W celu wprowadzenia na rynek, ich wyjścia są: 1/5 2/5 3/5 4/5 5/5.

Powiedzmy, że użytkownik decyduje się na zakończenie wystąpienia 3. Wystąpienie 4 staje się wówczas nowym wystąpieniem 3, a wystąpienie 5 nowym wystąpieniem 4, ponieważ są one odpowiednio trzecim i czwartym wystąpieniem, które zostało uruchomione z łącznej liczby 4 instancje. Zatem zmiana danych wyjściowych każdej instancji wyglądałaby następująco:

  • 1/51/4
  • 2/52/4
  • 3/5 → (zakończone)
  • 4/53/4
  • 5/54/4

Zasady

  • Możesz wyprowadzić dwie liczby (liczbę instancji, całkowitą liczbę instancji) w dowolnym rozsądnym formacie.
  • Za każdym razem, gdy instancja zostanie uruchomiona lub zakończona, wszystkie pozostałe instancje muszą zaktualizować swoje dane wyjściowe w ciągu 100 milisekund.
  • Jeśli zdecydujesz się zaktualizować dane wyjściowe, drukując w nowym wierszu (lub w innym „dołączającym” formacie wyjściowym; w przeciwieństwie do zastępowania), musisz drukować tylko wtedy, gdy zmienia się liczba wystąpień, a nie w żadnym innym momencie.
  • To jest kod golfowy. Najkrótszy program w bajtach wygrywa.
  • W swojej odpowiedzi zachęcamy do określenia, co użytkownik musi zrobić, aby otworzyć więcej niż jedną instancję i / lub nagrać screencast, aby zademonstrować.

Czy ktoś ma sugestie dotyczące dodania tagów?
darrylyeo

Taki program byłby specyficzny dla systemu operacyjnego.
user202729,

Jest „Za każdym razem, gdy instancja zostanie uruchomiona lub zakończona, wszystkie inne instancje muszą zaktualizować swoje dane wyjściowe w ciągu 100 milisekund”, nawet pod naszą kontrolą, biorąc pod uwagę, że musimy polegać na systemie operacyjnym, aby się komunikować (i fakt, że możemy spawnować wiele, wiele procesów może ” t pomoc)?
Jonathan Allan,

Współdziałanie procesów @Ouros nie może być niezależne od systemu operacyjnego
edc65

Odpowiedzi:


3

APL (Dyalog Unicode) , 39 bajtów SBCS

Anonimowa funkcja prefiksu. Wywołaj przez spawnowanie na fikcyjnym argumencie (pusty wektor numeryczny), tj f&⍬. Zapytaj aktualnie uruchomione wątki za pomocą ⎕TNUMSi zabij jeden lub więcej wątków za pomocą ⎕TKILL n. Wątki wyprowadzają zmiany w [liczba własna, liczba całkowita], gdy tylko otrzymają czas procesora, tj. Prawie natychmiast.

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

Wypróbuj online!

{} Anonimowa lambda gdzie jest argument (początkowo pusty wektor numeryczny)

n[] Indeks n(do zdefiniowania) z:

  ⎕TNUMS~0 Wszystko T hread Num BERS wyjątkiem numeru 0(the REPL)

   n← przechowywać jako n

    permutacja sortująca rosnąco

  teraz mamy aktywne wątki w kolejności

  ⍵≡ jeśli argument jest identyczny z tym…

  : następnie:

   ∇⍵ ogon powraca do argumentu

   jeszcze:

   ⊢/n numer prawej nici

   ⎕TID, ten T hread jest ID (liczba nici) dołączany do

   n⍳ znaleźć ɩ ndices tych dwóch

   ⎕← wydrukuj to do STDOUT

   n⊣ odrzucić to na korzyść n

    powrócić do tego


2

Python 3, 694 691 bajtów

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 (skrót od 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")

Dlaczego to tak długo?

Niestety, ta funkcjonalność nie wydaje się być wbudowana w Pythona. Kusiło mnie, aby używać przetwarzania wieloprocesorowego, ale nie do końca pasowało to do tego, co robimy (pozwalanie użytkownikowi otwierać program z dowolnego miejsca).

Więc skorzystałem z porady, którą zobaczyłem w StackOverflow (zgubiłem link) i zaimplementowałem go za pomocą bottle. (Jestem otwarty na nowe sugestie).

Użyłem biblioteki Bottle do uruchomienia własnego mini serwera http, aby wszystkie różne instancje mogły się ze sobą komunikować. Przypuszczam, że mógłbym użyć gniazda, chociaż nie jestem przekonany, czy zmniejszyłoby to liczbę bajtów.

Mam dwa osobne pliki si main.py. sbrakuje serwera i ponieważ pojawia się w kodzie, pomyślałem, że powinienem skrócić nazwę tak krótko, jak to możliwe.

Komunikacja API serwera WWW

Serwer WWW przyjmuje tylko żądania POST i odpowiada tylko na dane wejściowe wewnątrz ciała POST.

Wszystkie żądania przechodzą /(lub localhost/).

Prawidłowe dane wejściowe:

  • * w treści postu poprosi serwer o zwrócenie nowego identyfikatora w celu przypisania klienta.
  • -<id> w treści postu usunie identyfikator z aktywnej listy identyfikatorów, zmniejszając wszystkie odpowiednie identyfikatory i całkowitą liczbę.
  • Puste żądanie w treści postu zwróci po prostu pusty ciąg. To jest używane do testowania, aby sprawdzić, czy serwer jest online.

Zamknięcie programu

Zaimplementowałem wielowątkowość, więc zamknięcie programu jest tak proste, jak naciśnięcie Enter.

Otwieranie programu

Jeśli nie masz instalację Pythona prawidłowo wewnątrz zmiennych środowiskowych wystarczy utworzyć .batplik i umieścić go w tym samym folderze, main.pya sz kodem Następujące (jeśli zainstalowany Python dla wszystkich użytkowników, może być w innym miejscu):

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

Kredyty

Od 694 do 691 bajtów Adám .


Nie można usunąć :8080/?
Adám

Gdybym miał przypisać port do portu 80, to tak; w przeciwnym razie nie. Domyślnym portem dla przeglądarek internetowych (i żądań) jest port 80, ale mogę go usunąć /.
Neil,

@ Adám Zaktualizowałem go ze zmianą portu, w ten sposób zapisałem 1 bajt.
Neil,

1

Narzędzia sh + linux / unix, 128 bajtów

jeśli sen obsługuje liczby zmiennoprzecinkowe

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

w przeciwnym razie 159 bajtów

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

lub sen może zostać zastąpiony przez :(no-op), ale spowoduje aktywne czekanie.


Jest to naprawdę blisko - „Musisz drukować tylko wtedy, gdy zmienia się liczba wystąpień, a nie w żadnym innym momencie”.
darrylyeo

@darrylyeo właśnie naprawiłem, ale szukałem krótszego rozwiązania, ale nie miałem czasu, również spać 100 ms, mam rozwiązanie, ale dłużej
Nahuel Fouilleul

0

Java 8, (199 + 301 =) 500 bajtów

M.jar: (program główny)

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: (serwer do sterowania przebiegiem programu)

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);}}}}

Objaśnienie kodu:

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

Ogólne wyjaśnienie:

Wszystkie programy będą prowadzić rejestr własnego identyfikatora; całkowita liczba pozostałych wystąpień; czy nastąpiło usunięcie; i które programy zostały zamknięte.

Serwer jest tylko klasą opakowania do uruchamiania i zatrzymywania programów. Gdy użytkownik wprowadzi dane 0, uruchomi nowy program. Kiedy użyte wprowadzi dodatnią liczbę całkowitą (tj. 2), Zamknie program o tym identyfikatorze. (Uwaga: S.jar ma M.jar jako bibliotekę, aby uzyskać do niego dostęp).

Gif, aby zobaczyć to w akcji:

wprowadź opis zdjęcia tutaj

Myśli o dalszym golfie:

Właśnie zauważyłem, pisząc wyjaśnienie, że używam go tylko ObservableListdo dodawania / usuwania- ListChangeListeneri wcale nie używam jego zawartości. Usunięcie tego i użycie innego rodzaju statycznego Listenera może być krótsze.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.