Posso fazer [$ (($ 1% $ check)) - um 0]; ter mais desempenho e não ser morto?

1

Se o código a seguir funcionar para até 13 (linha 2) em alguns segundos, mas quando eu tento e faço adolescentes superiores e 20 ele é morto depois de alguns minutos.

divisible_by () {
  for ((check=2; check<13; check++)) {
    if [ $(($1 % $check)) -ne 0 ]; then
      return
    fi  
  }
  echo "$1 is divisible by all the numbers"
  exit 0
}
d=0
while true; do
  d=$((d+1))
  divisible_by $d
done

Eu tentei usar

if $(($1 % $check)) -ne 0; then

mas recebo 1: command not found

Eu tentei

if $(($1 % $check)) -ne 0; then

mas tenho 1:command not found e -ne command not found

Eu tentei

 if [ $($1 % $check) -ne 0 ]; then

mas tenho 1:command not found e -ne: unary operator expected

Eu tentei

 if [ $1 % $check -ne 0 ]; then

mas eu tenho [: too many arguments

    
por Michael Durrant 05.01.2015 / 03:16

3 respostas

2

Supondo que o objetivo aqui é encontrar o menor número divisível por números inteiros de 2 a n, tentar verificar se cada inteiro é massivamente ineficiente. O algoritmo mais fácil que posso imaginar é usar uma série de fatores que eventualmente serão multiplicados para obter a resposta. Começa vazio. Em seguida, pegue cada número em sequência e divida os fatores que já estão em nosso conjunto de fatores únicos. Tudo o que resta é adicionado ao conjunto de fatores únicos, e sabemos que esse conjunto será divisível pelo número atual. Como o produto desse conjunto contém o conjunto mínimo de fatores primos que satisfaz todas as divisões necessárias, é garantido que seja o menor número divisível por todos os números de 2 a n.

upto=20
uniqueFactors=()
for ((i=2; i <= upto; i++)) 
do
  newFactors=$i
  for factor in "${uniqueFactors[@]}" #loop over array of factors
  do
    if [ $(($newFactors%$factor)) -eq 0 ]; then
      newFactors=$(($newFactors/$factor));
    fi;
  done
  uniqueFactors+=($newFactors);
done

product=1
for factor in "${uniqueFactors[@]}"
do
  product=$(bc <<< "$product*$factor") #use bc for numbers outside integer range
done

echo $product

Calcula o primeiro número divisível por 2-20 (232792560) em 4 milissegundos na minha máquina. Ele calcula até 100 (69720375229712477164533808935312303556800) em 0,425 segundo e 1000 (um número com várias centenas de casas decimais) em 4.813 segundos. Se você tentasse repetir muitos números, teria que se preocupar com o processo de ser morto pela morte pelo calor do universo. A otimização de linhas individuais oferece melhorias em porcentagens ou ordens de magnitude. Alterar seu algoritmo pode fornecer melhorias em uma escala logarítmica.

    
por 05.01.2015 / 12:41
2

Você pode aproveitar o fato de que (( retorna zero quando o resultado é diferente de zero:

if (( $1 % check )); then
  ...
fi
    
por 05.01.2015 / 03:37
2

Eu iteriaria em ordem decrescente. O loop pode terminar mais cedo.

for ((check=12; check>1; --check)) {

em vez de

for ((check=2; check<13; check++)) {

Pense nisso. Se o número não é divisível por 12, também não é divisível por 4, 3 e 2. Não vice-versa.

    
por 05.01.2015 / 03:59