大力出奇迹,组合数学计算器

效果

根据排列计算不同生成算法的下一排列

分两种模式,输入排列和输入序数,由于中介数并不能保证三者中同时存在,所以懒得做了.....

目前也只做了常见的9位,懒得支持任意位。。。。(主要作业中大多是九位的)

对于速度而言,由于是在运行期间计算所有排列所以在初始加载时比较慢,可以先持久化为json文件,直接加载,查找排列时可以用高效的二分查找,缩短查找时间

数据结构方面,对于表格格式的输出,应该设置一个转换函数,将对象转为需要的格式

工具函数可以集成到一个对象中,直接调用 静态方法

工具

// 获取长度为len的所有排列,按照字典序
function getAllRange(len) {
  let a = []
  let MAX = len
  let used = new Set()
  let ALL = []

  dfs(0)

  function dfs(n) {
    if (n == MAX) {
      // console.log(a)
      ALL.push(Array.from(a))
      used.delete(a.pop())
      return
    }

    for (let i = 1; i <= MAX; i++) {
      if (!used.has(i)) {
        a.push(i)
        used.add(i)
        dfs(n + 1)
      }
    }

    used.delete(a.pop())
  }

  return ALL
}

// 阶乘
function fac(n) {
  return n < 2 ? 1 : n * fac(n - 1)
}

// 字典序中介数计算
function f1(arr) {
  let ret = []
  for (let i = 0; i < arr.length; i++) {
    let c = 0
    for (let j = i + 1; j < arr.length; j++)
      arr[j] < arr[i] ? c++ : c
    ret[i] = c
  }

  return ret.slice(0, arr.length - 1)
}

// 字典序中介数求序数
function getM1(arr) {
  return arr.reduce(
    (pre, cur, index) => pre + cur * fac(arr.length - index),
    0
  )
}

// 递增排列转中介数
function f2(arr) {
  let ret = []
  for (let i = 0; i < arr.length; i++) {
    let c = 0
    for (let j = i + 1; j < arr.length; j++)
      arr[j] < arr[i] ? c++ : c
    ret[arr[i] - 1] = c
  }

  return ret.reverse().slice(0, arr.length - 1)
}

// 递增中介数求序数
function getM2(a) {
  return a.reduce(
    (pre, cur, index) => pre + cur * fac(a.length - index),
    0
  )
}

// 递减中介数求序数
function getM3(a, len) {
  let pre = a[0]
  for (let i = 1; i < a.length; i++) {
    pre = pre * (len - a.length + 1 + i) + a[i]
  }
  return pre
}

function getData(len) {
  let data = {
    inc: {},
    dec: {},
    dic: {}
  }

  let range = getAllRange(len)
  for (let i of range) {

    // 递增的中介数和序数
    data['inc'][i.join('')] = {}
    data['inc'][i.join('')]['mid'] = parseInt(f2(i).join(''))
    data['inc'][i.join('')]['num'] = getM2(f2(i))
    data['inc'][i.join('')]['range'] = i.join('')
    // 递减
    data['dec'][i.join('')] = {}
    data['dec'][i.join('')]['mid'] = parseInt(f2(i).reverse().join(''))
    data['dec'][i.join('')]['num'] = getM3(f2(i).reverse(), len)
    data['dec'][i.join('')]['range'] = i.join('')

    // 字典
    data['dic'][i.join('')] = {}
    data['dic'][i.join('')]['mid'] = parseInt(f1(i).join(''))
    data['dic'][i.join('')]['num'] = getM1(f1(i))
    data['dic'][i.join('')]['range'] = i.join('')

  }

  return data
}

// 字典序下一个排列
function next1(arr) {
  let num = d['dic'][arr]['num']
  console.log(num + 1)
  for (let i in d['dic']) {
    if (d['dic'][i]['num'] == num + 1) {
      console.log(i)
      return {
        key: i,
        num: d['dic'][i]['num'] + 1,
        mid: d['dic'][i]['mid']
      }
    }
  }
}


let d = getData(9)

// 递增序下一个排列
function next2(arr) {
  console.log(d['inc'][arr])
  let num = 1 + d['inc'][arr]['num']
  console.log(num)

  for (let i in d['inc']) {
    if (d['inc'][i]['num'] == num) {
      console.log(i)
      return {
        key: i,
        num: d['inc'][i]['num'],
        mid: d['inc'][i]['mid']
      }
    }
  }
}

// 递减序下一个排列
function next3(arr) {
  console.log(d['dec'][arr])
  let num = 1 + d['dec'][arr]['num']
  console.log(num)

  for (let i in d['dec']) {
    if (d['dec'][i]['num'] == num) {
      console.log(i)
      return {
        key: i,
        num: d['dec'][i]['num'],
        mid: d['dec'][i]['mid']
      }
    }
  }
}

// 递增进制的加法,低位逢二进一,依次递增
function inc1(num) {
  let a = Array.from('' + num).map(cur => cur - '').reverse()
  // console.log(a);
  let c = 1
  for (let i = 0; i < a.length; i++) {
    let s = (a[i] + c)
    a[i] = s % (i + 2)
    c = Math.floor(s / (i + 2))
  }
  if (c == 1) {
    a[a.length] = 1
  }
  console.log(a);
  return parseInt(a.reverse().join(''))
}

