Existe um software que periodicamente me permita fazer exercícios aritméticos mentais?

9

Estou ciente da minha natureza preguiçosa e preciso me esforçar para fazer alguma aritmética mental básica de tempos em tempos. Portanto, estou procurando um software que periodicamente me peça para fazer um pequeno exercício aritmético mental (mais, menos, multiplicar, dividir).

Critério:

  • Isso deve permitir que eu personalize o intervalo de tempo
  • Ele deve se integrar ao Ubuntu Desktop, ou seja, ficar oculto em segundo plano e aparecer apenas (pop-up) durante o exercício
orschiro
fonte
2
Duvido que esse software exista, mas poderia ser facilmente criado com um script shell ou python. Vou preparar alguma coisa amanhã, por favor, lembre-me #
Sergiy Kolodyazhnyy
Sim, o bsdgames tem aritmética e tal, mas você teria que automatizar os pop-ups periódicos por conta própria.
Mchid
Caro @Serg, lembro-o gentilmente sobre sua experiência de cozinhar. :)
orschiro 26/01
11
Então, publiquei uma resposta em andamento, que editarei à medida que for avançando. Dê uma olhada, deixe-me saber o que você pensa, que funcionalidade adicionar ou remover. Até agora, este é um aplicativo de console, mas acabará se transformando em uma pequena janela pop-up.
Sergiy Kolodyazhnyy
2
É uma boa pergunta para trabalhar!
Jacob Vlijm

Respostas:

8

1. Versão simples

O script abaixo produzirá tarefas aleatoriamente, + , - , × e ÷ . Você pode (e deve) definir um número máximo que o script possa usar, bem como o intervalo de tempo entre as atribuições.

As atribuições

As tarefas são apresentadas em uma janela de entrada do Zenity:

insira a descrição da imagem aqui

se a resposta estiver errada:

insira a descrição da imagem aqui

Se a resposta estiver correta:

insira a descrição da imagem aqui

O script

#!/usr/bin/env python3
from random import randint
import sys
import subprocess
import time

# maximum number & interval
max_n = int(sys.argv[1]); pause = int(sys.argv[2])

def fix_float(n):
    """
    if the assignment is a division, the script divides the random number by a
    number (integer) it can be divided by. it looks up those numbers, and picks
    one of them (at random). if the number is a prime number the assignment is
    changed into another type
    """
    try:
        divs = [i for i in range(2, n) if n%i == 0]
        pick = randint(1, len(divs))
        div_by = divs[pick-1]
        return [str(n)+" : "+str(div_by), int(n/div_by)]
    except (ValueError, IndexError):
        pass

def get_assignment():
    """
    get a random number within the user defined range, make the assignment and
    the textual presentation
    """
    n1 = randint(2, max_n); n2 = randint(2, max_n)
    assignments = [
        [str(n1)+" + "+str(n2), n1+n2],
        [str(n1)+" - "+str(n2), n1-n2],
        [str(n1)+" x "+str(n2), n1*n2],
        fix_float(n1),
        ]
    # pick an assignment (type) at random
    assignment = assignments[randint(0, 3)]
    # if the random number is a prime number and the assignment a division...
    assignment = assignment if assignment != None else assignments[1]
    # run the interface job
    try:
        answer = int(subprocess.check_output(["/bin/bash", "-c",
            'zenity --entry --title="Think hard:" --text='+'"'+assignment[0]+'"'
            ]).decode("utf-8"))
        if answer == assignment[1]:
            subprocess.Popen(["notify-send", "Coolcool"])
        else:
            subprocess.Popen([
                "notify-send", "Oooops, "+assignment[0]+\
                " = "+str(assignment[1])])
    except (subprocess.CalledProcessError, ValueError):
        pass

while True:
    time.sleep(pause)
    get_assignment()

Como usar

  1. Copie o script em um arquivo vazio, salve-o como mindpractice.py
  2. Execute-o com o número máximo permitido e o tempo de intervalo (em segundos) entre as atribuições como argumentos:

    python3 /path/to/mindpractice.py <max_number> <interval>

    por exemplo

    python3 /path/to/mindpractice.py 1000 300

    fazer cálculos de até 1000, com um intervalo de 5 minutos entre as tarefas.

  3. Se tudo funcionar bem, você pode adicioná-lo aos aplicativos de inicialização da maneira usual ou pode ser feito um iniciador para alternar, que eu devo adicionar posteriormente :)

Nota

  • A divisão pode precisar de alguma explicação. Você provavelmente não gostaria de calcular em carros alegóricos. Portanto, se a atribuição for uma divisão, o script procurará os números pelos quais pode ser dividido e escolhe um (aleatoriamente). Se o número (principal) for um número primo, a atribuição será alterada para outro tipo.

