Quantas instâncias estão em execução?


13

Escreva um programa em execução indefinidamente que relate quantas instâncias dele estão em execução no momento. Cada instância do programa também deve relatar a ordem em que foi aberto em todas as outras instâncias em execução no momento.

Exemplo

O usuário inicia o programa pela primeira vez - chamaremos isso de Instância 1. A Instância 1 é exibida 1/1, porque é a primeira instância a ser lançada de um total de 1 instâncias atualmente em execução.

Enquanto a Instância 1 está em execução, o usuário inicia o programa uma segunda vez para se tornar a Instância 2. A Instância 1 agora é exibida 1/2, sendo a primeira instância de um total de 2 instâncias atualmente em execução. A instância 2 é exibida 2/2, porque é a segunda instância de um total de 2 instâncias atualmente em execução.

Digamos que o usuário continue gerando mais instâncias até que existam 5 delas. Em ordem de lançamento, os seus resultados são: 1/5 2/5 3/5 4/5 5/5.

Agora, digamos que o usuário decida encerrar a Instância 3. A Instância 4 se torna a nova Instância 3 e a Instância 5 a nova Instância 4, porque são respectivamente a terceira e a quarta instâncias a serem lançadas do que agora é um total de 4 instâncias. Portanto, a alteração de saída de cada instância seria a seguinte:

  • 1/51/4
  • 2/52/4
  • 3/5 → (Terminado)
  • 4/53/4
  • 5/54/4

Regras

  • Você pode emitir os dois números (número da instância, total de instâncias) em qualquer formato razoável.
  • Sempre que uma instância é iniciada ou finalizada, todas as outras instâncias devem atualizar suas respectivas saídas em 100 milissegundos.
  • Se você optar por atualizar a saída imprimindo para uma nova linha (ou outro formato de saída "anexado"; em vez de substituir), deverá imprimir somente quando o número de instâncias mudar, e não a qualquer outro momento.
  • Isso é código de golfe. O programa mais curto em bytes vence.
  • Em sua resposta, você deve especificar o que o usuário deve fazer para abrir mais de uma instância e / ou registrar um screencast para demonstrar.

Alguém tem sugestões para incluir tags?
darrylyeo

Esse programa seria específico do SO.
user202729

É "Sempre que uma instância é iniciada ou finalizada, todas as outras instâncias devem atualizar suas respectivas saídas em 100 milissegundos", mesmo sob nosso controle, pois precisamos confiar no sistema operacional para nos comunicar (e o fato de podermos gerar muitos e muitos processos pode " não ajuda)?
Jonathan Allan

@Ouros interoperação processo não pode ser independente do sistema operacional
edc65

Respostas:


3

APL (Dyalog Unicode) , SBCS de 39 bytes

Função de prefixo anônimo. Chame gerando o argumento fictício (vetor numérico vazio), ie f&⍬. Consulte os tópicos atualmente em execução ⎕TNUMSe elimine um ou mais tópicos com ⎕TKILL n. A saída de threads muda em [número próprio, número total] assim que obtém o tempo do processador, ou seja, instantaneamente.

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

Experimente online!

{} Lambda anônima onde está o argumento (inicialmente , o vetor numérico vazio)

n[] Índice n(a ser definido) com:

  ⎕TNUMS~0 todos t hread Num fibras excepto número 0(REPL)

   n← armazenar como n

    permutação que classificaria ascendente

  agora temos os threads ativos em ordem

  ⍵≡ se o argumento é idêntico a isso ...

  : então:

   ∇⍵ recuar cauda sobre o argumento

   outro:

   ⊢/n o número da rosca mais à direita

   ⎕TID, este T do hread ID (número fio) anexado ao que

   n⍳ encontre os ndices desses dois

   ⎕← imprima isso para STDOUT

   n⊣ descartar isso em favor de n

    recuar sobre isso


2

Python 3, 694 691 bytes

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 (abreviação de 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")

Por que demora tanto?

Infelizmente, essa funcionalidade não parece estar embutida no Python. Fiquei tentado a usar o multiprocessamento, mas isso não parecia adequado para o que estamos fazendo (permitindo que um usuário abra um programa de qualquer lugar).

Então, segui o conselho de um post do StackOverflow que vi (extraviei o link) e o implementei usando bottle. (Estou aberto a novas sugestões).

Eu usei a biblioteca Bottle para executar meu próprio servidor http mini, para que todas as instâncias diferentes possam se comunicar. Suponho que poderia ter usado um soquete, embora não esteja convencido de que teria reduzido a contagem de bytes.

Eu tenho dois arquivos separados se main.py. sestá com falta de servidor e, como aparece no código, achei que deveria tornar o nome o mais curto possível.

API do Communication Web Server

O servidor da Web aceita apenas solicitações POST e responde apenas à entrada dentro do corpo do POST.

Todas as solicitações passam por /(ou localhost/).

Entrada válida:

  • * no corpo da postagem solicitará que o servidor retorne um novo ID para atribuir o cliente.
  • -<id> no corpo da postagem removerá o ID da lista ativa de IDs, diminuindo todos os IDs relevantes e a contagem total.
  • Uma solicitação vazia no corpo da postagem retornará simplesmente uma sequência vazia. É isso que é usado para testar para ver se o servidor está online.

Fechando o programa

Eu implementei o multi-threading, portanto, fechar o programa é tão simples quanto pressionar enter.

Abrindo o programa

Se você não tiver a configuração do Python corretamente dentro de suas variáveis ​​ambientais, basta criar um .batarquivo e colocá-lo na mesma pasta que main.pye scom o seguinte código (se você instalou o Python para todos os usuários, ele pode estar em um local diferente):

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

Créditos

De 694 a 691 bytes Adám .


Você não pode remover :8080/?
Adám 11/12/19

Se eu atribuir a porta à porta 80, então sim; caso contrário, não. A porta padrão para navegadores da web (e solicitações) é a porta 80, mas eu posso remover o /.
Neil

@ Adám Eu atualizei com a mudança de porta, salvei 1 byte dessa maneira.
1111 Neil

1

Ferramentas sh + linux / unix, 128 bytes

se o sono suportar números de ponto flutuante

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

caso contrário, 159 bytes

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

ou sleep pode ser substituído por :(no-op), mas ativará a espera.


Isso é bem próximo - "Você deve imprimir apenas quando o número de instâncias mudar, e não em nenhum outro momento".
darrylyeo

@darrylyeo apenas correção, mas estava à procura de uma solução mais curto, mas não têm o tempo, também a 100ms do sono, eu tenho uma solução, mas mais
Nahuel FOUILLEUL

0

Java 8, (199 + 301 =) 500 bytes

M.jar: (o programa principal)

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: (o servidor para controlar o fluxo do programa)

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

Explicação do código:

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

Explicação geral:

Todos os programas manterão um registro de sua própria identificação; o número total de instâncias restantes; se ocorreu uma remoção; e quais programas foram fechados.

O servidor é apenas uma classe de invólucro para iniciar e parar programas. Quando um usuário entra 0, ele inicia um novo programa. Quando o usado digitar um número inteiro positivo (ou seja 2), fechará o programa com esse ID. (Nota: S.jar possui M.jar como biblioteca para acessá-lo.)

Gif para vê-lo em ação:

insira a descrição da imagem aqui

Pensamentos para jogar ainda mais:

Eu só notei enquanto escrevia a explicação de que eu só uso o ObservableListmétodo add / remove- ListChangeListenere não uso o conteúdo. Remover isso e usar outro tipo de ouvinte estático pode ser mais curto.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.