Algoritmo para Validar RUT

Para validar de forma estricta el RUT, usado por ejemplo en Chile, que no permite ni puntos ni guiones, se pueden usar estos algoritmos. Los dejo en dos lenguajes javascript para validar en cliente y vb.net para validar en servidor.

 

function validar(codigo)
{
		var rut; //lng
		var bRet=false;
        var digitoControl="";//str

       try {

            bRet = false;
            codigo = codigo.toUpperCase().trim();

            var largo=parseInt(codigo.length,10);
			var ultimo=parseInt(largo-1,10);
            

            //Si tiene menos de 8 caractéres es incorrecto
            if (largo < 6 || largo > 12) { return false;}
			for(var i=0;i<ultimo;i++)
			{
				var c= codigo.charCodeAt(i);
				if (i<ultimo){if (c<48 || c>57){return false;}}
				else{if (c<48 && c>57 && c != 75){return false;}}
				
			}
           
			rut= codigo.substring(0,ultimo).toString();
            var digitoControlEsperado=codigo.substring(codigo.length-1, codigo.length).toString();
           
            digitoControl = RutDigito(rut).toString();

            if(digitoControl == digitoControlEsperado ){bRet=true;}

        }
		catch(err) {
					bRet = false;
		}
		return bRet

}

 function RutDigito(T) {
     var M=0,S=1;
     for(;T;T=Math.floor(T/10))
        S=(S+T%10*(9-M++%6))%11;
     return S?S-1:'K';
  }

Para validar con VB se puede usar este:

  Public Function VerificaRUTChile(ByVal codigo As String) As Boolean
        Dim rut As Long
        Dim bRet As Boolean
        Dim digitoControl As String

        Try

            bRet = False
            codigo = codigo.Trim.ToUpper

            Dim largo As Integer = codigo.Length
            Dim penultimo As Integer = largo - 2
            Dim ultimo As Integer = largo - 1

            'Si tiene menos de 8 caractéres es incorrecto
            If (largo < 6 Or largo > 12) Then Return False

            For i As Integer = 0 To ultimo
                Dim c As Char = CChar(codigo.Substring(i, 1))

                If i < ultimo Then
                    'Solo admite numeros antes del ultimo caracter
                    If Asc(c) < 48 Or Asc(c) > 57 Then Return False
                Else
                    'Solo admite numeros o K mayúscula en el digito de control.
                    If (Asc(c) < 48 And Asc(c) > 57) And (Asc(c) <> 75) Then Return False 'K
                End If

            Next

            rut = CType(codigo.Substring(0, codigo.Length - 1), Long)
            Dim digitoControlEsperado As String = Right(codigo, 1)

            digitoControl = RutDigito(rut)

            If digitoControl = digitoControlEsperado Then
                bRet = True
            End If

        Catch ex As Exception
            bRet = False


        End Try
        Return bRet

    End Function

    Private Function RutDigito(ByVal Rut As Long) As String
        Dim Digito As Long
        Dim Contador As Long
        Dim Multiplo As Long
        Dim Acumulador As Long

        Contador = 2
        Acumulador = 0
        While Rut <> 0
            Multiplo = (Rut Mod 10) * Contador
            Acumulador = Acumulador + Multiplo
            Rut = Rut \ 10
            Contador = Contador + 1
            If Contador = 8 Then
                Contador = 2
            End If
        End While
        Digito = 11 - (Acumulador Mod 11)
        RutDigito = CStr(Digito)
        If Digito = 10 Then RutDigito = "K"
        If Digito = 11 Then RutDigito = "0"
    End Function

Serialización en VB.NET

Hoy he tenido un problema al intentar duplicar un vector que contenía objetos de clase.
Hiciera lo que hiciera, todas las llamadas a parametros o intentos de crear un duplicado de un elemento de un vector, de tipo clase, me encontraba el mismo problema. Me devolvía siempre un objeto por referencia y nunca por valor.

Esto me estaba dando muchos problemas, por ejemplo, si quería crear un duplicado de un único elemento, por ejemplo extraer un equipo del vector de equipos, y que fuese independiente, no me dejaba, ya que al pasarse por referencia, todos los cambios que yo hacía en el duplicado que había extraido, se estaban cambiando automáticamente en el equipo original en el vector. Lo cual era un desastre.

De modo que la forma que he encontrado, es crear un documento serializandolo, descomponiendolo en pedazos de forma automática en memoria para disponer de dicho duplicado real, y no como hasta ahora, un simple punto de referencia en memoria.

Todas las clases que se deseen serializar, deben incluir esta sentencia delante de la declaración de la clase:

&lt;Serializable()&gt;
 Public Class clsEquipos

También hace falta en los Structures.
Se puede crear una función que realice el trabajo de serialización.


Imports System
 Imports System.Collections.Generic
 Imports System.Text
 Imports System.Runtime.Serialization
 Imports System.IO
 Imports System.Runtime.Serialization.Formatters.Binary
 Namespace Utilidades

 '''
''' Realiza una clonación de un objeto de estructura compleja
 '''
Public Class clsCopiador

 Public Shared Function Duplicar(ByVal fuente)

 'Creamos un stream en memoria
 Dim formatter As IFormatter = New BinaryFormatter()
 Dim stream As Stream = New MemoryStream()

 formatter.Serialize(stream, fuente)
 stream.Seek(0, SeekOrigin.Begin)

 'Deserializamos la porción de memoria en el nuevo objeto
 Return formatter.Deserialize(stream)

 End Function
 End Class
 End Namespace

Otras opciones son mediante clones basicos y complejos.

Dejo aqui dos ejemplos, para desarrollar otro día.

Public Function ShallowCopy() As Person
       Return DirectCast(Me.MemberwiseClone(), Person)
    End Function

    Public Function DeepCopy() As Person
       Dim other As Person = DirectCast(Me.MemberwiseClone(), Person)
       other.IdInfo = New IdInfo(Me.IdInfo.IdNumber)
       Return other
    End Function

MemberwiseClone crea un clon superficial, donde solo copia el primer nivel de objetos, el resto queda por referencia. El efecto me parece desastroso.

Para hacerlo en profundidad hay que reenvíar todos los métodos, propiedades, etc, uno por uno, como se ve en DeepCopy, pero para lo que necesitaba yo, que era una copia completa y total y que no me implique tener que estar pendiente de cada mantenimiento en las propiedades, prefiero la serialización.

Nota: Tened cuidado si vais a volcar este tipo de información para hacer salvados a disco, ya que un salvado en 32 bits no lo podreis recuperar bien en uno de 64 bits y viceversa.

Dejo unas referencias para ampliar información:

Memberwise en MSDN
Memberwise en Java
Ejemplo completo en C#
Lección magistral de Guille