2. Mais opções

Quando você começar a calcular, descobrirá que dividir até figuras de (digamos) 100 é muito mais fácil do que multiplicar figuras até 100.

Com o script abaixo, você pode (e deve) definir o número máximo de números por tipo de exercício (consulte as instruções abaixo do script).

O script

#!/usr/bin/env python3
from random import randint
import sys
import subprocess
import time

levels = sys.argv[1:]
pause = [int(arg.replace("p:", "")) for arg in levels if "p:" in arg][0]

def fix_float(n):
    """
    if the assignment is a division, the script divides the random number by a
    number (integer) it can be divided by. it looks up those numbers, and picks
    one of them (at random). if the number is a prime number the assignment is
    changed into another type
    """
    try:
        divs = [i for i in range(2, n) if n%i == 0]
        pick = randint(1, len(divs))
        div_by = divs[pick-1]
        return [str(n)+" : "+str(div_by), int(n/div_by)]
    except (ValueError, IndexError):
        pass

def get_assignment():
    """
    get a random number within the user defined range, make the assignment and
    the textual presentation
    """
    # pick an assignment (type) at random
    track = randint(0, 3)
    arg = ["a:", "s:", "m:", "d:"][track]
    max_n = [int(item.replace(arg, "")) for item in levels if arg in item][0]

    n1 = randint(2, max_n); n2 = randint(2, max_n)
    assignments = [
        [str(n1)+" + "+str(n2), n1+n2],
        [str(n1)+" - "+str(n2), n1-n2],
        [str(n1)+" x "+str(n2), n1*n2],
        fix_float(n1),
        ]
    assignment = assignments[track]     
    # if the random number is a prime number and the assignment a division...
    assignment = assignment if assignment != None else assignments[1]
    # run the interface job
    try:
        answer = int(subprocess.check_output(["/bin/bash", "-c",
            'zenity --entry --title="Think hard:" --text='+'"'+assignment[0]+'"'
            ]).decode("utf-8"))
        if answer == assignment[1]:
            subprocess.Popen(["notify-send", "Coolcool"])
        else:
            subprocess.Popen([
                "notify-send", "Oooops, "+assignment[0]+\
                " = "+str(assignment[1])])
    except (subprocess.CalledProcessError, ValueError):
        pass

while True:
    time.sleep(pause)
    get_assignment()

Como usar

  • Configure o script exatamente como o primeiro, mas execute-o com os argumentos (em qualquer ordem, o script vinculará os argumentos corretos ao item certo):

    • p: pausa (intervalo entre as atribuições, em segundos))
    • s: subtrair (número máximo com o qual calcular)
    • a: adicionar (número máximo)
    • m: multiplicar (número máximo)
    • d: dividir (número máximo)

    Por exemplo:

    python3 '/home/jacob/Desktop/num.py' a:10 d:100 s:10 m:10 p:300

    para mostrar um exercício a cada cinco minutos, números até 10, exceto a divisão até a figura 100.


3. Vamos nos deixar levar um pouco

Ser capaz de ver algumas estatísticas

A versão abaixo mostra as estatísticas após cada 10 exercícios:

insira a descrição da imagem aqui

Além disso (pode ser útil quando usado em crianças), você pode ver o que deu errado nos últimos 100 exercícios respondidos incorretamente. Em um arquivo oculto, as atribuições e suas respostas (incorretas) são gravadas:

insira a descrição da imagem aqui

Este arquivo de log está localizado:

~/.calculog

O script

#!/usr/bin/env python3
from random import randint
import sys
import subprocess
import time
import os

log = os.environ["HOME"]+"/.calculog"

levels = sys.argv[1:]
pause = [int(arg.replace("p:", "")) for arg in levels if "p:" in arg][0]

def fix_float(n):
    """
    if the assignment is a division, the script divides the random number by a
    number (integer) it can be divided by. it looks up those numbers, and picks
    one of them (at random). if the number is a prime number the assignment is
    changed into another type
    """
    try:
        divs = [i for i in range(2, n) if n%i == 0]
        pick = randint(1, len(divs))
        div_by = divs[pick-1]
        return [str(n)+" : "+str(div_by), int(n/div_by)]
    except (ValueError, IndexError):
        pass

