¿Hay algún software que periódicamente me permita hacer ejercicios de cálculo mental?

9

Soy consciente de mi naturaleza perezosa y de vez en cuando necesito esforzarme para hacer algo de cálculo mental básico. Por lo tanto, estoy buscando un software que periódicamente me pida que haga un breve ejercicio de cálculo mental (más, menos, multiplicar, dividir).

Criterios

  • Debería permitirme personalizar el intervalo de tiempo
  • Debe integrarse en el escritorio de Ubuntu, es decir, estar oculto en el fondo y solo aparecer (emergente) durante el tiempo de ejercicio
orschiro
fuente
2
Dudo que dicho software exista, pero podría crearse muy fácilmente con un script de shell o python. Mañana cocinaré algo, por favor recuérdame
Sergiy Kolodyazhnyy
Sí, bsdgames tiene aritmética y demás, pero tendrías que automatizar las ventanas emergentes periódicas tú mismo.
mchid
Estimado @Serg, te recuerdo amablemente tu experimento de cocina. :)
orschiro
1
Así que publiqué una respuesta en progreso, que editaré a medida que avance. Eche un vistazo, dígame qué piensa, qué funcionalidad agregar o quitar. Hasta ahora, esta es una aplicación de consola, pero eventualmente se convertirá en una pequeña ventana emergente.
Sergiy Kolodyazhnyy
2
¡Resulta ser una buena pregunta para trabajar!
Jacob Vlijm

Respuestas:

8

1. Versión sencilla

El siguiente script producirá asignaciones al azar, + , - , × y ÷ . Puede (y debe) establecer un número máximo que el script puede usar, así como el intervalo de tiempo entre las asignaciones.

Las tareas

Las tareas se presentan en una ventana de entrada de Zenity:

ingrese la descripción de la imagen aquí

Si la respuesta es incorrecta:

ingrese la descripción de la imagen aquí

Si la respuesta es correcta:

ingrese la descripción de la imagen aquí

La secuencia de comandos

#!/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()

Cómo utilizar

  1. Copie el script en un archivo vacío, guárdelo como mindpractice.py
  2. Ejecútelo con el número máximo permitido y el tiempo de intervalo (en segundos) entre las asignaciones como argumentos:

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

    p.ej

    python3 /path/to/mindpractice.py 1000 300

    hacer cálculos hasta cifras de 1000, con un descanso de 5 minutos entre las tareas.

  3. Si todo funciona bien, puede agregarlo a las aplicaciones de inicio de la manera habitual, o puede crear un iniciador para alternar, que podría agregar más tarde :)

Nota

  • La división podría necesitar alguna explicación. Probablemente no le gustaría calcular en carrozas. Por lo tanto, si la asignación es una división, el script busca los números por los que se puede dividir y elige uno (al azar). Si el número (principal) resulta ser un número primo, la asignación se cambia a otro tipo.

2. Más opciones

Una vez que comience a calcular, descubrirá que dividir hasta cifras de (digamos) 100 es mucho más fácil que multiplicar cifras hasta 100.

Con la secuencia de comandos a continuación, puede (y debe) establecer el máximo de números por tipo de ejercicio (consulte las instrucciones debajo de la secuencia de comandos).

La secuencia de comandos

#!/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()

Cómo utilizar

  • Configure el script exactamente como el primero, pero ejecútelo con los argumentos (en cualquier orden, el script vinculará los argumentos correctos con el elemento correcto):

    • p: pausa (pausa entre las asignaciones, en segundos))
    • s: restar (número máximo para calcular con)
    • a: agregar (número máximo)
    • m: multiplicar (número máximo)
    • d: dividir (número máximo)

    Por ejemplo:

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

    para mostrar un ejercicio cada cinco minutos, números hasta 10, excepto dividir hasta la cifra 100.


3. Dejémonos llevar un poco

Poder ver algunas estadísticas

La siguiente versión muestra las estadísticas después de cada 10 ejercicios:

ingrese la descripción de la imagen aquí

Además (puede ser útil cuando se usa para niños), puede ver qué salió mal en los últimos 100 ejercicios respondidos incorrectamente. En un archivo oculto, se escriben tanto las tareas como sus respuestas (incorrectas):