// 递减进制的加法,低位逢九进一,依次递减
function inc2(num, len = 9) {
  let a = Array.from('' + num).map(cur => cur - '').reverse()
  // console.log(a);
  let c = 1
  for (let i = 0; i < a.length; i++) {
    let s = (a[i] + c)
    a[i] = s % (len - i)
    c = Math.floor(s / (len - i))
  }
  if (c == 1) {
    a[a.length] = 1
  }
  console.log(a);
  return parseInt(a.reverse().join(''))
}

export {
  d,
  next1,
  next2,
  next3,
}

ui

<template>
  <div class="main">
    <el-form ref="form" :model="form" label-width="80px" style="width: 300px">
      <el-form-item label="位数">
        <el-select v-model="form.len">
          <el-option v-for="i in 9" :label="i" :value="i" :key="i"></el-option>
        </el-select>
      </el-form-item>
      <el-form-item label="类型">
        <el-select v-model="form.type">
          <el-option label="序数" :value="0"></el-option>
          <!--<el-option label="中介数" :value="1"></el-option>-->
          <el-option label="排列" :value="2"></el-option>
        </el-select>
      </el-form-item>
      <el-form-item label="数据">
        <el-input v-model="form.input" placeholder="请输入数据" @keyup.enter.native="onSubmit"></el-input>
      </el-form-item>
      <el-form-item>
        <el-button type="primary" @click="onSubmit">submit</el-button>
      </el-form-item>
    </el-form>

    <table class="table table-bordered table-striped  " style="width: 800px;text-align: center">
      <thead>
      <tr>
        <th></th>
        <th>增序</th>
        <th>逆序</th>
        <th>字典序</th>
      </tr>
      </thead>
      <tbody>
      <tr v-for="i,index in tableData">
        <th scope="row">{{cols[index]}}</th>
        <td>{{tableData[index][0]}}</td>
        <td>{{tableData[index][1]}}</td>
        <td>{{tableData[index][2]}}</td>
      </tr>
      </tbody>
    </table>
  </div>
</template>

<script>
  import {next1, next2, next3, d} from '../util'
  import 'bootstrap/dist/css/bootstrap.css'

  export default {
    name: "main-view",

    methods: {
      // 对应不同类型的处理函数,返回一个对象
      f0() {
        // 输入的是序数 232450
        let cur_inc, cur_dec, cur_dic
        let next_inc, next_dec, next_dic
        for (let i in d['inc']) {
          if (d['inc'][i]['num'] == this.form.input) {
            cur_inc = d['inc'][i]
            break
          }
        }

        for (let i in d['dec']) {
          if (d['dec'][i]['num'] == this.form.input) {
            cur_dec = d['dec'][i]
            break
          }
        }
        for (let i in d['dic']) {
          if (d['inc'][i]['num'] == this.form.input) {
            cur_dic = d['dic'][i]
            break
          }
        }

        for (let i in d['inc']) {
          if (d['inc'][i]['num'] == cur_inc['num'] + 1) {
            next_inc = d['inc'][i]
            break
          }
        }

        for (let i in d['dec']) {
          if (d['dec'][i]['num'] == cur_dec['num'] + 1) {
            next_dec = d['dec'][i]
            break
          }
        }
        for (let i in d['dic']) {
          if (d['dic'][i]['num'] == cur_dic['num'] + 1) {
            next_dic = d['dic'][i]
            break
          }
        }
        return [
          [cur_inc['num'], cur_dec['num'], cur_dic['num']],
          [cur_inc['mid'], cur_dec['mid'], cur_dic['mid']],
          [cur_inc.range, cur_dec.range, cur_dic.range],
          [next_inc['num'], next_dec.num, next_dic.num],
          [next_inc.mid, next_dec.mid, next_dic.mid],
          [next_inc.range, next_dec.range, next_dic.range],
        ]
      },
      f1() {
        // 输入的是中介数

      },
      f2() {
        // 输入的是排列  //632589714

        let cur_inc = d['inc'][this.form.input]
        let cur_dec = d['dec'][this.form.input]
        let cur_dic = d['dic'][this.form.input]
        let next_inc, next_dec, next_dic
        for (let i in d['inc']) {
          if (d['inc'][i]['num'] == cur_inc['num'] + 1) {
            next_inc = d['inc'][i]
            break
          }
        }

        for (let i in d['dec']) {
          if (d['dec'][i]['num'] == cur_dec['num'] + 1) {
            next_dec = d['dec'][i]
            break
          }
        }
        for (let i in d['dic']) {
          if (d['dic'][i]['num'] == cur_dic['num'] + 1) {
            next_dic = d['dic'][i]
            break
          }
        }
        return [
          [cur_inc['num'], cur_dec['num'], cur_dic['num']],
          [cur_inc['mid'], cur_dec['mid'], cur_dic['mid']],
          [cur_inc.range, cur_dec.range, cur_dic.range],
          [next_inc['num'], next_dec.num, next_dic.num],
          [next_inc.mid, next_dec.mid, next_dic.mid],
          [next_inc.range, next_dec.range, next_dic.range],
        ]
      },
      // 执行查询显示结果
      onSubmit() {
        this.tableData = [this.f0, this.f1, this.f2][this.form.type]()
      }
    },
    data() {
      return {
        cols: ['当前序数', '当前中介数', '当前排序', '下一序数', '下一中介数', '下一排序'],
        form: {
          len: 9,
          type: 2,
          input: ''
        },
        tableData: Array(6).fill([]),
      }
    }
  }
</script>

<style scoped>
  .main {
    width: 100vw;
    height: 100vh;
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
  }
</style>

猜你喜欢

转载自my.oschina.net/ahaoboy/blog/1807251