def get_assignment():
    """
    get a random number within the user defined range, make the assignment and
    the textual presentation
    """
    # pick an assignment (type) at random
    track = randint(0, 3)
    arg = ["a:", "s:", "m:", "d:"][track]
    max_n = [int(item.replace(arg, "")) for item in levels if arg in item][0]

    n1 = randint(2, max_n); n2 = randint(2, max_n)
    assignments = [
        [str(n1)+" + "+str(n2), n1+n2],
        [str(n1)+" - "+str(n2), n1-n2],
        [str(n1)+" x "+str(n2), n1*n2],
        fix_float(n1),
        ]
    assignment = assignments[track]     
    # if the random number is a prime number and the assignment a division...
    assignment = assignment if assignment != None else assignments[1]
    # run the interface job
    try:
        answer = int(subprocess.check_output(["/bin/bash", "-c",
            'zenity --entry --title="Think hard:" --text='+'"'+assignment[0]+'"'
            ]).decode("utf-8"))
        if answer == assignment[1]:
            subprocess.Popen(["notify-send", "Coolcool"])
            return "ok"
        else:
            subprocess.Popen([
                "notify-send", "Oooops, "+assignment[0]+\
                " = "+str(assignment[1])])
            open(log, "+a").write(assignment[0]+"\t\t"+str(answer)+"\n")
            try:
                history = open(log).read().splitlines()
                open(log, "wt").write(("\n").join(history[-100:])+"\n")     
            except FileNotFoundError:
                pass 
            return "mistake"
    except (subprocess.CalledProcessError, ValueError):
        return None

results = []
while True:
    time.sleep(pause)
    results.append(get_assignment())
    if len(results) >= 10:
        score = results.count("ok")
        subprocess.call([
            "zenity", "--info",
            '--title=Latest scores',
            '--text='+str(score)+' out of 10',
            '--width=160',
            ])
        results = []

Como usar

O uso é exatamente igual à opção 2, mas você terá o arquivo de log disponível e as pontuações após cada 10 atribuições.


4. versão final

A versão abaixo é como a opção 3 (incluindo arquivos de log e relatórios), mas possui alguns recursos adicionais:

  • adiciona o cálculo da raiz quadrada

    insira a descrição da imagem aqui

  • adiciona usando um intervalo de números, em vez de simplesmente definir um número máximo

  • adiciona a opção para executar apenas tipos de cálculo específicos (por exemplo, apenas dividir e multiplicar).
  • lembra os argumentos em que foi executado pela última vez, quando executado sem argumentos (somente na primeira vez, os argumentos devem ser definidos). Se nenhum argumento foi definido na primeira execução, o script envia uma mensagem:

    insira a descrição da imagem aqui

O script

#!/usr/bin/env python3
from random import randint
import sys
import subprocess
import time
import os

"""
Use this script to practice head count. Some explanation might be needed:
The script can be used for the following types of calculating:

Type          argument example      explanation
-------------------------------------------------------------------------------
add           a:30-100              to add in numbers from 30-100
subtract      s:10-100              to subtract in numbers from 10-100
multiply      m:10-20               to multiply in numbers from 10-20
divide        d:200-400             to divide in numbers from 200-400
square root   r:1-1000              to find square root in numbers from 1-1000

N.B.
-------------------------------------------------------------------------------
- The argument p: (pause in seconds; break between the assignments) *must* be
  set, for example: p:300 to launch an assignment every 5 minutes
- A calculation type will only run *if* the argument is set for the
  corresponding type. An example: python3 /path/to/script p:60 s:30-60
  will run a subtract- assignment every minute.

Miscellaneous information:
-------------------------------------------------------------------------------
- On first run, arguments *must* be set. After first run, when no arguments
  are used the last set arguments will run, until the script is run with a new
  set of arguments.
- A log file of the last 100 incorrectly answered questions is kept in
  ~/.calculog
- After 10 assignments, the score of the last 10 pops up.
"""

log = os.environ["HOME"]+"/.calculog"
prefs = os.environ["HOME"]+"/.calcuprefs"
levels = sys.argv[1:]

if levels:
    open(prefs, "wt").write(str(levels))
else:
    try:
        levels = eval(open(prefs).read())
    except FileNotFoundError:
        subprocess.call([
            "zenity", "--info",
            '--title=Missing arguments',
            '--text=On first run, the script needs to be run with arguments\n'
            ])

def fix_float(n):
    """
    if the assignment is a division, the script divides the random number by a
    number (integer) it can be divided by. it looks up those numbers, and picks
    one of them (at random). if the number is a prime number the assignment is
    changed into another type
    """
    try:
        divs = [i for i in range(2, n) if n%i == 0]
        pick = randint(1, len(divs))
        div_by = divs[pick-1]
        return [str(n)+" : "+str(div_by), int(n/div_by)]
    except (ValueError, IndexError):
        pass