ingrese la descripción de la imagen aquí

Este archivo de registro se encuentra:

~/.calculog

La secuencia de comandos

#!/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 = []

Cómo utilizar

El uso es casi exactamente como la opción 2, pero tendrá el archivo de registro disponible y los puntajes después de cada 10 tareas.


4. Versión definitiva

La siguiente versión es como la opción 3 (incluido el archivo de registro y los informes), pero tiene algunas características adicionales:

  • agrega cálculo de raíz cuadrada

    ingrese la descripción de la imagen aquí

  • agrega usando un rango de números, en lugar de simplemente establecer un máximo

  • agrega la opción de ejecutar solo tipos de cálculo específicos (por ejemplo, solo dividir y multiplicar).
  • recuerda los argumentos con los que se ejecutó la última vez, cuando se ejecutó sin argumentos (solo la primera vez, se deben establecer los argumentos ). Si no se establecieron argumentos en la primera ejecución, el script envía un mensaje:

    ingrese la descripción de la imagen aquí

La secuencia de comandos

#!/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 = []

Cómo utilizar

  • Copie el script en un archivo vacío, guárdelo (nuevamente) como mindpractice.py. Ejecútelo con las siguientes opciones (como ejemplos)

    Se debe establecer:

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

    Opcional (haga una selección):

    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 ejemplo:

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

    para establecer:

    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

    mientras que sumar y multiplicar no se usan.

Luego, la próxima vez, si el script se ejecuta con:

python3 '/path/to/mindpractice.py'

Recordará los últimos argumentos utilizados


Use la versión que mejor satisfaga sus necesidades ...


Jacob Vlijm
fuente
Esta versión está funcionando muy bien hasta ahora. Muchas gracias!
orschiro
1
@orschiro agregó una versión extendida, para diferenciar la dificultad.
Jacob Vlijm
¡El archivo de registro es una muy buena idea! Actualmente estoy tratando de entender algunas de las multiplicaciones y divisiones de tres dígitos. No son tan sencillos. :)
orschiro
solo una idea: a veces estoy tan concentrado en el trabajo que ignoro la Think Hardventana para terminar el trabajo antes (por ejemplo, terminar de escribir una oración). Entonces me olvido de la ventana. ¿Sería posible que después de 5 minutos, la Think Hardventana recupere automáticamente el foco?
orschiro
1
@orschiro absolutamente! También seguía masticando una versión completamente GUI (no es necesario configurar nada desde la línea de comandos, ni siquiera la primera ejecución), pero no estoy seguro de que nos permitan agregar más medidores a la respuesta :)
Jacob Vlijm
3

Introducción:

La siguiente aplicación produce expresiones enteras aleatorias para ser evaluadas por el usuario. El rango de expresiones generadas aleatoriamente depende de la configuración del usuario en la ventana emergente principal. Al hacer clic en el Lets Beginbotón, la sesión comienza indefinidamente, hasta que el usuario presiona el botón Cancelar.

ingrese la descripción de la imagen aquí

ingrese la descripción de la imagen aquí

Código fuente:

#!/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
fuente
Estimado @Serg, también quiero agradecerle personalmente por su versión extendida de GUI. Una pregunta, acabo de hacer el ejercicio 15/14 = 1. No estoy seguro de lo útil que es este ejercicio. ¿Qué piensas?
orschiro
@orschiro esto es integer arithmetic. Eso significa que el resultado es solo una parte, no el resto. Si lo desea, podría intentar implementar la decimalaritmética también. Además, avíseme qué tipo de otras opciones le gustaría que implemente y agregue. Actualmente, estoy tratando de practicar el agile developmentmétodo, y la comunicación con el cliente es clave en dicho método. Por favor hagamelo saber.
Sergiy Kolodyazhnyy
¡es bueno oir eso! Me encantaría brindarle más comentarios, por ejemplo, una mejor integración en el escritorio de Ubuntu (ejecute el script más en segundo plano, es decir, minimice después de la entrada del usuario). ¿Cómo puedo proporcionarle más comentarios?
orschiro