def fix_sqr(f1, f2):
    """
    If the assignment is calculating a square root, this function finds the sets
    of numbers (integers) that make a couple, within the given range.
    """
    q = f1; r = q**(.5); sets = []
    while q < f2:
        r = q**(.5)
        if r == int(r):
            sets.append([int(r), int(q)])
        q = q+1
    if sets:
        pick = sets[randint(0, len(sets)-1)]
        return ["√"+str(pick[1]), pick[0]]

def get_assignment():
    """
    get a random number within the user defined range, make the assignment and
    the textual presentation
    """ 
    args = ["a:", "s:", "m:", "d:", "r:"]
    indc = []
    for i, item in enumerate(args):
        if item in str(levels):
            indc.append(i)

    index = indc[randint(0, len(indc)-1)]
    name = args[index]

    minmax = [
        [int(n) for n in item.replace(name, "").split("-")] \
        for item in levels if name in item][0]

    assignment = None
    # if the random number is a prime number *and* the assignment a division 
    # or a square root...
    while assignment == None:
        n1 = randint(minmax[0], minmax[1]); n2 = randint(minmax[0], minmax[1])
        assignment = [
            [str(n1)+" + "+str(n2), n1+n2],
            [str(n1)+" - "+str(n2), n1-n2],
            [str(n1)+" x "+str(n2), n1*n2],
            fix_float(n1),
            fix_sqr(minmax[0], minmax[1]),
            ][index]
    # run the interface job
    try:
        answer = int(subprocess.check_output(["/bin/bash", "-c",
            'zenity --entry --title="Think hard:" --text='+'"'+assignment[0]+'"'
            ]).decode("utf-8"))
        if answer == assignment[1]:
            subprocess.Popen(["notify-send", "Coolcool"])
            return "ok"
        else:
            subprocess.Popen([
                "notify-send", "Oooops, "+assignment[0]+\
                " = "+str(assignment[1])])
            open(log, "+a").write(assignment[0]+"\t\t"+str(answer)+"\n")
            try:
                history = open(log).read().splitlines()
                open(log, "wt").write(("\n").join(history[-100:])+"\n")     
            except FileNotFoundError:
                pass 
            return "mistake"
    except (subprocess.CalledProcessError, ValueError):
        return None

if levels:
    pause = [int(arg.replace("p:", "")) for arg in levels if "p:" in arg][0]
    [levels.remove(item) for item in levels if "p:" in item]
    results = []
    while True:
        time.sleep(pause)
        results.append(get_assignment())
        if len(results) >= 10:
            score = results.count("ok")
            subprocess.call([
                "zenity", "--info",
                '--title=Latest scores',
                '--text='+str(score)+' out of 10',
                '--width=160',
                ])
            results = []

Como usar

  • Copie o script para um arquivo vazio, salve-o (novamente) como mindpractice.py. Execute-o com as seguintes opções (como exemplos)

    Deve ser definido:

    p:300                to set the interval between assignments to 5 minutes

    Opcional (faça uma seleção):

    a:30-100             to add in numbers from 30-100 (optional)
    s:10-100             to subtract in numbers from 10-100
    m:10-20              to multiply in numbers from 10-20
    d:200-400            to divide in numbers from 200-400
    r:1-1000             to find square root in numbers from 1-1000
    
  • Comando de exemplo:

    python3 '/path/to/mindpractice.py' p:300 d:10-100 s:10-30  r:300-600

    pôr:

    p:300                to set the interval between assignments to 5 minutes
    d:10-100             to divide in numbers from 10-100
    s:10-30              to subtract in numbers from 10-30
    r:300-600            to calculate square roots from 300-600
    

    enquanto adicionar e multiplicar não são usados.

Da próxima vez, se o script for executado com:

python3 '/path/to/mindpractice.py'

Ele lembrará os últimos argumentos usados


Use a versão que melhor atende às suas necessidades ...


Jacob Vlijm
fonte
Esta versão está funcionando muito bem até agora. Muito obrigado!
precisa saber é
11
@orschiro adicionou uma versão estendida, para diferenciar a dificuldade.
Jacob Vlijm
o arquivo de log é uma ótima idéia! Atualmente, estou tentando entender algumas das multiplicações e divisões de três dígitos. Eles não são tão diretos. :)
orschiro
apenas uma idéia: Às vezes, estou tão focado no trabalho que ignoro a Think Hardjanela para terminar o trabalho antes (por exemplo, terminar de escrever uma frase). Eu então esqueço a janela. Seria possível que, após 5 minutos, a Think Hardjanela recupere o foco automaticamente?
Orschiro
11
@orschiro absolutamente! Eu também ainda estava mastigando uma versão completamente GUI (não há necessidade de definir nada na linha de comando, nem mesmo na primeira execução), mas não tenho certeza de que eles permitirão adicionar mais medidores à resposta :)
Jacob Vlijm
3

Introdução:

O aplicativo a seguir produz expressões inteiras aleatórias para serem avaliadas pelo usuário. O intervalo de expressões geradas aleatoriamente depende das configurações do usuário na janela pop-up principal. Ao clicar no Lets Beginbotão, a sessão inicia indefinidamente, até o usuário clicar no botão Cancelar.

insira a descrição da imagem aqui

insira a descrição da imagem aqui

Código fonte:

#!/usr/bin/env python

# Author: Serg Kolo
# Date: Jan 30,2016
# Purpose: A graphical utility for practicing
#          random arithmetic operations
# Written for: http://askubuntu.com/q/725287/295286

#    Copyright: Serg Kolo , 2016
#    This program is free software: you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation, either version 3 of the License, or
#    (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.

import sys
import time
import random
from PyQt4 import QtGui


class mathApp(QtGui.QWidget):
   def __init__(self):
       super(mathApp,self).__init__()
       self.mainMenu()

   def mainMenu(self):
      self.setGeometry(300, 300, 400, 200)

      self.btn = QtGui.QPushButton("Let's begin",self)
      self.btn.move(20,150)
      self.btn.clicked.connect(self.askQuestions)

      self.lbl1 = QtGui.QLabel(self)
      self.lbl1.move(20,25)
      self.lbl1.setText("Numbers From")


      self.lbl2 = QtGui.QLabel(self)
      self.lbl2.move(20,55)
      self.lbl2.setText("Numbers To")

      self.lbl2 = QtGui.QLabel(self)
      self.lbl2.move(20,85)
      self.lbl2.setText("Repeat (seconds)")

      self.le1 = QtGui.QLineEdit(self)
      self.le1.move(150,20)

      self.le2 = QtGui.QLineEdit(self)
      self.le2.move(150,50)

      self.le3 = QtGui.QLineEdit(self)
      self.le3.move(150,80)

      self.lbl3 = QtGui.QLabel(self)
      self.lbl3.move(20,105)

      self.setWindowTitle('Random Integer Arithmetic')

      self.show()

   def askQuestions(self):
       rangeStart = int(self.le1.text())
       rangeEnd = int(self.le2.text())
       sleepTime = int(self.le3.text())
       done=False
       while not done:
          self.show()
          expression = self.generateOperation(rangeStart,rangeEnd)
          correctAnswer = eval(expression)

          prompt = QtGui.QInputDialog() 
          text,ok = prompt.getText(self,"Don't think too hard",expression) 
          if ok:
             if int(text) == correctAnswer:                
                self.showAnswer("CORRECT,YOU ROCK !")
             else :
                self.showAnswer("Nope");
          else:
              done=True

          if done==True:
              self.close()
          time.sleep(sleepTime)


   def generateOperation(self,start,end):
      a = random.randint(start,end)
      b = random.randint(start,end)
      oplist = ['+','-','/','*']
      op = oplist[random.randint(0,3)]
      expr = str(a) + op + str(b) + ''
      return expr

   def showAnswer(self,result):
       popup = QtGui.QMessageBox()
       popup.setText(result)
       popup.exec_()


def main():
   root = QtGui.QApplication(sys.argv)
   app = mathApp()
   sys.exit(root.exec_())

if __name__ == '__main__':
   main()
Sergiy Kolodyazhnyy
fonte
Caro @Serg, também quero agradecer pessoalmente por sua versão estendida da GUI. Uma pergunta, eu apenas fiz o exercício 15/14 = 1. Não tenho certeza de quão útil é esse exercício. O que você acha?
orschiro 31/01
@orschiro é isso integer arithmetic. Isso significa que o resultado é apenas uma parte inteira, sem resto. Se você quiser, eu poderia tentar implementar decimalaritmética também. Além disso, deixe-me saber que tipo de outras opções você gostaria que eu implementasse e adicionasse. Atualmente, estou tentando praticar o agile developmentmétodo, e a comunicação com o cliente é fundamental nesse método. Por favor deixe-me saber.
Sergiy Kolodyazhnyy 31/01
que bom ouvir isso! Gostaria de fornecer mais feedback, por exemplo, uma melhor integração ao Ubuntu Desktop (execute o script mais em segundo plano, ou seja, minimize após a entrada do usuário). Como posso fornecer melhor feedback adicional?
precisa saber é o seguinte